# AI Search Visibility Tracker: ChatGPT, Perplexity, Gemini (`pistachio_implementation/ai-search-visibility-tracker`) Actor

Check if ChatGPT, Perplexity and Gemini mention or cite your brand for any list of prompts. Get position, competitors named, cited sources and a 0 to 100 visibility score per engine. Bring your own API keys.

- **URL**: https://apify.com/pistachio\_implementation/ai-search-visibility-tracker.md
- **Developed by:** [Hay Equipos](https://apify.com/pistachio_implementation) (community)
- **Categories:** AI, SEO tools, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$20.00 / 1,000 prompt analyzed on one engines

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 Search Visibility Tracker: ChatGPT, Perplexity, Gemini

Find out whether AI assistants recommend your brand. Give this actor a list of prompts your buyers might ask, your brand name and your domain. It sends each prompt to **ChatGPT (OpenAI with web search)**, **Perplexity** and **Gemini (with Google Search grounding)**, then reports for every answer:

- whether your brand is **mentioned**, how often, and where it ranks against the competitors you track
- its **position** in the answer's list of recommendations
- whether your website is **cited** as a source, and at which citation position
- which **competitors** were named or cited
- every **cited source** with its domain
- a **visibility score** from 0 to 100 and your **share of voice**

It finishes with a summary per engine and overall: mention rate, citation rate, average score, average rank, top competitors and the domains the engines cite most. That is the data you need for generative engine optimization (GEO) and AI SEO reporting.

### Bring your own API keys

You supply your own OpenAI, Perplexity and Gemini API keys. They are stored encrypted by Apify as secret inputs, sent only to the engine they belong to, and never written to the log or the output. Each provider bills you directly at its own rates, so you always pay list price for the model calls, with no markup. The actor charges only a small fee for the orchestration and the analysis.

Use one, two or all three engines. An engine without a key is skipped.

**Try it free:** run the actor with no keys at all and it analyzes bundled sample answers so you can see exactly what the output looks like. Demo runs are never charged.

### Input example

```json
{
    "prompts": [
        "What are the best project management tools for small teams?",
        "Which Kanban app is easiest for a marketing team?"
    ],
    "brandName": "Trello",
    "brandDomain": "trello.com",
    "brandAliases": ["Trello by Atlassian"],
    "competitors": ["Asana (asana.com)", "monday.com (monday.com)", "ClickUp (clickup.com)", "Notion (notion.so)"],
    "engines": ["openai", "perplexity", "gemini"],
    "openaiApiKey": "your OpenAI key",
    "perplexityApiKey": "your Perplexity key",
    "geminiApiKey": "your Gemini key",
    "country": "US"
}
```

| Field | What it does |
|---|---|
| `prompts` | The questions to ask, up to 500 per run |
| `brandName`, `brandAliases` | Names that count as a mention of your brand (whole word, case insensitive) |
| `brandDomain` | Your site. A citation of this domain or any subdomain counts as cited |
| `competitors` | Names to track, each optionally followed by its domain in brackets for citation tracking |
| `engines` | `openai`, `perplexity`, `gemini` |
| `openaiModel`, `perplexityModel`, `geminiModel` | Defaults: `gpt-4.1-mini`, `sonar`, `gemini-2.5-flash` |
| `country` | Optional two letter country code for localized search where the engine supports it |
| `includeAnswerText` | Keep the full answer in the output (default on) |

### Output example

One row per prompt per engine:

```json
{
    "recordType": "result",
    "prompt": "What are the best project management tools for small teams?",
    "engine": "openai",
    "model": "gpt-4.1-mini-2025-04-14",
    "brandName": "Trello",
    "brandDomain": "trello.com",
    "brandMentioned": true,
    "brandMentionCount": 2,
    "brandRank": 2,
    "brandListPosition": 2,
    "brandCited": true,
    "brandCitationPosition": 2,
    "shareOfVoice": 0.333,
    "visibilityScore": 93,
    "competitorsMentioned": [
        { "name": "Asana", "domain": "asana.com", "mentionCount": 2, "rank": 1, "listPosition": 1, "cited": true, "citationPosition": 1, "visibilityScore": 100 }
    ],
    "citations": [
        { "position": 1, "url": "https://asana.com/pricing", "title": "Asana pricing", "domain": "asana.com", "isBrand": false, "competitor": "Asana" },
        { "position": 2, "url": "https://trello.com/pricing", "title": "Trello pricing", "domain": "trello.com", "isBrand": true, "competitor": null }
    ],
    "answerText": "Here are some of the best project management tools for small teams: ...",
    "error": null,
    "demo": false
}
```

Plus summary rows (`recordType` is `summary`), one per engine and one with `engine` set to `all`:

```json
{
    "recordType": "summary",
    "engine": "all",
    "brandName": "Trello",
    "answersAnalyzed": 3,
    "mentionRate": 1,
    "citationRate": 0.667,
    "averageVisibilityScore": 79.3,
    "averageRankWhenMentioned": 2.3,
    "averageShareOfVoice": 0.333,
    "topCompetitors": [{ "name": "Asana", "answers": 3 }],
    "topCitedDomains": [{ "domain": "asana.com", "answers": 2 }]
}
```

The same summary is saved to the key value store as `SUMMARY`.

#### How the visibility score works

| Part | Points |
|---|---|
| Brand mentioned | 40 |
| Mention prominence: 20 if named first among tracked brands, 15 if second, 10 if third, 5 if fourth | up to 20 |
| Brand site cited as a source | 30 |
| Citation prominence: 10 if the first source, 2 fewer for each later position | up to 10 |

`brandRank` is the order in which your brand first appears among all the names you track. `brandListPosition` is the numbered or bulleted list item where it first appears, if the answer is a list. `shareOfVoice` is your mentions divided by all tracked mentions in the answer.

### Pricing

Pay per event:

| Event | Price |
|---|---|
| One prompt answered and analyzed on one engine | $0.02 |

Example: 20 prompts on 3 engines is 60 analyses, which costs $1.20 here, plus whatever OpenAI, Perplexity and Google bill you for the calls on your own keys (usually a few cents per prompt for small models). Failed calls, rejected keys, summary rows and demo runs are free. You can cap your spend with the maximum charge setting on each run.

### Limits

- AI answers vary from run to run. Track the same prompts on a schedule and read the trend, not one run.
- API answers can differ from what a signed in user sees in the ChatGPT, Perplexity or Gemini apps, which add personalization and memory. The API with web search is the closest repeatable, rule abiding view.
- Gemini returns cited sources as Google redirect links with the source domain as the title; the actor reports the domain, so page level URLs are not available for Gemini.
- Mentions are matched as whole words. Very short or generic brand names (for example "Go" or "Apple") can match unrelated uses; add aliases or a distinctive name.
- Google AI Overviews are not covered, because there is no official API for them.
- Not affiliated with OpenAI, Perplexity or Google.

### FAQ

**Is my API key safe?** Keys are secret inputs, encrypted at rest by Apify, sent only over HTTPS to the matching provider, and never printed to the log or saved to the dataset.

**Why bring my own keys?** You pay the providers' own prices with no markup, you control your models and limits, and your usage stays in your own accounts.

**Which models can I use?** Any OpenAI model that supports the web search tool in the Responses API, any Perplexity Sonar model, and any Gemini model that supports Google Search grounding.

**Can I track many brands?** Run the actor once per brand, or list rival brands as competitors to see them side by side in one run.

**Can I schedule it?** Yes. Use Apify schedules to run weekly and connect the dataset to Google Sheets, Looker Studio or a webhook.

**Found a problem?** Open an issue on the Issues tab. Issues are answered quickly.

# Actor input Schema

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

Questions your buyers might ask an AI assistant, one per line. Each prompt is sent to every selected engine.

## `brandName` (type: `string`):

The brand to look for in the answers.

## `brandDomain` (type: `string`):

Your website domain, for example example.com. Used to detect when an engine cites your site as a source. Subdomains count.

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

Other names that should count as a mention, such as product names or old names.

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

Competitor names to track in the same answers. A domain in brackets is optional and enables citation tracking, for example: Asana (asana.com).

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

Which AI engines to query. An engine runs only if you supply its API key below.

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

Your own OpenAI API key. Stored encrypted by Apify and never logged or saved to the output. OpenAI bills you directly for tokens and web search calls.

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

Your own Perplexity API key. Perplexity bills you directly.

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

Your own Gemini API key from Google AI Studio. Google bills you directly (a free tier exists for some models).

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

Any OpenAI model that supports the web search tool in the Responses API.

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

Perplexity Sonar model, for example sonar or sonar-pro.

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

Gemini model that supports Google Search grounding.

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

Optional two letter country code (for example US or GB) passed to engines that support approximate user location for search.

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

Save the full answer from each engine in the output.

## `demoMode` (type: `boolean`):

Analyze bundled sample answers instead of calling any engine. Free, no keys needed. Also used automatically when no key is supplied.

## Actor input object example

```json
{
  "prompts": [
    "What are the best project management tools for small teams?"
  ],
  "brandName": "Trello",
  "brandDomain": "trello.com",
  "competitors": [
    "Asana (asana.com)",
    "monday.com (monday.com)",
    "ClickUp (clickup.com)",
    "Notion (notion.so)"
  ],
  "engines": [
    "openai",
    "perplexity",
    "gemini"
  ],
  "openaiModel": "gpt-4.1-mini",
  "perplexityModel": "sonar",
  "geminiModel": "gemini-2.5-flash",
  "includeAnswerText": true,
  "demoMode": false
}
```

# Actor output Schema

## `results` (type: `string`):

All rows the run saved to the default dataset.

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

The SUMMARY record: counts and problems for the whole run.

# 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 = {
    "prompts": [
        "What are the best project management tools for small teams?"
    ],
    "brandName": "Trello",
    "brandDomain": "trello.com",
    "competitors": [
        "Asana (asana.com)",
        "monday.com (monday.com)",
        "ClickUp (clickup.com)",
        "Notion (notion.so)"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("pistachio_implementation/ai-search-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 = {
    "prompts": ["What are the best project management tools for small teams?"],
    "brandName": "Trello",
    "brandDomain": "trello.com",
    "competitors": [
        "Asana (asana.com)",
        "monday.com (monday.com)",
        "ClickUp (clickup.com)",
        "Notion (notion.so)",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("pistachio_implementation/ai-search-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 '{
  "prompts": [
    "What are the best project management tools for small teams?"
  ],
  "brandName": "Trello",
  "brandDomain": "trello.com",
  "competitors": [
    "Asana (asana.com)",
    "monday.com (monday.com)",
    "ClickUp (clickup.com)",
    "Notion (notion.so)"
  ]
}' |
apify call pistachio_implementation/ai-search-visibility-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,pistachio_implementation/ai-search-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/gRzr9WPUJjCGnaHhG/builds/TUoPj5GvTi1yqjciw/openapi.json
