# AI Brand Visibility Tracker – ChatGPT, Claude, Gemini (`signalwharf/ai-brand-visibility-tracker`) Actor

AI visibility tracker and LLM visibility tool for GEO/AEO. Track brand mentions in ChatGPT, Claude, Gemini, Perplexity and Grok answers: visibility score, share of voice vs competitors, rank, sentiment, cited domains and change vs last run. Bring your own API key, no AI markup.

- **URL**: https://apify.com/signalwharf/ai-brand-visibility-tracker.md
- **Developed by:** [Signal Wharf](https://apify.com/signalwharf) (community)
- **Categories:** AI, SEO tools, Marketing
- **Features:** Limited permissions
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 ai answer analyzeds

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: track brand mentions in ChatGPT, Claude, Gemini & Perplexity

**Find out whether AI assistants recommend your brand, or your competitors.** Give it the questions your customers ask AI ("What's the best CRM for a small business?"), your brand, and your competitors. The Actor asks each AI model, detects every brand in each answer, and builds a **visibility report** for each model:

- **Visibility score (0–100)**, mention rate, and **share of voice** against your competitors
- **Rank** (which brand is mentioned first) and **list position** in "top 10" style answers
- **Sentiment** around each brand, and **cited domains** (does the AI link to your site?)
- The **prompts where your brand is missing**, which is your GEO to-do list
- **Other names in lists**: products the AI recommends that you aren't tracking yet
- **Change vs the previous run**, plus a 30-run history, for weekly or daily tracking

**Bring your own API keys, with no markup on AI costs.** You pay OpenAI, Anthropic, Google, Perplexity, OpenRouter or xAI directly, at their normal API prices, usually under $0.001 per answer for small models. This Actor charges only for the analysis. Most AI visibility tools bundle the AI cost and charge **$0.08–$0.30 per check**. Here it's **$0.005 per answer**.

### What can this AI visibility tracker do?

- 🔑 **Official APIs, no scraping of chat UIs.** No proxies, captchas, or broken runs when a website changes.
- 🎲 **Statistically honest.** AI answers change from one run to the next. Ask each prompt 3–5 times (`samplesPerPrompt`) to get a real **mention rate** instead of a one-off screenshot.
- 🌐 **Many models in one run:** compare ChatGPT, Claude, Gemini, Perplexity, Grok, Llama, Mistral, DeepSeek and others side by side. One **OpenRouter** key covers most of them.
- 🔎 **Optional web search and grounding**, to see what AI search cites: the OpenAI web search tool, Anthropic web search, Gemini Google Search grounding, the OpenRouter web plugin, and Perplexity.
- 📈 **Tracking built in:** reports compare against the last run with the same `trackingId`. Schedule it weekly and watch your score move.
- 🔒 **Keys are secret inputs:** encrypted by Apify, never logged, never written to results.
- 💸 **Failed AI calls are free.** A bad key, an unknown model, or a rate limit never costs you an event.

### How to track your brand in AI answers (GEO / AEO)

1. Add your **brand** in the form `Name | alias | domain.com` (e.g. `HubSpot | HubSpot CRM | hubspot.com`).
2. Add **competitors** in the same format, one per line.
3. Add **prompts**: real buyer questions. Keep them the same between runs so the trend stays meaningful.
4. Add **models** as `provider:model-id`, using any model id your provider currently lists:
   - `openrouter:<vendor>/<model>`: one OpenRouter key covers them all. Cheap current ids we tested (Nov 2026): `openrouter:openai/gpt-6-luna`, `openrouter:anthropic/claude-haiku-5.5`, `openrouter:google/gemini-3.5-flash-lite`, `openrouter:x-ai/grok-4.3`, `openrouter:perplexity/sonar`
   - `openai:<model>`, `anthropic:<model>`, `gemini:<model>`, `perplexity:<model>`, `xai:<model>` with that provider's own key
   - `custom:<model>` with `customBaseUrl` for any OpenAI-compatible endpoint (Groq, Together, Azure-compatible gateways, your own proxy)
5. Paste the **API key** for each provider you use. Run it.

#### Example input

```json
{
  "brand": "HubSpot | HubSpot CRM | hubspot.com",
  "competitors": ["Salesforce | salesforce.com", "Zoho CRM | Zoho | zoho.com", "Pipedrive | pipedrive.com"],
  "prompts": ["What is the best CRM for a small business?", "Which CRM should a 10-person startup use?"],
  "models": ["openrouter:openai/gpt-6-luna", "openrouter:anthropic/claude-haiku-5.5", "openrouter:google/gemini-3.5-flash-lite", "openrouter:x-ai/grok-4.3"],
  "openrouterApiKey": "sk-or-...",
  "samplesPerPrompt": 3,
  "webSearch": false,
  "trackingId": "hubspot-crm-us"
}
```

### Output

Dataset items have an `itemType`. The Console views are **Visibility reports**, **AI answers** and **Answer text**.

**`report`**: one per model, plus `all-models` when you track several (trimmed, illustrative values):

```json
{
  "itemType": "report",
  "model": "openrouter:openai/gpt-6-luna",
  "brand": "HubSpot",
  "answers": 6,
  "brandVisibilityScore": 72.5,
  "brandMentionRate": 0.833,
  "brandShareOfVoice": 0.31,
  "brandAvgRank": 1.4,
  "brandCitationRate": 0.0,
  "brandLeaderboardPosition": 1,
  "leaderboard": [{ "name": "HubSpot", "visibilityScore": 72.5, "mentionRate": 0.833, "shareOfVoice": 0.31 }],
  "promptsWhereBrandMissing": ["Which CRM should a 10-person startup use?"],
  "otherNamesInLists": [{ "name": "Freshsales", "answers": 3 }],
  "topCitedDomains": [{ "domain": "g2.com", "answers": 2 }],
  "previousBrandVisibilityScore": 64.0,
  "brandVisibilityScoreChange": 8.5,
  "providerCostUsd": 0.0021
}
```

**`answer`**: one per AI answer. It includes `prompt`, `sample`, `brandMentioned`, `brandRank`, `brandListPosition`, `brandSentiment` and `brandCited`. It also includes `brandsMentionedInOrder`, a per-competitor breakdown (`competitors`), `citedDomains` and `citationUrls`. Finally there's `otherNamesInLists`, the full `answerText`, token `usage` (with `costUsd` when the provider reports it, e.g. OpenRouter, and `truncated` when the answer hit `maxAnswerTokens`) and `latencyMs`.

**`info`**: written only when no API key is given. The run still succeeds, charges nothing, and explains which key field to fill in.

**`error`**: a failed AI call with its reason (`auth_error`, `model_not_found`, `rate_limited`, and so on). These are **never charged**.

**How the visibility score works:** 60% mention rate + 25% rank score (1 / rank, 0 when not mentioned) + 15% citation rate, scaled to 0–100. Citations only exist when answers carry sources (web search on, or Perplexity), so without them the top possible score is 85. `brandRank` is the order of first mention among your tracked brands; `brandListPosition` is the position in the answer's main recommendation list (bullets, numbered headings or a comparison table), empty when the brand is only mentioned outside it. Sentiment is a fast word-list heuristic over the brand's own list section and the sentences naming it, so treat it as a signal, not a verdict. Reports with `webSearch` on keep a separate history from plain runs, so the change vs last run compares like with like.

### How much does AI brand visibility tracking cost?

Pay per event. **AI usage goes on your own provider bill**, at cost.

| Event | Price |
|---|---|
| AI answer analyzed | **$0.005** |
| Visibility report (per model, plus a combined one) | $0.02 |
| Failed AI call | free |

Examples:

- 10 prompts × 3 samples × 1 model = 30 answers + 1 report = **$0.17**, plus roughly $0.01–0.05 at your AI provider for small models
- 20 prompts × 3 samples × 4 models = 240 answers + 5 reports = **$1.30** a run. Weekly, that's about $5.60 a month.

If you set a maximum cost per run, leave room for the reports: answers × $0.005 + reports × $0.02.

### Limits and good to know

- These are **API answers**, not the consumer chat apps. Consumer apps add memory, personalization and their own system prompts. Use `systemPrompt`, `locationHint` and `webSearch` to get closer to what users see. API answers are the reproducible baseline most GEO teams track.
- Brand detection matches names, aliases and domains you give it, with whole-word, case-insensitive matching. Add aliases for common spellings. Very generic brand names (e.g. "Notion", "Apple") can produce false positives.
- Model ids change often. Use the ids your provider lists today, or OpenRouter's catalog.
- Some newer models accept only the default temperature, so leave `temperature` empty unless you need it.
- Web search makes answers slower and costs more at your provider.

### Use cases

- **GEO / AEO (generative engine optimization):** find the buyer questions where AI assistants skip your brand, then fix your content and check again.
- **Competitive intelligence:** a share-of-voice leaderboard of you vs competitors, for each model.
- **Agency reporting:** a weekly AI visibility report per client, with change vs last week.
- **Launch monitoring:** see when a new product starts showing up in LLM answers.
- **Model comparison:** compare how ChatGPT, Claude, Gemini, Perplexity and Grok talk about your category.

### FAQ

**Do I need an API key?** Yes, for the providers you want to test. One OpenRouter key covers most models. Without a key, the run finishes successfully, charges nothing, and tells you which key field to fill in.

**Is this an LLM visibility checker or a rank tracker?** Both. It checks whether you're mentioned (mention rate), where (rank and list position), how (sentiment), and whether your site is cited. Run it on a schedule and it becomes an AI rank tracker with history.

**Why are results different every run?** AI answers are probabilistic. Use `samplesPerPrompt` of 3–5 for stable rates, and keep prompts the same between runs.

**Does it check Google AI Overviews?** No. It uses AI model APIs. For Google AI Overviews, use a dedicated AI Overviews scraper.

### Legal and data

The Actor sends your prompts to the AI providers you choose, under your own API accounts and their terms. It doesn't scrape any website or chat interface. Don't put confidential data in prompts.

### Related signalwharf Actors

- [Telegram Channel Scraper](https://apify.com/signalwharf/telegram-channel-scraper): scrape public Telegram channel posts, views, reactions and media without login.
- [Substack Scraper](https://apify.com/signalwharf/substack-scraper): Substack posts with full text, comments, subscriber estimates and paid plan prices.
- [AI Brand Visibility Tracker](https://apify.com/signalwharf/ai-brand-visibility-tracker): track how often ChatGPT, Claude, Gemini and Perplexity mention your brand vs competitors.

# Actor input Schema

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

Brand name, optional aliases and website domain separated by <code>|</code>, e.g. <code>HubSpot | HubSpot CRM | hubspot.com</code>. The domain is used to detect when AI answers cite your site.

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

Same format as the brand, one per line, e.g. <code>Salesforce | salesforce.com</code>.

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

The questions your customers would ask an AI assistant, e.g. 'What is the best CRM for a small business?'.

## `models` (type: `array`):

One per line as <code>provider:model-id</code>. Providers: <code>openai</code>, <code>anthropic</code>, <code>gemini</code>, <code>perplexity</code>, <code>openrouter</code>, <code>xai</code>, <code>custom</code> (any OpenAI-compatible endpoint). The prefilled models are cheap current models on OpenRouter (one OpenRouter key covers all four). Add <code>openrouter:perplexity/sonar</code> for a search-based answer engine. Native ids work too, e.g. <code>openai:gpt-6-luna</code> with an OpenAI key. Model ids change often; use the ids your provider lists today.

## `samplesPerPrompt` (type: `integer`):

AI answers vary between runs. Ask each prompt several times per model to get a reliable mention rate (3-5 recommended for tracking).

## `webSearch` (type: `boolean`):

Let models search the web where the provider supports it (OpenAI web search tool, Anthropic web search, Gemini Google Search grounding, OpenRouter web plugin; Perplexity always searches). Gives citation data but costs more on your provider bill.

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

Needed for <code>openai:</code> models. Your key is encrypted by Apify, never logged or stored in results. You pay OpenAI directly for usage.

## `anthropicApiKey` (type: `string`):

Needed for <code>anthropic:</code> models.

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

Needed for <code>gemini:</code> models (Google AI Studio key).

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

Needed for <code>perplexity:</code> models.

## `openrouterApiKey` (type: `string`):

Needed for <code>openrouter:</code> models. One key gives access to models from OpenAI, Anthropic, Google, Meta, Mistral and more.

## `xaiApiKey` (type: `string`):

Needed for <code>xai:</code> (Grok) models.

## `customBaseUrl` (type: `string`):

For provider <code>custom</code>, e.g. <code>https://api.groq.com/openai/v1</code> or your own gateway. Requests go to <code>{baseUrl}/chat/completions</code>.

## `customApiKey` (type: `string`):

Bearer key for the custom endpoint (optional if it needs none).

## `trackingId` (type: `string`):

Name for this tracking project. Reports compare against the previous run with the same tracking ID (default: the brand name).

## `stateStoreName` (type: `string`):

Named key-value store that keeps report history between runs.

## `locationHint` (type: `string`):

Optional, e.g. 'Germany' or 'Austin, Texas'. Added to the system prompt so answers reflect a market.

## `systemPrompt` (type: `string`):

Optional. Leave empty to see the model's default behaviour (closest to what real users get).

## `temperature` (type: `string`):

Optional, e.g. 0.7. Empty = provider default (recommended; some models only accept the default).

## `maxAnswerTokens` (type: `integer`):

Upper limit for answer length (also limits your provider cost).

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

Store the full AI answer in each result.

## `maxAnswers` (type: `integer`):

Safety cap on AI calls per run (prompts x samples x models).

## `maxConcurrency` (type: `integer`):

How many AI requests run at the same time.

## `maxRetries` (type: `integer`):

Retries for rate limits (429), server errors and network errors.

## Actor input object example

```json
{
  "brand": "HubSpot | HubSpot CRM | hubspot.com",
  "competitors": [
    "Salesforce | salesforce.com",
    "Zoho CRM | Zoho | zoho.com",
    "Pipedrive | pipedrive.com"
  ],
  "prompts": [
    "What is the best CRM for a small business?",
    "Which CRM should a 10-person startup use?"
  ],
  "models": [
    "openrouter:openai/gpt-6-luna",
    "openrouter:anthropic/claude-haiku-5.5",
    "openrouter:google/gemini-3.5-flash-lite",
    "openrouter:x-ai/grok-4.3"
  ],
  "samplesPerPrompt": 1,
  "webSearch": false,
  "stateStoreName": "ai-brand-visibility-state",
  "maxAnswerTokens": 1200,
  "includeAnswerText": true,
  "maxAnswers": 300,
  "maxConcurrency": 3,
  "maxRetries": 3
}
```

# Actor output Schema

## `reports` (type: `string`):

Share-of-voice reports per model.

## `answers` (type: `string`):

Every AI answer with detected brands, ranks, sentiment and citations.

## `runSummary` (type: `string`):

Per-model status and errors.

# 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": "HubSpot | HubSpot CRM | hubspot.com",
    "competitors": [
        "Salesforce | salesforce.com",
        "Zoho CRM | Zoho | zoho.com",
        "Pipedrive | pipedrive.com"
    ],
    "prompts": [
        "What is the best CRM for a small business?",
        "Which CRM should a 10-person startup use?"
    ],
    "models": [
        "openrouter:openai/gpt-6-luna",
        "openrouter:anthropic/claude-haiku-5.5",
        "openrouter:google/gemini-3.5-flash-lite",
        "openrouter:x-ai/grok-4.3"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("signalwharf/ai-brand-visibility-tracker").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": "HubSpot | HubSpot CRM | hubspot.com",
    "competitors": [
        "Salesforce | salesforce.com",
        "Zoho CRM | Zoho | zoho.com",
        "Pipedrive | pipedrive.com",
    ],
    "prompts": [
        "What is the best CRM for a small business?",
        "Which CRM should a 10-person startup use?",
    ],
    "models": [
        "openrouter:openai/gpt-6-luna",
        "openrouter:anthropic/claude-haiku-5.5",
        "openrouter:google/gemini-3.5-flash-lite",
        "openrouter:x-ai/grok-4.3",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("signalwharf/ai-brand-visibility-tracker").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": "HubSpot | HubSpot CRM | hubspot.com",
  "competitors": [
    "Salesforce | salesforce.com",
    "Zoho CRM | Zoho | zoho.com",
    "Pipedrive | pipedrive.com"
  ],
  "prompts": [
    "What is the best CRM for a small business?",
    "Which CRM should a 10-person startup use?"
  ],
  "models": [
    "openrouter:openai/gpt-6-luna",
    "openrouter:anthropic/claude-haiku-5.5",
    "openrouter:google/gemini-3.5-flash-lite",
    "openrouter:x-ai/grok-4.3"
  ]
}' |
apify call signalwharf/ai-brand-visibility-tracker --silent --output-dataset

```

## MCP server setup

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

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/3a1S6RtCjTpUPvtLm/builds/OpGfHW49in5cze03w/openapi.json
