AI brand monitoring across ChatGPT, Perplexity, Gemini and Google AI Overviews. Samples every prompt multiple times for mention rate, share of voice and week-over-week deltas — not a single-shot guess.
Pricing
from $6.50 / 1,000 prompt sampled — google ai overviews
All notable changes to this Actor are documented here.
The format follows Keep a Changelog .
[0.4.11] — 2026-08-09
Gaps found by reading Apify's own publishing docs. Listing only.
Added
.actor/key_value_store_schema.json, declared in actor.json under
storages.keyValueStore. The quality score's congruency category names the
key-value store schema explicitly alongside the input and dataset schemas, and
it was the one this Actor did not have — the SUMMARY record the output schema
links to was undeclared. Verified after deploy that Actor.setValue('SUMMARY')
still writes cleanly under the schema's application/json content type.
Changed
README images renamed from hero.png / variance.png to
ai-search-visibility-tracker-hero.png and
ai-answer-variance-measurement.png. Apify's README guide asks for
descriptive, SEO-friendly file names and warns against generic ones; the first
pass shipped exactly the generic names it warns about.
Both images are now wrapped in links to the Actor page, which the same guide
recommends.
Notes
Two things checked and deliberately not done:
No status badge. It renders live runs: N, users: N. At two users that
argues against the Actor on its own page. Worth adding once the numbers help.
No llms.txt to write. Apify serves one at apify.com/llms.txt, but it
lists Apify's own pages only — no community Actor appears in it, ours or a
competitor's. The LLM-facing surface is instead the per-Actor markdown at
apify.com/<user>/<actor>.md, which is generated from this README. It strips
images, so the variance evidence is carried by the markdown table rather than
the chart alone — which it is.
That same page currently reports 0.0% runs succeeded to any model reading
it: publicActorRunStats30Days is 5 TIMED-OUT and 0 succeeded, all of them the
quality tests that failed before 0.4.7. Owner runs do not count toward it, so
it clears only as the automated tests start passing.
[0.4.9] — 2026-08-09
Store listing and discoverability. One real bug fixed, no behaviour change.
Fixed
The MCP connection URL in the README was a 404. It advertised
mcp.apify.com?tools=emoubarak/ai-brand-monitor, but the published Actor slug
is ai-search-visibility-tracker — verified against the API, which returns 404
for the former and 200 for the latter. Every agent that followed the README
failed to connect, on the one section aimed squarely at agent traffic.
Root cause was .actor/actor.json still carrying "name": "ai-brand-monitor"
from before the Store rename. That is now aligned, which also removes a
standing hazard: a bare apify push resolved that name to no Actor and
would have created a second, duplicate listing rather than updating this one.
test/docs.test.ts gained a guard pinning every Apify URL in the README to the
slug in actor.json, so the two cannot drift apart again.
Added
A measured variance example replaces the hypothetical one. The
"Why one query per prompt is not a measurement" section previously argued from
an invented 2-of-5 example. It now shows a real run — JuXrVfwWxMSfwaas5,
2 prompts x 5 samples x 4 engines, 40/40 collected, 0 errors — where the
commercial prompt was perfectly stable (5/5 on every engine) and the
informational one was not (4/5, 4/5, 1/5, 0/5).
The point that argument had been missing: the true mention rate there is 45%,
and a one-sample audit across four engines can only ever return 0, 25, 50 or
75%. 45% is unreachable in principle, and a flat "brand invisible" 0% comes
up in 3.2% of the 5⁴ possible draws. Both figures are exact enumerations, not
simulations.
Keeping the stable prompt in the example is deliberate: sampling is not
uniformly necessary, it is unequally necessary, and which prompts need it is
not knowable until they have been sampled.
Two images, the first on this listing: a hero and the variance chart, served
from the public key-value store ai-visibility-tracker-assets.
An explicit positioning line against the subscription platforms buyers compare
this against (Profound, Otterly, AthenaHQ).
Changed
Store categories moved from AI, SEO_TOOLS, AGENTS to
SEO_TOOLS, MARKETING, MCP_SERVERS (applied via the API; categories are not a
field actor.json carries). Apify caps an Actor at three. "AI" is already
carried by the title, SEO title and description, so the text search finds it
either way, whereas MARKETING (1,385 Actors) and MCP_SERVERS (1,687) can
only be reached through the category filter — against AI at 7,622 and
AGENTS at 2,902.
[0.4.7] — 2026-08-09
Fixes the Apify automated quality test, which had flagged the Actor as "under
maintenance" after three consecutive days of failing runs. Input schema only —
no code change.
(Builds 0.4.5 and 0.4.6 were pushed on 2026-08-05 without a changelog entry and
carried no behaviour change; the platform build counter had moved on, so this
entry is numbered to match the build it ships in rather than to follow 0.4.4.)
Fixed
maxPrompts and samplesPerPrompt now carry a prefill of 1. Neither
field had one, so the automated test — which runs the Actor with the input
schema's prefilled values — fell through to the Zod defaults of 10 and 3.
Combined with the four prefilled engines that is 10 x 3 x 4 = 120 downstream
Actor calls, which at MAX_CONCURRENCY = 5 and the ~60-100 s a downstream
call takes is 24 waves, or 35-50 minutes. The test requires Succeeded with a
non-empty dataset within 5 minutes, so the default run could never pass it.
Measured on real runs of build 0.4.4 (2026-08-05), which is where those
per-wave figures come from:
Run
Samples
Duration
SWc8fiUpAOx2pYygf
6
2 m 34 s
DpBVbEzl0JlwKMzhr
12
5 m 10 s
TSpxik0PwVCm1SF11
18
8 m 24 s
H0eEQNeBmGeFmihvO
30
8 m 49 s
The prefilled run is now 1 x 1 x 4 = 4 samples, a single concurrency
wave, ~2 minutes end to end. All four engines stay prefilled: multi-engine
coverage is the Actor's headline claim, so the demo run has to show it.
The default values are deliberately left at 10 and 3. A prefill is the
starting point of a Store form, not the recommended configuration, and
samplesPerPrompt: 1 is explicitly not a measurement — both field
descriptions now say so and point at 3 as the floor for a run worth acting
on.
[0.4.4] — 2026-08-05
Documentation correction. No code change.
Fixed
The 0.4.3 notes claimed Apify has no multi-example mechanism and that the
competitors' "examples" were README content. Both were wrong. The claim came
from a page fetch whose markdown conversion dropped the tab bar; the raw HTML
shows an Examples tab on apify/google-search-scraper and on the competitor,
and none on ours.
The real mechanism: the Examples tab is backed by Apify Tasks. A task
appears there once publicConfig.publishedAt is set. Creating tasks is
API-writable and is now done — four exist, one per entry in
.actor/examples.json. Setting publicConfig is not: the API accepts it and
stores null, and no publish route exists in the OpenAPI spec, so publishing
is a Console step. exampleRunInput is a separate, older field that prefills
the Input tab rather than the Examples tab.
Corrected in .actor/examples.json, OPERATIONS.md and the 0.4.3 entry, with
the four task IDs and the exact Console path recorded.
[0.4.3] — 2026-08-05
Ready-to-run examples. Listing content only.
Added
.actor/examples.json — four input examples, one per differentiator: the full
audit, a cheap Google-AI-Overviews-only weekly watch, a genuinely localized
French run, and collect-only. Each carries its BRONZE-tier price.
README Recipes section rendering all four, and the first one published to
the Actor's exampleRunInput.
test/examples.test.ts — validates every example against ActorInputSchema,
recomputes its advertised price from pay_per_event.json and fails above 15%
drift, asserts each appears in the README, keeps the localized example under
$2.50, and rejects an example that lists the tracked brand as its own
competitor.
Changed
The Actor page's Examples tab is backed by Apify Tasks: a task whose
publicConfig.publishedAt is set appears as an example. Creating the task is
API-writable; publishing it is Console-only (the API nulls publicConfig and
exposes no publish route). Four tasks were created from this file; publishing
them is a Console step. exampleRunInput is a separate, older field that
prefills the Input tab, and carries example 1.
The French example's competitor list was ["Axonaut", "Sellsy"] — it listed
the tracked brand as its own competitor. Now ["Axonaut", "noCRM.io"], both
confirmed by a real French AI Overview that names "Axonaut, Sellsy et
noCRM.io". Prompts reduced from 5 to 4 to keep the run under $2.50, since
localized Google costs ~13x the default engine.
README no longer claims an exact unit-test count. The guard could not verify it:
it.each blocks expand at runtime, so a source-level count is always wrong. A
precise number that cannot be checked mechanically should not be published.
[0.4.2] — 2026-08-05
Listing content only. No code, schema or pricing change.
Added
"Use from an AI agent (MCP)" section near the top of the README: the
https://mcp.apify.com?tools=emoubarak/ai-brand-monitor connection URL, three
example prompts a user can say to their agent, and the agent-relevant facts
(pay-per-event, limited permissions, no Standby, collect-only) with the two
cost anchors taken from the existing table — $0.99 for 5 prompts x 2 samples
across four engines, $0.43 for a Google AI Overviews-only check.
The ?tools= query-parameter convention was checked against the current Apify
MCP documentation rather than assumed. One claim was corrected in the process:
the docs state the MCP server only accepts unauthenticated requests for
discovery tools, so running an Actor does require authorising Apify once in the
browser. The section says "no OpenRouter key" rather than "no API key".
Changed
The "Can AI agents run this Actor?" FAQ entry now links to that section instead
of restating it.
[0.4.1] — 2026-08-05
Listing consistency fix. No behaviour change.
Fixed
The published README contradicted itself: the opening said "No API key
required" while the input section still carried the pre-BYOK paragraph "The
OpenRouter key is yours … without a key every metric that depends on analysis
is empty". The second was false as of 0.4.0. Root cause was a stale README in
the repo, not a stale build — the live build already matched HEAD.
Input table was missing analysisMode entirely, and described analysisModel
as accepting "any OpenRouter model ID", which is only true under BYOK.
SUMMARY example showed schemaVersion: 1 and omitted the v2 fields, so it
contradicted the webhook section that tells consumers to branch on version 2.
Stale test count in "Run it locally".
Added
test/docs.test.ts — a drift guard that fails the suite when the README's
input table diverges from input_schema.json, when it names an event absent
from pay_per_event.json or omits a billable one, when the SUMMARY example
falls behind the schema version, or when the documented test count goes stale.
A one-line price anchor near the top: a 3-sample Google AI Overviews prompt
costs about $0.027, which is comparable at a glance against the per-check
prices competitors display.
[0.4.0] — 2026-08-05
Analysis key included by default, collect-only mode, per-engine cost breakdown.
Added
Included analysis key.ANALYSIS_OPENROUTER_KEY (secret Actor env var)
scores answers when the user supplies none, so the Actor now runs with no API
key required — the last onboarding step is gone and it is callable by an agent
with nothing to configure. openRouterApiKey becomes optional BYOK: the user
then pays OpenRouter directly, may use any model, and is billed the reduced
response-analyzed-byok event (~1/3 price). SUMMARY.analysisKeySource
reports which was used.
Model allowlist on the included key — openai/gpt-5.6-luna (default) and
deepseek/deepseek-v4-flash-0731, both validated with real calls against
AnalysisResultSchema at ~$0.0002/call. Anything else falls back to the default
with a warning, so one input field cannot point the owner's key at an expensive
model. Two candidates were rejected by that validation: openai/gpt-5-nano
returned an empty completion (reasoning tokens consumed its budget) and
openai/gpt-4.1-nano returned schema-valid but wrong extractions.
Per-run analysis spend ceiling, mirroring the downstream circuit breaker.
On trip, remaining answers are collected but left unscored.
analysisMode: "collect-only" — no LLM call, no analysis charge, raw
answers and citations only. Collection metrics and their deltas are still
computed; analysis-derived metrics are absent rather than zero.
SUMMARY.costByEngine — samples, billable samples, estimated cost, cost
share and mention share per engine, for deciding which engines earn their place.
Changed
SUMMARY.schemaVersion is now 2. SUMMARY is a webhook payload, so its
shape is a contract; consumers should branch on this field. Version 2 adds
analysisMode, analysisKeySource and costByEngine, and makes
analysis-derived metrics absent in collect-only mode.
report-generated raised from $0.08 to $0.20 (FREE), with proportional
tiers ($0.125 BRONZE). The aggregation and delta layer is the differentiated
value; samples stay cheap. A default run moves +$0.12 at FREE, +$0.075 at
BRONZE — $2.64 to $2.72.
A sample with no analysis is no longer marked analysis_failed when the run is
in collect-only mode; leaving it ok keeps the coverage report meaningful.
[0.3.0] — 2026-08-05
Fourth engine, webhooks, and a listing rewritten around what buyers actually search for.
Added
Gemini as a fourth answer engine, via apify/gemini-search-scraper — the
official Apify Actor, same { queries } input and same sectioned-source output
shape as ChatGPT Search, so it reuses that parser. Measured unit cost $0.00505
(run gePTBPiX5pFk8wSo5), billed as prompt-sampled-gemini at $0.015 BRONZE.
engines now defaults to all four.
Optional webhook. Set webhookUrl and the finished summary — metrics,
coverage and deltas — is POSTed there as JSON at end of run: 10s timeout, two
retries, 4xx not retried. Failures are warned about and never fail the run.
Deliberately not billed: it is a retention feature, not a metered one.
README sections answering the queries buyers actually search: how to track
brand mentions in AI search, how to improve brand visibility in AI search
engines, and what to check before buying an AI search monitoring tool. Plus a
worked example of why one query per prompt is not a measurement, and a
cost-per-check table so the price can be compared against per-check tools.
Changed
Actor title and short description rewritten from keyword data, leading with
"AI Search Visibility Tracker" and covering AI brand monitoring. Title kept
under Apify's 63-character limit.
Run cost examples recomputed for four engines.
[0.2.0] — 2026-08-05
Production hardening. Billing model, per-engine pricing and real market targeting.
Changed — billing (breaking for the operator, invisible to users)
Downstream engine Actors are now called with the developer's Apify token
(DOWNSTREAM_APIFY_TOKEN, a secret environment variable) instead of the token
injected into the user's run. An Actor started via the API runs under the
account of the token used, so the previous behaviour billed users at retail for
the engine scrapers on top of this Actor's pay-per-event charges. A run
without the token now fails at startup rather than silently double-charging.
See OPERATIONS.md for the cash-flow and concurrency exposure this creates.
prompt-sampled is replaced by four per-engine events:
prompt-sampled-google-aio (primary), prompt-sampled-google-aio-localized,
prompt-sampled-perplexity and prompt-sampled-chatgpt. One Perplexity call
costs ~4x one Google AI Overview and a localized one ~13x; a single blended
price made cheap-engine users subsidize expensive ones. Every price is 3x the
measured downstream cost, floor $0.005.
Added
Market targeting for Google AI Overviews. Any market other than US is
served by johnvc/Google-AI-Overview-API, which accepts Google's own gl and
hl parameters. Verified: 10/10 French queries and 3/3 German queries returned
localized AI Overviews with local sources. The official Apify Actor exposes
only queries and cannot localize; Perplexity and ChatGPT Search expose no
country parameter at all.
geoApplied on every sample row, plus sourceActor, so a user can tell which
answers were genuinely localized instead of inferring it. A run warns explicitly
about engines that could not honour the requested market.
maxTotalChargeUsd on every downstream call, plus a per-run circuit breaker
(src/budget.ts) ceilinged at samples x worst-case unit cost x 1.5. On trip,
collection stops and the run reports partial coverage.
OPERATIONS.md: billing exposure, measured costs with run IDs, monitoring to
configure in Console, and the deploy procedure.
Fixed
The downstream circuit breaker under-counted spend by ~170x. run.usageTotalUsd
is not settled when .call() returns — it holds only the $0.00005 actor-start
charge, with the per-result event landing moments later. The budget now charges
max(reported, worst-case unit cost).
Answer analysis was truncated at max_tokens: 800, which silently lost samples
whose answers named many brands: the JSON came back cut off mid-object and
failed validation twice. Raised to 2000, and a truncated completion now reports
itself as truncated instead of as malformed JSON.
[0.1.0] — 2026-08-04
Initial release.
Added
Sampling across three answer engines via the official Apify Actors:
apify/perplexity-search-scraper, apify/google-ai-overviews-scraper and
apify/chatgpt-search-scraper. Every prompt is asked samplesPerPrompt
times per engine, with bounded concurrency (max 5), 3 retries with
exponential backoff and a per-call timeout.
Stratified prompt generation across commercial, informational,
transactional, brand-defensive and comparison intents, from one LLM call.
User-supplied queries bypass generation entirely.
Structured answer analysis via OpenRouter (default openai/gpt-5.6-luna):
brand mention, position, sentiment with evidence, competitors named, and
which brand the answer recommends. Invalid JSON is retried once with the
validation error fed back into the prompt.
Metrics per engine and overall: answer trigger rate, mention rate,
visibility rate, average position, share of voice, recommendation rate,
sentiment distribution and top cited domains — each with its denominator.
Week-over-week deltas from a named key-value store (ai-brand-monitor-state,
keyed by brand + market), including new and lost cited domains.
Pay-per-event monetization: prompt-sampled, response-analyzed and
report-generated. Failed engine calls are not charged. Collection stops
gracefully when the run's spending limit is reached.
Graceful partial failure throughout: engine errors, analysis failures, a
missing OpenRouter key and an exhausted budget all degrade the output and
add a warning instead of aborting the run.
103 unit tests (Vitest) covering metrics, schemas, delta logic, adapters
against a mocked ApifyClient, analysis retry behaviour and the collection
layer. No test touches the network.
npm run local for a fully mocked end-to-end run at zero cost.
Known limitations at 0.1.0
No market targeting (addressed in 0.2.0).
A single blended prompt-sampled event across all engines (addressed in 0.2.0).