LLM Brand Visibility Tracker avatar

LLM Brand Visibility Tracker

Pricing

from $42.50 / 1,000 brand probes

Go to Apify Store
LLM Brand Visibility Tracker

LLM Brand Visibility Tracker

For each query that matters, check whether AI assistants recommend YOUR brand — and which competitors they cite instead. Grounded answers from Perplexity Sonar, GPT and Gemini with your own OpenRouter key. This is GEO: the SEO of the AI era.

Pricing

from $42.50 / 1,000 brand probes

Rating

0.0

(0)

Developer

Tim Zinin

Tim Zinin

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

9 days ago

Last modified

Categories

Share

LLM Brand Visibility Tracker — Is Your Brand Present in AI Answers?

Track whether a grounded AI answer names your brand, where the model reports it in the answer's brand order, which alternatives it names, and which source domains appear in citation annotations. Run the same buyer questions across Perplexity Sonar, GPT, Gemini, or another OpenRouter model and receive one review-ready Dataset row per query × model probe.

Bring your own OpenRouter key. This Actor does not include model access. Provider usage is billed directly to your OpenRouter account; Apify separately charges the Actor start and each successfully delivered probe. Without a key, the Actor performs no model work and writes one free setup row. The Apify start event may still apply.

LLM Brand Visibility Tracker — buyer question to review-ready result

What this Actor sells

Most teams can manually ask one chatbot one question. The operational problem starts when the team has dozens of commercial questions, several markets, multiple models, repeated reporting dates and a need to explain why a row deserves attention. This Actor turns that matrix into structured data:

  • whether the tracked brand was observed as a whole token sequence;
  • the model-reported first-mention position when the answer supplies a brand list;
  • alternative brands/products named in the same answer;
  • structured citation URLs and domains when the provider returns them;
  • separate brand-evidence and citation-evidence modes;
  • freshness, coverage, confidence reasons and explicit data gaps;
  • a conservative recommended review action;
  • provider token usage and providerCostUsd when OpenRouter reports it;
  • stable entity/event IDs for joining repeated exports;
  • failure, retry and replay diagnostics for pipelines.

It is a probe and evidence-normalization product, not an SEO crawler, sentiment engine or ranking oracle. Every row keeps safeToAutomate: false because one probabilistic answer is not enough to publish content, contact a competitor, change a campaign or claim a durable market trend.

Who it is for

GEO and SEO agencies

Create the same bounded query portfolio for every client, export rows after each scheduled run and review brand gaps with citation evidence attached. The Actor makes the matrix repeatable; it does not manufacture a universal visibility score or pretend that all prompts have equal commercial importance.

In-house content and organic-search teams

Check whether category, comparison and problem-aware questions name your product. When an answer names alternatives but not your brand, inspect the cited domains and pages before deciding whether the gap is content, authority, product fit, geography or model variance.

Product marketing and competitive intelligence

Compare which alternatives appear for the same query across supported models and languages. Treat the extracted order as model-authored evidence from that response, not independently measured market rank.

Founders and small teams

Run a small hand-picked query set without buying another monthly dashboard. Use Apify schedules, webhooks and exports when the manual spreadsheet stops scaling. You still need an OpenRouter account and should cap spend in both OpenRouter and Apify.

Analysts and data pipelines

Join on entityId, retain eventId and observedAt, and compare repeated observations in your own warehouse. The Actor itself is stateless: it does not label a change until your downstream system compares two or more runs.

What you get in one row

QuestionField(s)
Did the model answer successfully?found, failureType, retryable, error
Was the brand observed?mentioned, brandEvidenceMode
Where did the model report it?position, positionBasis
Which alternatives were named?competitorsNamed, legacy competitorsCited, brandNamesExtracted
Which sources grounded the answer?citations, citedUrls, citedDomains, citationEvidenceMode, groundingObserved
How complete is the observation?coverageScore, coverageBand
How strongly should it be trusted?confidenceScore, confidenceBand, confidenceReasons
What is still unknown?dataGaps
What should a human do next?recommendedAction, actionPriority, actionReason, safeToAutomate
Can I reconcile provider spend?promptTokens, completionTokens, providerCostUsd, modelAccessMode
Can I join repeated exports?entityId, eventId, observedAt, freshness

Quick start

  1. Create an OpenRouter key and apply the provider-side limit appropriate for your test.
  2. Click Try for free on Apify.
  3. Enter the exact brand name, one to twenty buyer questions, and one to three model IDs.
  4. Paste the key into the secret OpenRouter API key field.
  5. Keep concurrency at 1 for a first run, review the Apify maximum charge, then start.
  6. Open the Dataset and inspect mentioned, evidence modes, cited domains, confidence reasons and data gaps together.

Minimal input:

{
"brand": "Notion",
"queries": [
"best note-taking app",
"best project management tool for a small startup"
],
"models": ["perplexity/sonar"],
"lang": "en",
"openrouterApiKey": "YOUR_OPENROUTER_KEY",
"maxConcurrency": 1
}

Do not commit the key to source control, paste it into a public Task definition or send it in a URL. The Apify Input field is marked secret. The Actor uses the value only in the OpenRouter Authorization header and never intentionally copies it to Dataset rows, OUTPUT or logs.

Input contract

FieldRequiredLimitsMeaning
brandyes1–200 charactersExact brand, company or product token sequence to track
queriesyes1–20 strings; 1,000 characters eachQuestions real buyers might ask
modelsno1–3 IDs; 200 characters eachDefault perplexity/sonar; every model multiplies row count
langnovalid tag; max 35 charactersRequested answer language, default en
openrouterApiKeyfor probesmax 512 characters; secretYour provider credential and provider billing boundary
maxConcurrencynointeger 1–3Parallel provider calls, default 1

Input validation is fail-closed. Values must already have the documented types: numbers are not coerced into strings, arrays are not silently truncated and blank elements are rejected. Exact duplicate queries or models are collapsed so the same literal probe is not billed twice. Case and wording are preserved because prompt wording can change a model answer.

Row count before you run

The requested matrix is:

number of rows = unique queries × unique models

Five queries across three models request fifteen rows. The maximum is twenty queries across three models, or sixty rows. Error/setup/stop rows do not use the paid result-found event, but the one-time Actor start price can still apply.

Model and retrieval policy

The listed grounded configurations are:

Model IDRetrieval requestSupport label
perplexity/sonarPerplexity web search with high search contextlisted_grounded_model
openai/gpt-4o-miniOpenRouter openrouter:web_search server toollisted_grounded_model
google/gemini-2.5-flashOpenRouter openrouter:web_search server toollisted_grounded_model

The retired :online examples are not used for these listed models. You may submit another OpenRouter model ID because this is a BYOK product, but the row is labeled custom_byok_model and may have weak or absent structured citation evidence. A successful HTTP response alone never sets groundingObserved: true.

Model availability, pricing, rate limits and retention are controlled by OpenRouter and the selected upstream provider. Check those terms before processing confidential prompts or committing to a schedule. This Actor does not proxy a hidden shared credential and does not promise a model will remain available forever.

How a response becomes evidence

LLM Brand Visibility workflow — validation, grounding, evidence and action

1. Validate and reserve budget

The Actor validates exact input types and creates the bounded query × model matrix. Before a provider call, it reserves room against the run's Apify maximum charge. That prevents spending the buyer's OpenRouter balance for a new probe when the Actor already knows the Apify budget cannot accept its result.

2. Request an answer and brand list

The tracked brand is not injected into the buyer question. The model receives the original query and an instruction to answer concretely, then append one BRANDS_JSON list containing names it actually used. This makes extraction more consistent, but the list is still model-authored output — not independent telemetry.

3. Match the brand conservatively

The matcher normalizes letter/number tokens and requires the full tracked brand token sequence in a candidate name. Go does not match Google; Notion does not match Notional Systems. HubSpot may match HubSpot CRM, while tracking the longer HubSpot CRM does not silently reduce the target to HubSpot.

When the structured marker is present:

  • mentioned is derived from the extracted ordered list;
  • position is the first matching index plus one;
  • positionBasis is model_reported_brand_order;
  • alternatives are preserved in competitorsNamed;
  • legacy competitorsCited stays populated for backward compatibility.

When the marker is missing or malformed, the Actor falls back to a whole-token scan of answer text. It may still determine mention/no mention, but position and competitors remain empty rather than being invented.

4. Classify citation evidence

Citation evidence has three explicit modes:

  • structured_url_annotations — provider-supplied URL annotations were observed;
  • inline_url_fallback — URLs appeared only inside answer text;
  • none — no auditable URL was returned.

URLs are limited to HTTP(S), credentials and fragments are rejected/removed, common tracking and secret-bearing parameters are stripped, duplicates are collapsed and annotation titles are kept. The Actor does not fetch cited pages, prove their content, validate reachability or determine whether the page supports every claim in the answer.

5. Produce a review decision

Coverage and confidence answer different questions:

  • coverage asks how much of the expected observation contract is present — answer, extracted brand order, citation evidence and usage metadata;
  • confidence asks how strong the available evidence is for review routing.

A structured citation plus model-authored brand list currently reaches confidence 80/medium, not high, because neither the order nor the recommendation is independent ranking telemetry. Missing structured grounding caps confidence further. confidenceReasons explains the score; dataGaps names what remains unresolved.

ActionWhen it appearsHuman interpretation
REVIEW_OWN_MENTION_AND_CITED_SOURCESBrand mentioned and structured grounding observedInspect wording, context and cited pages before acting
REVIEW_COMPETITOR_GAPAlternatives named, tracked brand absent, structured grounding observedCompare competitor/source footprint; do not assume causality
VERIFY_GROUNDING_BEFORE_ACTIONAnswer succeeded without strong citation evidenceRe-run or verify manually before strategy changes
FIX_INPUT_KEY_MODEL_OR_PROVIDERProbe/configuration failedFollow failure and retry diagnostics first

safeToAutomate is always false. The recommended action is a queue label, not permission to edit a website, launch outreach, publish a comparison page or make a commercial claim automatically.

Real legacy output example

The following core fields come from an actual historical run on 2026-07-26. They demonstrate the backward-compatible columns; the current version adds evidence and decision fields described above.

{
"brand": "Zzqfake Nonexistent Xyz Corp",
"query": "best CRM software",
"model": "perplexity/sonar",
"lang": "en",
"found": true,
"mentioned": false,
"position": null,
"competitorsCited": [
"Salesforce",
"HubSpot CRM",
"Zoho CRM",
"Pipedrive",
"Microsoft Dynamics 365"
],
"promptTokens": 96,
"completionTokens": 234,
"checkedAt": "2026-07-26T13:27:30.617Z"
}

The historical row did not retain structured citations or decision scores, so none are fabricated in this example. Current rows add those fields from the current response and code path.

Field dictionary

Identity and observation time

  • entityId — stable hash identity for brand + query + model + language;
  • eventId — observation identity including time, mention state and extracted names;
  • checkedAt / observedAt — when this model response was observed;
  • firstSeenAt / lastSeenAt — equal for this stateless one-response observation;
  • freshness.cacheReused — always false; this Actor does not serve a cached model answer.

Brand evidence

  • mentioned — whether the full tracked-brand token sequence was observed;
  • position — one-based index only when a model-reported list contains the brand;
  • positionBasis — makes the origin of that position explicit;
  • brandNamesExtracted — bounded ordered list produced from the response marker;
  • competitorsNamed — extracted names that do not match the tracked brand;
  • competitorsCited — legacy alias retained for existing consumers;
  • brandEvidenceMode — structured model list or answer-text fallback.

The word “competitor” means an alternative name in this answer, not a verified corporate competitor, substitute product, market-share peer or legal entity.

Citation and grounding evidence

  • citations — normalized URL/title/evidence-type objects;
  • citedUrls / citedDomains — convenient flattened arrays;
  • citationEvidenceMode — structured annotation, inline fallback or none;
  • groundingRequested — whether the transport requested retrieval;
  • groundingObserved — true only for structured URL annotations;
  • sourceEvidence — citation objects repeated in a decision-oriented form with reachability false.

Quality and decision fields

  • coverageScore / coverageBand — completeness of the observation contract;
  • confidenceScore / confidenceBand — conservative evidence confidence;
  • confidenceReasons — human-readable score drivers;
  • dataGaps — nondeterminism, model-authored order, unfetched citation content, missing sentiment, weak grounding and/or absent independent position measurement;
  • recommendedAction, actionPriority, actionReason — manual queue routing;
  • safeToAutomate — always false.

Cost and failure fields

  • promptTokens, completionTokens — provider-reported token counts when available;
  • providerCostUsd — provider-reported cost when available, useful for reconciling BYOK spend;
  • modelAccessMode — always buyer_openrouter_key for model probes;
  • modelSupport — listed grounded or custom BYOK model;
  • failureType — configuration versus model-check failure;
  • retryable — conservative retry hint, not a guarantee;
  • setupRequired — true on the no-key setup row;
  • error — redacted bounded diagnostic.

Pricing and two separate bills

This workflow has two billing boundaries.

Apify bill

On the FREE tier the configured price is $0.005 per Actor start + $0.05 per successfully delivered query × model row. Paid Apify tiers have lower event prices. The public Pricing tab is authoritative for your account.

Examples using FREE-tier Apify prices:

  • 1 query × 1 model = 1 row: $0.005 + $0.05 = $0.055;
  • 5 queries × 2 models = 10 rows: $0.005 + $0.50 = $0.505;
  • 20 queries × 3 models = 60 rows: $0.005 + $3.00 = $3.005.

The runtime accepts only the six configured tier pairs and checks the combined result/Dataset event price before work. A successful linked Dataset write must return the exact Apify SDK 3.7.2 aggregate receipt: one paid result-found event plus one zero-price default Dataset-item event. Ambiguous delivery fails the run and sets replaySafe: false because automatic retry could double charge or duplicate a row.

OpenRouter bill

Every model call uses your secret openrouterApiKey, so tokens/search/tool usage is billed directly by OpenRouter and the selected provider. The Actor does not mark it up or include it in the Apify row price. Actual provider cost varies by model, retrieval behavior, prompt and answer. Use provider-side limits and inspect providerCostUsd rather than relying on a fixed estimate.

Free and partial rows

No-key setup rows, provider failures and budget-stop explanations do not use result-found while the default Dataset-item event remains unpriced. The Actor start can still be charged. OUTPUT records requested, delivered and error counts plus setup, budget, key and replay state.

If the buyer's Apify maximum charge cannot reserve another row, further provider work is not started. A final row that was fully delivered is not mislabeled partial merely because no future row would fit.

Failure and recovery contract

SituationDataset / OUTPUT behaviorRetry guidance
Key omittedOne setup row; no model calls; OUTPUT setupRequired:trueAdd key, then run
Key invalid/expired (401)One diagnostic probe; run fails honestlyFix/reissue key first
Key out of credits (402)One diagnostic probe; run fails honestlyFund/change key first
Provider/network/model failureFree full-shape row with redacted errorUse retryable and provider status
Apify budget exhaustedRemaining work not started; partial OUTPUT when applicableRaise cap only if intended
Pricing mismatchFail before model workOperator must reconcile Pricing and source
Delivery receipt ambiguousRun fails; replaySafe:falseInspect Dataset and charge receipt before retry

An invalid or unfunded buyer key is not reported as a healthy product success. The first job is a serial probe; only after it passes can the bounded concurrency pool start, avoiding several identical authentication failures.

Privacy and security boundaries

  • Your OpenRouter key is secret input and is used only for the provider Authorization header.
  • Provider error text is bounded and scrubbed for the exact key, bearer tokens and OpenRouter-style key patterns before storage or logging.
  • Queries, brand names, answer snippets, extracted names and citation URLs are stored in the run's Apify Dataset. Do not submit confidential prompts unless that retention is acceptable.
  • The full raw provider response is not retained; the answer excerpt is capped at 280 characters.
  • Citation URLs are data, never executed. This Actor does not crawl them.
  • No platform-owned provider fallback exists. BYOK means the buyer controls provider spend and provider-account policy.
  • The Actor is bounded to 20 queries, 3 models, concurrency 3, 60-second provider calls and a 2 MB response body.

Review Apify, OpenRouter and upstream-provider terms for your jurisdiction and data class. This README is a product contract, not legal or privacy advice.

Integrations

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('zinin/llm-brand-visibility').call({
brand: 'Notion',
queries: ['best note-taking app'],
models: ['perplexity/sonar'],
lang: 'en',
openrouterApiKey: process.env.OPENROUTER_API_KEY,
maxConcurrency: 1,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map(({ mentioned, competitorsNamed, citedDomains, recommendedAction }) => ({
mentioned, competitorsNamed, citedDomains, recommendedAction,
})));

Python

from apify_client import ApifyClient
import os
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("zinin/llm-brand-visibility").call(run_input={
"brand": "Notion",
"queries": ["best note-taking app"],
"models": ["perplexity/sonar"],
"openrouterApiKey": os.environ["OPENROUTER_API_KEY"],
"maxConcurrency": 1,
})
rows = client.dataset(run["defaultDatasetId"]).list_items().items

Webhooks, n8n, Make and warehouses

Use the Actor-run-succeeded webhook and read resource.defaultDatasetId. Route found:false rows to operations, VERIFY_GROUNDING_BEFORE_ACTION to an evidence-review queue and grounded mention/gap rows to analysts. Export JSON/CSV/Excel from Apify or load rows into BigQuery, Snowflake, Postgres or Sheets. Keep IDs, observation time, evidence mode, confidence reasons and gaps together.

Never branch only on mentioned. A useful automation checks at least:

found
groundingObserved
brandEvidenceMode
confidenceScore
dataGaps
recommendedAction
safeToAutomate

Because safeToAutomate is false, the final business action remains a human decision.

Repeat-monitoring workflow

The Actor is stateless but schedule-friendly:

  1. Freeze a commercially meaningful query/model/language matrix.
  2. Run on a cadence that matches the decision — weekly or monthly is often more interpretable than noisy hourly probes.
  3. Store each Dataset externally using entityId, eventId and observedAt.
  4. Compare mention state, model-reported order, alternative names, cited domains and evidence modes.
  5. Require repeated observations before labeling a trend.
  6. Review changed citations/pages manually before content or PR work.

Prompt wording, model releases, provider routing, geography and search results can change answers. Keep the matrix stable when measuring change, and treat a model-ID change as a methodology change.

Important limitations

  • A mention is not a recommendation, positive sentiment, endorsement or purchase intent.
  • Absence in one answer is not proof that a model never knows or recommends the brand.
  • position is the order in a model-authored list, not a universal rank or market share.
  • Extracted alternatives are names in that answer, not verified legal competitors.
  • Structured citation annotations prove that URLs were returned, not that every answer claim is correct or supported by those pages.
  • Cited pages are not fetched, archived, licensed or checked for availability.
  • Answer generation is nondeterministic; repeated identical prompts may differ.
  • Language and geography can change retrieval and brand naming.
  • Custom models may ignore the brand-list instruction or omit citation annotations.
  • The Actor does not calculate sentiment, share of voice, traffic, conversion, revenue or causal impact.
  • The Actor does not persist a historical baseline or send alerts by itself.

Troubleshooting

I only received a setup row. Add your OpenRouter key. Model access is not included. The setup row is free, but the Apify start event may already have been charged.

The run failed with 401. The supplied key is invalid, expired or disabled. Replace it before retrying; repeated runs cannot repair provider authentication.

The run failed with 402. The OpenRouter account does not have sufficient credits for this call. Fund the account or use another authorized key.

The answer mentions my brand but mentioned:false. Inspect the exact tracked name, brandNamesExtracted and brandEvidenceMode. Aliases, abbreviations and parent-company names are not silently treated as equivalent. Run intentional variants as separate tracked brands.

Position is null. The response did not provide a usable ordered brand list or the target was not in it. The Actor will not infer a numeric position from arbitrary prose.

There are names but no citations. Brand extraction and citation grounding are independent. Treat the row as weak evidence and follow VERIFY_GROUNDING_BEFORE_ACTION.

The same query changed. This can be normal model/retrieval nondeterminism. Compare timestamps, model IDs, evidence modes and cited domains; repeat before declaring a trend.

The run stopped for budget. Review OUTPUT, your Apify maximum charge and the matrix size. The Actor reserves Apify budget before starting more provider work.

Delivery is marked unsafe to replay. Inspect both Dataset items and charged events. An automatic retry after an ambiguous linked receipt may duplicate a row or charge.

Acceptance checklist for buyers

Before operational use, confirm:

  • the tracked brand name and aliases are intentionally defined;
  • queries represent real buyer questions and remain stable across comparisons;
  • the chosen model IDs currently support the required retrieval behavior;
  • OpenRouter and Apify spend limits match the full matrix;
  • structured versus fallback citation evidence is visible in your export;
  • downstream logic keeps confidence reasons and data gaps;
  • no automated action ignores safeToAutomate:false;
  • retention of prompts, snippets, names and URLs is acceptable;
  • repeated observations are required before a trend claim.
ActorWhat it adds
AI Overview Citation TrackerMap which source domains and exact URLs AI answers cite
AI Answer Change AlertCompare a query's answer/citation state over time
AI Crawler Access CheckerCheck whether major AI crawlers can access a website
Domain Health CheckerAdd DNS, TLS and email-authentication website signals
Social Preview CheckerVerify how campaign URLs render on major sharing platforms

FAQ

Does this work without an API key? No. It is intentionally BYOK. Without a key it returns one setup row and performs no model probes.

Why charge an Apify row if I pay OpenRouter too? OpenRouter charges model/retrieval usage. The Apify result event pays for validation, budget reservation, orchestration, extraction, citation normalization, decision enrichment, schemas, exports and recovery semantics.

Is position an AI-search ranking? No. It is the first matching position in a model-authored brand list for one response, labeled with positionBasis.

Are competitorsNamed verified competitors? No. They are alternative names extracted from the answer. Validate company/product relationships separately.

Can I use a custom model? Yes, with your OpenRouter key. It is labeled custom and may not provide structured grounding.

Can an agent call this Actor? Yes, through the Apify API, SDK or MCP integration. Keep the final business action behind human review.

Does it give SEO or investment advice? No. It reports one model observation and conservative review metadata.

Found a reproducible defect or unsupported model behavior? Open an issue on the Actor page with the run ID and non-secret input shape. Never include your provider key.


Built by zinin. Questions? Telegram @timzinin.