# AI Visibility Tracker for Brands | GEO / AEO Monitoring (`leafy-dev-jr/brand-ai-visibility-tracker`) Actor

Know exactly where your brand stands when buyers ask AI for recommendations. Track mentions, sentiment, and share of voice across ChatGPT, Gemini, Perplexity & Claude and what changes run after run.

- **URL**: https://apify.com/leafy-dev-jr/brand-ai-visibility-tracker.md
- **Developed by:** [Leafy](https://apify.com/leafy-dev-jr) (community)
- **Categories:** AI, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Brand AI Visibility Tracker: GEO / AEO Monitoring for ChatGPT, Gemini, Perplexity & Claude

**Track whether your brand actually gets mentioned or cited when real buyers ask AI assistants for recommendations.** This is an **AI visibility tracker** and **GEO tracker** (Generative Engine Optimization) that runs buyer-intent questions through **ChatGPT, Gemini, Perplexity, and Claude**, detects your brand and competitors in the answers, and scores your **share of voice in AI search**. It runs on a schedule, so you can watch that score move over time.

Unlike the subscription-only tools in this space, this Actor is **pay-per-check**, has **no monthly minimum**, and runs on a **free Google Gemini API key**, so your model cost can be **$0**.

> **Keywords:** AI visibility tracker, GEO tracker, AEO audit, ChatGPT brand monitoring, Gemini brand tracking, Perplexity brand monitoring, Claude brand tracking, generative engine optimization, share of voice AI search, LLM brand monitoring, answer engine optimization.

---

### Why this exists (the price & access gap)

When someone asks ChatGPT, Gemini, Perplexity, or Claude *"what's the best moisturizer for sensitive skin?"*, a handful of brands get named, and the rest are invisible. **Generative Engine Optimization (GEO)** / **Answer Engine Optimization (AEO)** is about being one of the named brands. To manage it, you first have to measure it.

This Actor is built differently:

- **Bring your own free Gemini key.** Google AI Studio's free tier (~250 requests/day, no credit card) covers the model calls. You pay Google nothing.
- **Pay-per-check, not per-month.** You're billed a tiny fee **per prompt-check** for the orchestration, canonicalization, scoring, and localization logic. It's not a subscription, and it's not the model cost.
- **Built for recurring use.** Delta mode compares each run to the last and tells you *what changed*, so it's something you schedule weekly or monthly rather than a one-time report.

---

### What it does

1. **Generates realistic buyer-intent prompts** for your category (or you supply your own). These are the kinds of questions a real customer types, not stiff templates.
2. **Asks each AI engine** those questions with live web search / grounding enabled.
3. **Detects your brand** (and its aliases) plus each competitor in every answer, with fuzzy/canonical matching and an optional LLM false-positive check.
4. **Scores** each answer: mentioned or not, position/prominence (leading vs. buried), and sentiment.
5. **Aggregates** into a 0–100 **Visibility Score**, plus breakdowns by engine and language and **share of voice** vs. competitors.
6. **Diffs against your last run** (delta mode) to report which prompts *gained* or *lost* a brand mention.

---

### AI assistants covered

You choose which assistants to check, by name. Each uses one key, and any engine without its key is **skipped automatically** (no errors), so you can start free with Gemini and add the others when you want multi-engine coverage.

| Assistant | Cost | Which key it uses | Where to get the key |
| --- | --- | --- | --- |
| **Gemini** (default) | Free tier | `geminiApiKey` | [aistudio.google.com/apikey](https://aistudio.google.com/apikey) |
| **ChatGPT** (GPT) | You pay OpenRouter | `openrouterApiKey` | [openrouter.ai/keys](https://openrouter.ai/keys) |
| **Perplexity** | You pay OpenRouter | `openrouterApiKey` | [openrouter.ai/keys](https://openrouter.ai/keys) |
| **Claude** | You pay Anthropic | `anthropicApiKey` | [console.anthropic.com](https://console.anthropic.com/) |

**One OpenRouter key covers both ChatGPT and Perplexity.** Both are reached through the [OpenRouter](https://openrouter.ai) gateway (ChatGPT via a GPT model with live web search, Perplexity via a Sonar model). Claude uses your Anthropic key directly. Gemini is direct and free, and also powers the internal prompt generation and analysis.

---

### Bring your own free Gemini key (the $0 path)

1. Go to **[aistudio.google.com/apikey](https://aistudio.google.com/apikey)** and click **Create API key** (free, no credit card).
2. Paste it into the **Gemini API key** field in this Actor's input.
3. Run. That's it. Gemini's free tier (~250 requests/day) covers a typical run at $0 in model cost.

> **Your key stays yours.** Each run uses the key *you* enter in its input. Keys are never shared between users, so you never end up paying for, or rate-limited by, someone else's runs.

---

### Example input

```json
{
  "brand": "CeraVe",
  "brandAliases": ["Cera Ve"],
  "category": "affordable skincare for sensitive skin",
  "competitors": ["Cetaphil", "La Roche-Posay", "Neutrogena"],
  "languages": ["en"],
  "country": "United States",
  "promptCountPerLanguage": 5,
  "engines": ["gemini"],
  "geminiApiKey": "YOUR_FREE_GEMINI_KEY",
  "useLlmAnalysis": true,
  "enableDeltaMode": true,
  "runsToKeep": 5
}
````

### Example output

**Per prompt × engine (one dataset row each):**

```json
{
  "recordType": "detail",
  "brand": "CeraVe",
  "language": "en",
  "prompt": "What's the best affordable moisturizer for sensitive skin?",
  "engine": "gemini",
  "engineModel": "gemini-2.5-flash",
  "brandMentioned": true,
  "position": 1,
  "prominence": "lead",
  "sentiment": "positive",
  "competitorsMentioned": ["Cetaphil", "La Roche-Posay"],
  "visibilityScore": 100,
  "citations": [{ "title": "Best drugstore skincare 2026", "url": "https://example.com/best-skincare" }],
  "answerExcerpt": "For sensitive skin on a budget, CeraVe's Moisturizing Cream is often the top recommendation...",
  "timestamp": "2026-07-08T09:20:00.000Z"
}
```

**Run summary (one record):**

```json
{
  "recordType": "summary",
  "brand": "CeraVe",
  "category": "affordable skincare for sensitive skin",
  "country": "United States",
  "runDate": "2026-07-08T09:20:12.000Z",
  "visibilityScore": 72.4,
  "scoreByLanguage": { "en": 72.4 },
  "scoreByEngine": { "gemini": 72.4 },
  "shareOfVoice": { "CeraVe": 41.7, "Cetaphil": 25.0, "La Roche-Posay": 20.8, "Neutrogena": 12.5 },
  "mentionRate": 80,
  "sentimentBreakdown": { "positive": 3, "neutral": 1, "negative": 0, "unknown": 0 },
  "deltaSinceLastRun": {
    "available": true,
    "previousRunDate": "2026-07-01T09:10:00.000Z",
    "scoreChange": 6.5,
    "gained": [{ "language": "en", "engine": "gemini", "prompt": "which moisturizer do dermatologists recommend?" }],
    "lost": []
  }
}
```

***

### Input reference

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `brand` | string | none | **Required.** The brand/company to track. |
| `brandAliases` | string\[] | `[]` | Alternate names/spellings canonicalized into the same brand. |
| `category` | string | none | **Required.** What the brand does; drives prompt generation. |
| `competitors` | string\[] | `[]` | Competitor names for share-of-voice. |
| `languages` | string\[] | `["en"]` | Languages to run. English today; more coming (see FAQ). |
| `country` | string | none | Optional market context for prompt framing. |
| `customPrompts` | string\[] | `[]` | Your own prompts. If set, generation is skipped. |
| `promptCountPerLanguage` | integer | `5` | Prompts to generate per language (max 20). |
| `engines` | string\[] | `["gemini"]` | Assistants to check: `gemini`, `chatgpt`, `perplexity`, `claude`. |
| `geminiApiKey` | string (secret) | none | Free Gemini key; required unless you exclusively use another engine and supply custom prompts. |
| `openrouterApiKey` | string (secret) | none | Optional OpenRouter key that powers **both** the `chatgpt` and `perplexity` engines. |
| `anthropicApiKey` | string (secret) | none | Optional Anthropic key that powers the `claude` engine. |
| `chatgptModel` | string | `openai/gpt-4o-mini:online` | Advanced: OpenRouter model slug for ChatGPT (`:online` enables web search). |
| `perplexityModel` | string | `perplexity/sonar` | Advanced: OpenRouter model slug for Perplexity. |
| `claudeModel` | string | `claude-sonnet-5` | Advanced: Anthropic model id for Claude. |
| `useLlmAnalysis` | boolean | `true` | One extra Gemini call per answer for sentiment + false-positive checks. Turn off to save quota. |
| `enableDeltaMode` | boolean | `true` | Compare to the previous run; report gained/lost mentions. |
| `regeneratePrompts` | boolean | `false` | Generate a fresh prompt set instead of reusing the persisted one. |
| `runsToKeep` | integer | `5` | Historical run snapshots to retain for trends. |

***

### FAQ

**How do I schedule this Actor?**
Use Apify **Schedules** to run it weekly or monthly. Keep `enableDeltaMode: true` and `regeneratePrompts: false` so each run asks the same questions and the delta (`gained` / `lost`) is meaningful. That's the whole point: come back and see what moved.

**What is delta mode?**
After each run, the Actor saves a snapshot (which prompts mentioned your brand, on which engine). On the next run it compares and reports which prompts *gained* or *lost* a brand mention, plus the change in your Visibility Score. To keep deltas comparable, auto-generated prompts are **persisted and reused** across runs.

**Which languages are supported?**
**English** today. The architecture is multi-language-ready by design, and the prompt generator is language-parameterized, so native-language prompt packs (Taglish, Bahasa Indonesia, Vietnamese, Thai, and more) are a planned fast-follow. English-first keeps the addressable market wide at launch.

**How is the Visibility Score calculated?**
Per answer (0–100): not mentioned = 0; mentioned = 40 base, plus prominence (leading +35, in-body +20, passing +10) and sentiment (positive +25, neutral/unknown +10, negative +0), capped at 100. The run score averages across all prompt×engine answers, with breakdowns by engine and language.

**Do I need a paid API key?**
No. Gemini's free tier covers the default path at $0 model cost. ChatGPT and Perplexity (one OpenRouter key) and Claude (an Anthropic key) are optional add-ons for multi-engine coverage and are skipped if no key is provided.

**Why do ChatGPT and Perplexity use an OpenRouter key?**
OpenRouter is a single gateway that reaches GPT (ChatGPT's model) and Perplexity Sonar with one key and one integration, so you don't manage separate OpenAI and Perplexity accounts. ChatGPT runs on a GPT model with live web search; Perplexity runs on a Sonar model that searches natively. Claude, by contrast, uses your Anthropic key directly.

**Does it scrape Google/ChatGPT?**
No. It calls official APIs (Gemini directly, ChatGPT/Perplexity via OpenRouter, Claude via Anthropic) with web search / grounding enabled. No proxies, no browser, no scraping.

***

### Contact / feedback

Bug reports, feature requests, and use-case tips welcome. Email the developer at [leafydevjr@gmail.com](mailto:leafydevjr@gmail.com?subject=Brand%20AI%20Visibility%20Tracker%20feedback).

# Actor input Schema

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

The brand or company you want to track (e.g. 'CeraVe').

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

Alternate names or spellings that mean the same brand. These are canonicalized into a single brand when detecting mentions (e.g. 'Cera Ve').

## `category` (type: `string`):

A short description of the product category. Used to auto-generate realistic buyer-intent prompts (e.g. 'affordable skincare for sensitive skin').

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

Competitor brand names to measure share-of-voice against.

## `languages` (type: `array`):

Languages to generate and run buyer-intent prompts in. Only English (en) is enabled today — more languages (Taglish, Bahasa Indonesia, Vietnamese, Thai) are coming as a fast-follow.

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

Optional. Frames the generated prompts with local market context (e.g. 'United States', 'Philippines'). Leave blank for a generic global framing.

## `customPrompts` (type: `array`):

Optional. Your own buyer-intent questions to run instead of auto-generated ones. If provided, these are used verbatim for every selected language and prompt generation is skipped.

## `promptCountPerLanguage` (type: `integer`):

How many prompts to auto-generate and run per language when no custom prompts are supplied.

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

Which AI assistants to query. Gemini is the free default. ChatGPT and Perplexity both run through an OpenRouter key (one key covers both); Claude uses an Anthropic key. Any engine without its key is skipped automatically — no errors.

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

Your free Google Gemini (AI Studio) API key. Get one at https://aistudio.google.com/apikey — free tier, no credit card required. Required unless you exclusively use another engine and supply your own prompts.

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

Optional. Your OpenRouter API key (https://openrouter.ai/keys). One key powers BOTH the ChatGPT and Perplexity engines. You pay OpenRouter directly for these calls.

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

Optional. Your Anthropic API key (https://console.anthropic.com/). Enables the Claude engine (with web search). You pay Anthropic directly for these calls.

## `chatgptModel` (type: `string`):

Optional. OpenRouter model slug for the ChatGPT engine. The ':online' suffix enables live web search. Override with a newer GPT model any time.

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

Optional. OpenRouter model slug for the Perplexity engine. Perplexity Sonar models perform live web search natively.

## `claudeModel` (type: `string`):

Optional. Anthropic model id for the Claude engine.

## `useLlmAnalysis` (type: `boolean`):

When on, each answer gets one extra lightweight Gemini call to classify sentiment toward your brand and veto false-positive mentions. Turn off to save API quota and rely on fast deterministic detection only.

## `enableDeltaMode` (type: `boolean`):

Compare this run against the previous run for the same brand + category + languages + engines and report which prompts gained or lost a brand mention. This is what makes scheduling the actor worthwhile.

## `regeneratePrompts` (type: `boolean`):

By default the auto-generated prompt set is saved and reused on every run so week-over-week deltas compare the same questions. Turn this on to generate a fresh set of prompts this run (resets delta history for auto-generated prompts).

## `runsToKeep` (type: `integer`):

How many past run snapshots to retain in the key-value store for trend tracking and delta comparison.

## Actor input object example

```json
{
  "brand": "CeraVe",
  "brandAliases": [
    "Cera Ve"
  ],
  "category": "affordable skincare for sensitive skin",
  "competitors": [
    "Cetaphil",
    "La Roche-Posay",
    "Neutrogena"
  ],
  "languages": [
    "en"
  ],
  "country": "United States",
  "customPrompts": [
    "What is the best affordable moisturizer for sensitive skin?",
    "Which cleanser should I use if I have acne-prone skin?"
  ],
  "promptCountPerLanguage": 5,
  "engines": [
    "gemini"
  ],
  "chatgptModel": "openai/gpt-4o:online",
  "perplexityModel": "perplexity/sonar-pro",
  "claudeModel": "claude-sonnet-5",
  "useLlmAnalysis": true,
  "enableDeltaMode": true,
  "regeneratePrompts": false,
  "runsToKeep": 5
}
```

# Actor output Schema

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

One detailed row per prompt x engine plus a single run-summary record (Visibility Score, share of voice, sentiment, and delta since the last 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 = {
    "brand": "CeraVe",
    "brandAliases": [
        "Cera Ve"
    ],
    "category": "affordable skincare for sensitive skin",
    "competitors": [
        "Cetaphil",
        "La Roche-Posay",
        "Neutrogena"
    ],
    "country": "United States"
};

// Run the Actor and wait for it to finish
const run = await client.actor("leafy-dev-jr/brand-ai-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": "CeraVe",
    "brandAliases": ["Cera Ve"],
    "category": "affordable skincare for sensitive skin",
    "competitors": [
        "Cetaphil",
        "La Roche-Posay",
        "Neutrogena",
    ],
    "country": "United States",
}

# Run the Actor and wait for it to finish
run = client.actor("leafy-dev-jr/brand-ai-visibility-tracker").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": "CeraVe",
  "brandAliases": [
    "Cera Ve"
  ],
  "category": "affordable skincare for sensitive skin",
  "competitors": [
    "Cetaphil",
    "La Roche-Posay",
    "Neutrogena"
  ],
  "country": "United States"
}' |
apify call leafy-dev-jr/brand-ai-visibility-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=leafy-dev-jr/brand-ai-visibility-tracker",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "AI Visibility Tracker for Brands | GEO / AEO Monitoring",
        "description": "Know exactly where your brand stands when buyers ask AI for recommendations. Track mentions, sentiment, and share of voice across ChatGPT, Gemini, Perplexity & Claude and what changes run after run.",
        "version": "0.1",
        "x-build-id": "GndBKYi3y7lbRX50L"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/leafy-dev-jr~brand-ai-visibility-tracker/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-leafy-dev-jr-brand-ai-visibility-tracker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/leafy-dev-jr~brand-ai-visibility-tracker/runs": {
            "post": {
                "operationId": "runs-sync-leafy-dev-jr-brand-ai-visibility-tracker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/leafy-dev-jr~brand-ai-visibility-tracker/run-sync": {
            "post": {
                "operationId": "run-sync-leafy-dev-jr-brand-ai-visibility-tracker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "brand",
                    "category"
                ],
                "properties": {
                    "brand": {
                        "title": "Brand name",
                        "type": "string",
                        "description": "The brand or company you want to track (e.g. 'CeraVe')."
                    },
                    "brandAliases": {
                        "title": "Brand aliases",
                        "type": "array",
                        "description": "Alternate names or spellings that mean the same brand. These are canonicalized into a single brand when detecting mentions (e.g. 'Cera Ve').",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "category": {
                        "title": "Category / what the brand does",
                        "type": "string",
                        "description": "A short description of the product category. Used to auto-generate realistic buyer-intent prompts (e.g. 'affordable skincare for sensitive skin')."
                    },
                    "competitors": {
                        "title": "Competitors",
                        "type": "array",
                        "description": "Competitor brand names to measure share-of-voice against.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "languages": {
                        "title": "Languages",
                        "type": "array",
                        "description": "Languages to generate and run buyer-intent prompts in. Only English (en) is enabled today — more languages (Taglish, Bahasa Indonesia, Vietnamese, Thai) are coming as a fast-follow.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "en"
                            ],
                            "enumTitles": [
                                "English (en)"
                            ]
                        },
                        "default": [
                            "en"
                        ]
                    },
                    "country": {
                        "title": "Country / market context",
                        "type": "string",
                        "description": "Optional. Frames the generated prompts with local market context (e.g. 'United States', 'Philippines'). Leave blank for a generic global framing."
                    },
                    "customPrompts": {
                        "title": "Custom prompts",
                        "type": "array",
                        "description": "Optional. Your own buyer-intent questions to run instead of auto-generated ones. If provided, these are used verbatim for every selected language and prompt generation is skipped.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "promptCountPerLanguage": {
                        "title": "Prompts per language",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "How many prompts to auto-generate and run per language when no custom prompts are supplied.",
                        "default": 5
                    },
                    "engines": {
                        "title": "AI assistants to check",
                        "type": "array",
                        "description": "Which AI assistants to query. Gemini is the free default. ChatGPT and Perplexity both run through an OpenRouter key (one key covers both); Claude uses an Anthropic key. Any engine without its key is skipped automatically — no errors.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "gemini",
                                "chatgpt",
                                "perplexity",
                                "claude"
                            ],
                            "enumTitles": [
                                "Gemini (free, default)",
                                "ChatGPT / GPT (via OpenRouter, BYOK)",
                                "Perplexity (via OpenRouter, BYOK)",
                                "Claude (via Anthropic, BYOK)"
                            ]
                        },
                        "default": [
                            "gemini"
                        ]
                    },
                    "geminiApiKey": {
                        "title": "Gemini API key (free)",
                        "type": "string",
                        "description": "Your free Google Gemini (AI Studio) API key. Get one at https://aistudio.google.com/apikey — free tier, no credit card required. Required unless you exclusively use another engine and supply your own prompts."
                    },
                    "openrouterApiKey": {
                        "title": "OpenRouter API key (ChatGPT + Perplexity)",
                        "type": "string",
                        "description": "Optional. Your OpenRouter API key (https://openrouter.ai/keys). One key powers BOTH the ChatGPT and Perplexity engines. You pay OpenRouter directly for these calls."
                    },
                    "anthropicApiKey": {
                        "title": "Anthropic API key (Claude)",
                        "type": "string",
                        "description": "Optional. Your Anthropic API key (https://console.anthropic.com/). Enables the Claude engine (with web search). You pay Anthropic directly for these calls."
                    },
                    "chatgptModel": {
                        "title": "ChatGPT model (advanced)",
                        "type": "string",
                        "description": "Optional. OpenRouter model slug for the ChatGPT engine. The ':online' suffix enables live web search. Override with a newer GPT model any time.",
                        "default": "openai/gpt-4o-mini:online"
                    },
                    "perplexityModel": {
                        "title": "Perplexity model (advanced)",
                        "type": "string",
                        "description": "Optional. OpenRouter model slug for the Perplexity engine. Perplexity Sonar models perform live web search natively.",
                        "default": "perplexity/sonar"
                    },
                    "claudeModel": {
                        "title": "Claude model (advanced)",
                        "type": "string",
                        "description": "Optional. Anthropic model id for the Claude engine.",
                        "default": "claude-sonnet-5"
                    },
                    "useLlmAnalysis": {
                        "title": "Deep LLM analysis (sentiment + false-positive check)",
                        "type": "boolean",
                        "description": "When on, each answer gets one extra lightweight Gemini call to classify sentiment toward your brand and veto false-positive mentions. Turn off to save API quota and rely on fast deterministic detection only.",
                        "default": true
                    },
                    "enableDeltaMode": {
                        "title": "Delta mode (compare to previous run)",
                        "type": "boolean",
                        "description": "Compare this run against the previous run for the same brand + category + languages + engines and report which prompts gained or lost a brand mention. This is what makes scheduling the actor worthwhile.",
                        "default": true
                    },
                    "regeneratePrompts": {
                        "title": "Regenerate prompts each run",
                        "type": "boolean",
                        "description": "By default the auto-generated prompt set is saved and reused on every run so week-over-week deltas compare the same questions. Turn this on to generate a fresh set of prompts this run (resets delta history for auto-generated prompts).",
                        "default": false
                    },
                    "runsToKeep": {
                        "title": "Historical runs to keep",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "How many past run snapshots to retain in the key-value store for trend tracking and delta comparison.",
                        "default": 5
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
