# AI Brand Visibility Tracker: ChatGPT, Perplexity, Gemini (`ostrata/ai-search-visibility`) Actor

AI search visibility & brand visibility tracker for GEO / AEO: run your prompts on ChatGPT, Perplexity and Gemini with web search, via official APIs and your own keys. Get brand mentions, rank position, competitors, cited URLs and share of voice in AI answers. MCP-ready.

- **URL**: https://apify.com/ostrata/ai-search-visibility.md
- **Developed by:** [Ostrata](https://apify.com/ostrata) (community)
- **Categories:** AI, SEO tools, Marketing
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 prompt checks

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## AI Brand Visibility Tracker: ChatGPT, Perplexity, Gemini

**Does ChatGPT recommend you? Does Perplexity cite your site? Does Gemini list your competitors instead?**
Give this Actor your brand, your competitors and the questions your customers ask. It runs each prompt on **ChatGPT (OpenAI web search)**, **Perplexity** and **Gemini (Grounding with Google Search)** through their **official APIs, with your own API keys**, and tells you for every answer:

**Also known as:** AI brand visibility tracker, ChatGPT rank tracker, Perplexity rank tracker, Gemini brand monitoring, LLM visibility, GEO tracker (generative engine optimization), AEO (answer engine optimization), brand mentions in ChatGPT, AI share of voice.

- ✅ whether your **brand is mentioned** (name, aliases or domain) and how many times
- 🥇 your **position** among all brands named in the answer (1 = named first)
- 🔗 whether **your website is cited** as a source, and at which rank
- 🆚 which **competitors** are mentioned / cited, and their positions
- 🌐 every **cited URL and domain**, plus the search queries the engine ran
- 📊 a run **summary**: mention rate, citation rate, average position, **share of voice** vs competitors, top cited domains, and the prompts where you are missing, overall and per engine

Use it for GEO / AEO (generative engine optimization), brand monitoring in AI assistants, competitor benchmarking, and to find which pages AI engines trust in your niche. Schedule it weekly to track progress.

> **Status:** Gemini path live-tested (search + citations); OpenAI/Perplexity built to official docs. Gemini free-tier keys don't include Google Search grounding: link billing to your AI Studio project (paid tier includes 5,000 free searches/month).

### Your keys, official APIs only

- The Actor **never uses its own AI keys**. You paste your OpenAI, Perplexity and/or Gemini key; they are **secret inputs** (encrypted by Apify, hidden in the UI and logs) and are sent only to the provider's official endpoint:
  - `api.openai.com/v1/responses` with the `web_search` tool
  - `api.perplexity.ai/v1/agent` (Agent API, the successor of Sonar; `fast` preset by default)
  - `generativelanguage.googleapis.com` `generateContent` with the `google_search` tool
- No scraping of chatgpt.com, perplexity.ai or Google pages. No browser, no login, no ToS grey zone.
- The AI providers bill **your** account for tokens / searches (typically a fraction of a cent to a few cents per prompt depending on the model). Keys are never written to the dataset, logs or summary; error messages are scrubbed.
- Engines without a key are skipped automatically, so you can start with just one.

### Input

| Field | Example | Notes |
|---|---|---|
| `brand` | `Ostrata` | Required |
| `brandAliases` | `["EU Company Check"]` | Other names that count as a mention |
| `brandDomains` | `["ostrata.io"]` | Detects citations of your site |
| `competitors` | `["Kyckr \| kyckr.com", "Creditsafe"]` | `Name` or `Name \| domain` |
| `prompts` | `["Best KYB API for EU companies?"]` | Required |
| `engines` | `["openai","perplexity","gemini"]` | |
| `openaiApiKey`, `perplexityApiKey`, `geminiApiKey` | | Secret. At least one |
| `openaiModel` / `perplexityModel` / `geminiModel` | `gpt-4.1-mini` / `fast` / `gemini-3.5-flash-lite` | Any model with web search |
| `country` | `FR` | Approximate user location for OpenAI search |
| `forceWebSearch` | `true` | Make OpenAI search before answering |
| `runsPerPrompt` | `1`–`5` | AI answers vary: repeat to measure frequency |

```json
{
  "brand": "Ostrata",
  "brandDomains": ["ostrata.io"],
  "competitors": ["Kyckr | kyckr.com", "Creditsafe | creditsafe.com"],
  "prompts": ["What is the best API to verify European companies (KYB)?"],
  "engines": ["openai", "gemini"],
  "openaiApiKey": "sk-...",
  "geminiApiKey": "AIza..."
}
```

### Output

One dataset row per prompt × engine (× run):

```json
{
  "prompt": "What is the best API to verify European companies (KYB)?",
  "engine": "openai",
  "model": "gpt-4.1-mini-2025-04-14",
  "status": "ok",
  "brandVisible": true,
  "brandMentioned": true,
  "brandMentionCount": 2,
  "brandPosition": 2,
  "brandCited": true,
  "brandCitationRank": 2,
  "competitorsMentioned": [
    { "name": "Kyckr", "mentioned": true, "mentionCount": 3, "position": 1, "cited": true, "citationRank": 1 },
    { "name": "Creditsafe", "mentioned": true, "mentionCount": 1, "position": 3, "cited": false, "citationRank": null }
  ],
  "citedUrls": [
    { "rank": 1, "url": "https://www.kyckr.com/", "title": "Kyckr", "domain": "kyckr.com", "isBrand": false },
    { "rank": 2, "url": "https://ostrata.io/kyb", "title": "Ostrata KYB", "domain": "ostrata.io", "isBrand": true }
  ],
  "citedDomains": ["kyckr.com", "ostrata.io"],
  "searchQueries": ["best KYB API Europe"],
  "answerText": "Top options for EU company verification: ...",
  "checkedAt": "2026-10-19T09:00:00.000Z"
}
```

The `SUMMARY` record (key-value store) aggregates everything:

```json
{
  "brand": "Ostrata",
  "overall": { "checks": 20, "brandMentionRate": 0.45, "brandCitationRate": 0.3, "brandVisibilityRate": 0.5, "avgBrandPosition": 2.1,
               "shareOfVoice": { "Ostrata": 0.28, "Kyckr": 0.41, "Creditsafe": 0.31 }, "topCitedDomains": [{ "domain": "g2.com", "count": 9 }] },
  "byEngine": { "openai": { "...": "..." }, "perplexity": { "...": "..." }, "gemini": { "...": "..." } },
  "promptsWhereBrandMissing": ["..."]
}
```

How it's measured: mentions are case-insensitive whole-word matches of the brand name, aliases and domains (URLs inside markdown links are not counted twice). Position = order of first mention among your brand and the competitors you listed. A check is **visible** if the brand is mentioned or your domain is cited.

### Pricing (pay per event)

| Event | Price |
|---|---|
| `prompt-check`: one prompt answered by one engine and analyzed | **$0.02** |

**Not charged:** API errors (bad key, quota, rate limit, timeout, empty or blocked answer), skipped engines. 10 prompts × 3 engines = 30 checks = $0.60 (plus what your AI providers bill you).
The run stops exactly at your **maximum cost per run**, and the Actor checks the budget *before* calling your API, so it never spends your AI credits on a check it cannot deliver.

### Use with AI agents (MCP)

Available through the Apify MCP server (`https://mcp.apify.com`), e.g. "check whether Perplexity and ChatGPT recommend our brand for these 5 questions and list the sources they cite".

### Limitations

- API answers are close to, but not identical with, what a logged-in user sees in the ChatGPT, Perplexity or Gemini apps (personalization, memory, app-specific models). Use `runsPerPrompt` to smooth out randomness.
- Mention detection is lexical; a very generic brand name (e.g. "Apple" in a fruit question) can produce false positives. Add aliases or domains to make it precise.
- Gemini returns redirect links; they are resolved to the real URL with one lightweight request each (`resolveGeminiUrls`).
- Your API tier's rate limits apply; 429s are retried with backoff and never charged.
- Gemini: Grounding with Google Search is not part of the Gemini API free tier for Gemini 3+ models. Use a key from a Google AI Studio project with billing linked (the paid tier includes 5,000 free search requests per month); a free-tier key returns a quota error, which is never charged.

### Privacy

Only your prompts are sent, and only to the providers you chose with your keys. The Actor stores no personal data. Answers are kept in your own Apify dataset.

### Related Actors

- [EU Company Verification (KYB)](https://apify.com/ostrata/eu-company-check): verify companies from a name, SIREN/SIRET, VAT number or LEI (register status, VIES VAT, BODACC insolvency, LEI).
- [Website to Company (Impressum & Mentions Légales)](https://apify.com/ostrata/website-company-check): find the legal entity behind a website (SIREN/VAT from the legal notice) and verify it.
- [France Company List (SIRENE)](https://apify.com/ostrata/france-company-list): build lists of French companies by NAF code, area, headcount and revenue from the official register.
- [Greenhouse, Lever & Ashby Jobs API](https://apify.com/ostrata/ats-jobs-api): normalized job postings from Greenhouse, Lever, Ashby, Workable, SmartRecruiters and Recruitee boards, with only-new-jobs mode.

***

### 🇫🇷 En bref

**Votre marque apparaît-elle dans les réponses de ChatGPT, Perplexity et Gemini ?** Indiquez votre marque, vos concurrents et vos questions : l'Actor interroge les **API officielles** (OpenAI web search, Perplexity Agent API, Gemini + Google Search) **avec vos propres clés** (champs secrets, jamais nos clés) et renvoie pour chaque réponse : mention de la marque, position, citation de votre site, concurrents cités, URLs sources, et un résumé (taux de mention, part de voix). **0,02 $ par prompt et par moteur**, erreurs d'API non facturées, arrêt exact au budget maximum.

# Actor input Schema

## `brand` (type: `string`):

Your brand or product name, as people would write it.

## `brandAliases` (type: `array`):

Other spellings or product names that count as a mention of your brand (e.g. "EU Company Check").

## `brandDomains` (type: `array`):

Your website domain(s). Used to detect when AI answers cite your site, and counted as a mention when written in the answer.

## `competitors` (type: `array`):

One per line: "Name" or "Name | domain.com". Adding the domain also detects when the competitor's site is cited.

## `prompts` (type: `array`):

Questions your customers ask AI assistants. Each prompt is sent once to each selected engine (one billable check per prompt per engine).

## `engines` (type: `array`):

AI engines to query. An engine without an API key below is skipped (free).

## `openaiApiKey` (type: `string`):

Your own key from platform.openai.com. Stored encrypted by Apify, only sent to api.openai.com. OpenAI bills you for tokens and web-search calls.

## `perplexityApiKey` (type: `string`):

Your own key from perplexity.ai/account/api. Only sent to api.perplexity.ai.

## `geminiApiKey` (type: `string`):

Your own key from aistudio.google.com. Only sent to generativelanguage.googleapis.com. Grounding with Google Search is billed by Google per search query beyond the free tier.

## `openaiModel` (type: `string`):

Any Responses API model that supports the web_search tool (e.g. gpt-4.1-mini, gpt-5.5).

## `perplexityModel` (type: `string`):

Agent API preset (fast, low, medium, high, xhigh) or a model id such as perplexity/sonar. "fast" is the successor of Sonar.

## `geminiModel` (type: `string`):

Any Gemini model that supports Google Search grounding (e.g. gemini-3.5-flash-lite, gemini-3.8-flash).

## `country` (type: `string`):

Optional 2-letter country code passed to OpenAI web search as the approximate user location (e.g. FR). For other engines, write the location in the prompt.

## `forceWebSearch` (type: `boolean`):

On: OpenAI must search the web before answering (closest to ChatGPT search results). Off: the model decides, like ChatGPT does by default.

## `resolveGeminiUrls` (type: `boolean`):

Gemini returns redirect links; resolve them to the real page URL (one lightweight request per source, no page download).

## `includeAnswerText` (type: `boolean`):

Store the AI answer in each row (useful to review the context of mentions).

## `runsPerPrompt` (type: `integer`):

AI answers vary. Ask each prompt N times per engine (1-5) to measure how often you appear. Each run is a billable check.

## `concurrency` (type: `integer`):

Checks in flight at once (1-8). Lower it if your API tier has small rate limits.

## Actor input object example

```json
{
  "brand": "Ostrata",
  "brandAliases": [],
  "brandDomains": [
    "ostrata.io"
  ],
  "competitors": [
    "Kyckr | kyckr.com",
    "Creditsafe | creditsafe.com"
  ],
  "prompts": [
    "What is the best API to verify European companies (KYB)?",
    "How can I check a French company's SIREN and VAT number automatically?"
  ],
  "engines": [
    "openai",
    "perplexity",
    "gemini"
  ],
  "openaiModel": "gpt-4.1-mini",
  "perplexityModel": "fast",
  "geminiModel": "gemini-3.5-flash-lite",
  "country": "",
  "forceWebSearch": true,
  "resolveGeminiUrls": true,
  "includeAnswerText": true,
  "runsPerPrompt": 1,
  "concurrency": 3
}
```

# Actor output Schema

## `checks` (type: `string`):

Dataset items: brand mention, position, citations and competitors for each prompt and engine.

## `summary` (type: `string`):

Mention / citation rates, average position, share of voice vs competitors and top cited domains, overall and per engine.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "brand": "Ostrata",
    "brandDomains": [
        "ostrata.io"
    ],
    "competitors": [
        "Kyckr | kyckr.com",
        "Creditsafe | creditsafe.com"
    ],
    "prompts": [
        "What is the best API to verify European companies (KYB)?",
        "How can I check a French company's SIREN and VAT number automatically?"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ostrata/ai-search-visibility").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "brand": "Ostrata",
    "brandDomains": ["ostrata.io"],
    "competitors": [
        "Kyckr | kyckr.com",
        "Creditsafe | creditsafe.com",
    ],
    "prompts": [
        "What is the best API to verify European companies (KYB)?",
        "How can I check a French company's SIREN and VAT number automatically?",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("ostrata/ai-search-visibility").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "brand": "Ostrata",
  "brandDomains": [
    "ostrata.io"
  ],
  "competitors": [
    "Kyckr | kyckr.com",
    "Creditsafe | creditsafe.com"
  ],
  "prompts": [
    "What is the best API to verify European companies (KYB)?",
    "How can I check a French company'\''s SIREN and VAT number automatically?"
  ]
}' |
apify call ostrata/ai-search-visibility --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ostrata/ai-search-visibility"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/AlmfytvPd6yQipfIl/builds/14qhsAyS0jUQ4CmmP/openapi.json
