Skip to main content

Methodology

How the numbers on your dashboard are made — what we sample, what we count, and how much of any of it is certain.

Last updated: 15 August 2026

On this page18 sections

What visibility means

Visibility is the share of sampled answers that mention you: answers that mentioned the subject, divided by the answers we sampled in the range. Only runs that completed count — a request that errored is dropped from both sides of that fraction rather than recorded as an absence.

It describes our sample. It is not a census of everything an answer engine has ever said about you, and we do not present it as one.

Any pooled figure — a brand, a topic, an engine, a report — is computed across the prompts you chose to track. The estimate is therefore deck-dependent: adding a prompt you do badly on lowers it and removing one raises it, without anything having changed in the world. It estimates visibility across your tracked deck, not visibility, and the two are only as close as your deck is representative of what people actually ask.

How we sample

We run each of your prompts against each answer engine you have enabled and store every answer that comes back, once per sample slot per UTC day.

Every plan takes 1 scheduled run per prompt, per engine, per day. That is the baseline the cadence below builds on, and 3 is the ceiling no plan and no cadence goes above. We would rather publish the number we actually run than a larger one we would have to trim to fit the day’s budget: a scheduled run count you cannot rely on is worse than a small one you can. If you need more resolution on a particular prompt, the spot check below buys it on demand rather than making you wait for a cadence.

The cadence sits on top of that baseline. Daily takes the plan’s count every day. Weekly takes the same count on Mondays, UTC, and nothing on the other six days. Adaptive scales with demand: a prompt with 1,000 or more monthly searches is worth 3 samples a day and 100 or more is worth 2, and we take whichever is larger, the plan baseline or that volume figure. It is a maximum of the two, not a multiple of them — adaptive never takes fewer runs than your plan already buys, and never more than 3.

Extra runs buy two things and no others: they narrow the confidence band, and they make finer appearance rates representable at all. Below the floors in the next section a rate is not printed, so the first runs a plan buys are what makes a number appear.

When we withhold the number

Below 5 completed runs we do not print a rate. What you get instead is the count and the interval — how many answers we have, and the 95% band that count supports. The denominator and the band are never withheld; the single number is.

The reason is resolution rather than uncertainty, and they are different defects. At n=4 every answer the measurement can give is one of 0%, 25%, 50%, 75% or 100%, so a printed 33% is not a value the sample could ever have produced. The integer claims a precision the sample cannot express, and an interval printed beside it does not repair that.

A trend makes that claim in every period it draws, so the floor for one is higher: at least 10 completed runs per period. Your brand’s visibility chart enforces it directly: a day, week or month with fewer runs than that keeps its confidence interval and loses its point, and the line breaks across the gap rather than being drawn through it. A chart can therefore show you nothing but bands, which is the honest reading of a sample that thin — grouping by week or month pools more runs into each period and is the fix. We do not draw a trend line for a single prompt anywhere in the product either — a prompt’s history is shown as the runs themselves, per engine and per day, which are counts rather than estimates. The floor is deliberately stricter than the three-run minimum the change rule below uses: a drawn line makes a claim to every reader who never opens the change feed.

The spot check

The cadence answers what a prompt’s appearance rate is over time. It cannot answer “is that true right now”, because the runs it would answer from happened at some point in the last day and there are at most three of them. So you can ask for up to 10 runs of one prompt, on each engine you have enabled, issued at the same moment, on demand — and you see every individual run, including the ones that disagree with each other. Those runs count: they are the same rows the scheduler writes, so they widen the day’s sample and tighten the day’s band exactly as scheduled runs do.

Its limit belongs in the same breath. We sample each engine through its API. A consumer app on a phone routes differently, personalises per account and can be running a different model revision, so a single answer on a phone disagreeing with the distribution is expected, and is not evidence that either measurement is wrong.

Which engines we cover, and how

Not every answer engine can be reached the same way, and the difference matters more than a logo on a pricing page suggests. Some publish an API we call directly. Some publish nothing at all, so the only way to read what they actually say is through a data provider that fetches the page a person would see. And one of them we cannot read honestly at all, so we do not report a number for it.

A scraped surface is closer to what a user sees, and more fragile — the vendor can change or block it. A vendor API is stable, and is often not the product people mean: the ChatGPT API is not chatgpt.com. We would rather hand you that distinction than average it away.

ChatGPTHow we reach itVendor APIOpenAI API (gpt-4o-mini)Searches the live webNo — answers from model weightsWhat that costs you in accuracyThe API model, not the ChatGPT product. It answers from model weights with no web search, so it reflects what the model knows rather than what chatgpt.com would retrieve today.
ClaudeHow we reach itVendor APIAnthropic API (claude-sonnet-5)Searches the live webNo — answers from model weightsWhat that costs you in accuracyThe API model, not the Claude product. No web search on the sampled call, so citations come from the answer text rather than from a live retrieval.
GeminiHow we reach itVendor APIGoogle Generative AI API with Search groundingSearches the live webYesWhat that costs you in accuracyGrounded through the google_search tool, so sources are real — but this is the API's grounding, not the Gemini app's, and the two can retrieve differently.
PerplexityHow we reach itVendor APIPerplexity API (sonar)Searches the live webYesWhat that costs you in accuracySearch-native and genuinely cited. We book the low search-context tier; a wider context would retrieve more and cost more.
Google AI OverviewsHow we reach itScraped surfaceDataForSEO (google organic SERP)Searches the live webYesWhat that costs you in accuracyRead by scraping a real Google results page through a data provider. Google does not publish an API for this, so coverage depends on that provider and on Google continuing to serve an Overview for the query — an absent Overview is reported as absence, not as an error.
Google AI ModeHow we reach itScraped surfaceDataForSEO (google AI Mode)Searches the live webYesWhat that costs you in accuracyNobody has a Google AI Mode API, us included. This is the real consumer surface read through a data provider, single-turn only, and it can change or be blocked by Google without notice. Anyone selling you an 'AI Mode API' is selling you this. Our provider serves it in English only, so a location slice moves where the search is issued from and never the language it comes back in.
Microsoft Copilot (Copilot Search on Bing)How we reach itNot coveredSearches the live webWhat that costs you in accuracyNo honest read path at present. Microsoft retired the Bing Search APIs in August 2025 and ships no public Copilot API; the documented successor grounds a model of our own choosing in Bing results, which is not what a person sees in Copilot. No data provider we use reaches the Copilot surface either — Bing's own occasional AI summary is a different thing on a different page, and reporting it as Copilot would be a number about the wrong product. We do not sample it, so there is no Copilot figure anywhere in the app.
GrokHow we reach itVendor APIxAI API (grok-4.6)Searches the live webNo — answers from model weightsWhat that costs you in accuracyxAI's own endpoint, but the sampled call runs UNGROUNDED — live web search is a separate server-side tool we do not yet enable, so Grok answers from model weights. Treat it as what Grok knows, not what grok.com would look up.
Meta AIHow we reach itNot coveredSearches the live webWhat that costs you in accuracyNo API, and no data provider we trust reads the surface. We do not sample it, so there is no Meta AI number anywhere in the product. It stays listed so its absence is visible rather than quiet.

Engines marked Not covered produce no number anywhere in the product. They are listed rather than omitted because a gap you can see is worth more than a shorter table.

Locations and languages

A slice is a language, a location, or both — French (France), Paris, France, or French (France) — Paris, France. Each slice is sampled separately and keeps its own answers, so it is its own measurement rather than a filter over a shared one. A brand can run up to 12 of them, because every slice is another run per prompt, per engine, per day.

What a slice can actually do depends on the engine, and the two search surfaces can do more than the rest. Google AI Overviews reaches us through a search API that takes both a real location and a real language, so the answer comes from that place in that language. Google AI Mode takes the location but is served to us in English only, so a slice moves where that search is issued from and never the language it comes back in. The engines we call directly have no location parameter at all: language we can ask for, a city we cannot. We will not dress any of those three up as each other.

EngineWhat a slice changes
ChatGPT (OpenAI)Language only
Claude (Anthropic)Language only
Google GeminiLanguage only
PerplexityLanguage only
Google AI OverviewsLocation and language
Google AI ModeLocation only
Microsoft CopilotNot sampled
Grok (xAI)Language only
Meta AINot sampled
Language only.
We ask for the answer in the slice's language, which changes what comes back. There is no way to ask this engine for a city or a country, so the location half of a slice changes nothing about the call and we do not pretend otherwise.
Location and language.
The search really is issued from the slice's place, in the slice's language: the provider takes both as real search parameters, and the answer comes back from there.
Location only.
The search really is issued from the slice's place, but our provider serves this surface in English only — so the location half of a slice changes the answer and the language half cannot, and we do not pretend it does.
Not sampled.
In the catalog, not yet measured — there is no adapter, so this engine produces no answers, no slices and no numbers at all.

Per-slice numbers are measured over that slice’s answers only. Splitting a brand four ways divides the sample four ways rather than multiplying it, so each slice carries its own sample size and its own 95% interval, on exactly the terms set out in Which numbers carry a band. Comparing two slices is comparing two samples, and the bands are the part of that comparison that matters.

Ads around the answer

Whether a rival is paying to sit next to your brand is a question about one specific surface at a time, because what we can see differs by surface. Where the results page that served an answer comes back to us with its paid slots attached, we read them and can name the advertisers. Where we reach an engine through an API that carries no ad slots, we cannot see ads at all — and that is not the same as there being none.

EngineWhat we can see
ChatGPT (OpenAI)Ads exist, we cannot see them
Claude (Anthropic)Ads exist, we cannot see them
Google GeminiAds exist, we cannot see them
PerplexityAds exist, we cannot see them
Google AI OverviewsWe see the ads
Google AI ModeAds exist, we cannot see them
Microsoft CopilotNot sampled
Grok (xAI)Ads exist, we cannot see them
Meta AINot sampled
Ads exist, we cannot see them.
We sample this engine through a route that carries no ad slots, so a zero here is a limit of the route, not evidence that nobody is advertising. We would rather say that than print a zero.
We see the ads.
The data provider returns the ad slots from the results page that served this answer, so we can name the advertisers. We do not claim the ad sat inside the AI answer itself: placement varies and the payload does not say which.
Not sampled.
In the catalog, not yet measured — there is no adapter, so we ask this engine nothing and there is nothing to look at.

So a run on an engine we cannot see ads on is excluded from the sponsored rate entirely: it moves neither the numerator nor the denominator, and we print the count of excluded runs beside the rate rather than folding it in. A tool that quietly counts blind runs as ad-free reports a lower sponsored rate the more engines it cannot see.

Two limitations to state plainly. First, the parsing is proven against recorded search-provider payloads — real responses pulled from the provider, though none of the ones we hold happened to carry an ad — and a live search API key is configured on this deployment, so ads reported here are read from live result pages.

Second, we read the paid text results on the page and nothing else. Paid Shopping ads are not detected at all. Google’s shopping block carries free product listings alongside paid ones and the payload does not say which is which, so counting it would inflate the one number this section exists to report. A sponsored rate here is a rate of text ads, and a Shopping-only results page reports zero ads rather than a guess.

AI revenue: measured, and modelled

Three numbers, and they are never added together. The first is measured: conversions and revenue that Google Analytics attributed to an AI assistant on the session that converted. We report what GA4 measured and do no arithmetic on it.

The second is AI-assisted, also measured by GA4, under its first-touch attribution — the visitor arrived from AI and something else closed the sale. It overlaps the first figure by GA4’s own definitions, so it sits beside it and is never summed with it. A tool that adds those two together is selling you the same conversion twice.

The third is modelled, and we label it modelled. Between 35% and 70% of visits from AI assistants arrive with no referrer — mobile in-app browsers strip it, people paste URLs, native apps send nothing — and analytics files them as Direct. Our beacon runs on your page, so it sees visits GA4 does not. The gap between the two counts, on the same site on the same day, is measured on both sides. The revenue on that gap is not: we model it at your own site-wide conversion and revenue-per-session rates, print the visit counts it was built from, and keep it out of the measured totals. When there is no site-wide rate to model with, we show nothing rather than a zero.

Coding-agent traffic

Coding agents fetching your docs are their own channel, not another crawler, so they are counted separately. We identify Claude-Code, Cursor, Devin, opencode by their request user-agent.

Three we deliberately do not claim, because we cannot identify them without guessing, and a guess here would inflate your numbers:

  • WindsurfNo distinct request user-agent. The only string in circulation is a generic Go RPC library talking to Windsurf's own backend, so matching it would misclassify unrelated traffic.
  • OpenAI CodexDocumented as sending no User-Agent header on its HTTP transport, so its requests are indistinguishable from raw HTTP in any server log.
  • GitHub CopilotIts published agent token is the bare word “Code” — too ambiguous to match without inflating your numbers with false positives.

Why two runs disagree

Answer engines are non-deterministic. The same prompt, sent to the same engine an hour later, can come back with a different set of brands in a different order citing different pages, with nothing having changed on your site in between. That is a property of the engine, not a fault in the measurement, and it is the reason the honest objection to this whole category exists: a tool that shows you one integer today and a different integer tomorrow is showing you the engine’s variance and labelling it your performance.

We cannot make an answer engine deterministic and we do not claim to. What we can do is measure how uncertain each number is. Every prompt is sampled repeatedly on a stated cadence, every proportion we report says how many answers it was measured over, and every one carries a 95% interval computed from that count. One answer is an anecdote. An appearance rate over a stated number of answers, with the band around it, is a measurement.

Sampling more often narrows the band and makes a finer rate representable. It does not steady the engine and it does not turn a small difference into a real one. That is what the plan baseline and the adaptive cadence above are spending their extra runs on. Where the band stays wide, that is the honest state of the measurement, and we would rather print it than round it away.

Which numbers carry a band

Sampling an answer engine is sampling. Ask the same question twice and you can get two different answers, so 40% measured over 10 answers and 40% measured over 400 are not the same claim, and we do not print them as though they were.

Visibility is reported with a 95% Wilson score interval. We use Wilson rather than the textbook normal approximation because the normal one breaks down exactly where this data lives — small samples, and proportions close to 0% or 100%, where it happily returns a band reaching below zero or above one hundred.

Not every number carries a band, and we would rather say which. Share of voice is a ratio of counts and is shown without an interval. The position distribution is raw counts. Sentiment scores are averages, not proportions, and a proportion interval would be the wrong instrument for them. Where you see a band, it is the measurement telling you how far to trust it; where you do not, the number is a count or a mean and should be read as one.

When we call it a change

A day-on-day movement in a sampled number is not automatically news. We report one as a change only when it clears three conditions at once, and the rule is fixed rather than tuned per account.

The visibility movement has to be at least 10 percentage points. The two days’ 95% intervals have to be separated — the lower bound of the higher day above the upper bound of the lower day, with no overlap at all between them. And both days need at least three completed runs for the subject and engine being compared; a day with fewer is treated as no data rather than as a low number. The day we compare against is the most recent earlier day that has results, searched up to seven days back, and if there is none inside that window there is nothing to compare and we say nothing.

A leaderboard move is held to the relational form of the same test. Passing a competitor is a claim about two subjects, so we report it only when your interval and that competitor’s interval are separated on the day of the move — a subject-against-itself check would say nothing about whether the two can be told apart. A subject at zero visibility on both days does not move, whatever the ordering did. Citation changes are reported only at the boundary: none before and some now, or the reverse. A count that went from nine to seven stays on the chart and does not become an event.

The consequence is that we report fewer changes than a tool that reports every wobble, and that is the intended consequence rather than a limitation we are conceding. A change we do not report is not a change that did not happen — it is a change we could not distinguish from sampling noise, and saying so is the only version of this we can defend.

Position and share of voice

Average position is the mean first position at which you appear across answers that mention you — 1 is first, and answers that never mention you are not averaged in. Repeating a name inside one answer does not give that answer extra weight. Visibility uses the same one-answer-one-observation rule, with non-mentioning answers retained in its denominator.

Share of voice compares your mentions with every mention the sampled answers made about a subject we were reading for at the time — your brand and the rivals tracked when each answer was read. Stop tracking a rival and its past mentions stay in the denominator rather than inflating everybody else; start tracking one and its mentions join the denominator from then on, so tracking one more competitor can lower your share or leave it unchanged — never raise it. A brand you have never tracked is never extracted at all, so this is not a share of the whole market either.

The position distribution — how often you land #1, #2, #3, #4 or #5+ — is raw counts, and it carries no confidence interval. Nothing is being estimated there.

Citation verification

When an answer cites a URL we fetch it from our own servers and record what happened. There are four states, and one of them is “we have not looked yet”.

Unchecked is where every citation starts, and it is what you see until verification has run against that URL. It is shown as its own state rather than folded into one of the others, and it still counts as a citation — we are not going to quietly drop a link because we have not got to it. Verified means the URL resolves to a real page. Broken means we reached the web and did not get the page — a 5xx, a block, a timeout, or any other non-success response, including a 429 rate limit or a 451; it still counts as a citation and is flagged in the interface. Hallucinated means there is no page there and no reason to expect one: an invalid address, a dead domain, a 404, or a 410 — the last of which says the page is gone rather than never having existed. Those are excluded from every cited count.

That last one is the point. Models invent citations, and a tool that counted them would be reporting a link which has never existed as a win.

The AEO score

AEO is answer engine optimisation — making a page easy for an AI answer to read and quote. We audit each monitored page against a fixed list of deterministic checks, split into two buckets: Technical checks, and the answer-quality and content checks that make up AEO.

Each check carries a weight by severity — critical 4, high 3, medium 2, low 1 — and the score is the weight a page passed over the weight it was eligible for. Eligible is the operative word: a check that cannot apply to a page leaves the denominator rather than counting as a failure, so a homepage is not marked down for lacking an author byline. A page we could not fetch at all scores zero on both. Site-wide checks — robots.txt, the sitemap, llms.txt — do not score any individual page; they apply a flat penalty to the site rollup.

It is a readiness score, and that is its limit. It says how quotable the page is, not whether any answer engine has actually cited it — visibility and citations measure that, and a page can score 100 while never being mentioned. The percentile shown beside it is a published curve from the score itself, not a measured cohort of other sites.

Citation readiness, and what we will not claim

The AEO score above says how quotable a page is. The obvious next question is whether a quotable page actually gets cited more often — and that is a prediction, which is a different kind of claim than a measurement. So we built the score, wrote down in advance what would count as evidence for it, and published the test alongside the number.

Citation readiness scores each audited page on four families of signal we already check: structure (5 checks), schema (6 checks), freshness (2 checks), extractability (7 checks). Every factor is shown wherever the score is: open a page and you get the four families and the named checks under each, passed and failed. There is no path in the product where this number appears without the reasons for it.

The weights are the same severity weights the AEO score uses — critical 4, high 3, medium 2, low 1 — and the four families are averaged equally. Those weights were chosen for auditing, before anyone looked at which pages got cited, and they are not fitted to the citation data. That is deliberate and it is the whole reason the test below means anything: a score whose weights were tuned until it separated the data cannot then be validated against that same data. Tools do this and report the result as accuracy.

The bar, written down before we ran it. Take a brand with at least 40 scored pages, at least 10 of them observed cited and at least 10 observed uncited. Compare the citation rate of the top 33% of pages by readiness against the bottom 33%, each with a 95% Wilson interval. The score passes only if those two intervals do not overlap at all and the top third is the higher — the same separation rule we use before calling a day-on-day movement a change, rather than a second, looser standard invented for our own product claim. A brand below those floors is not a weak result; it is no result, and it reports as one.

We corrected this bar once, and it is worth saying why. It was first written as 100 pages compared by top and bottom tenth, to match the framing this category publishes in. That was unreachable: we cap a brand at 100 monitored pages, so it demanded a perfect 100 out of 100, and a single unfetchable page put it permanently out of reach. A test that cannot be run is not a strict standard, it is an inert one — it would have guaranteed this refusal forever whether or not the score works, which is the opposite of a commitment. We changed it while every result was still “not enough data”, so there was no outcome to tune toward; relaxing a bar that had failed would be a different and much worse act. The cost is that thirds are not tenths — comparing the extreme tenths of a list separates more easily — so our version is the less flattering one, and it is not a like-for-like comparison with anyone else’s published tenth.

That bar has not been cleared yet, so we make no predictive claim. Citation readiness ships as what it can defend — an audit-factor score, telling you which pages are structurally weakest and what to fix on them. It does not tell you that a page will be cited, it is not shown as a probability, and we are not going to call it a likelihood until the test above says we may. Observed citations are what measure citations; this number measures the page.

Hallucinated citations never count as evidence a page earned one, here or anywhere else — a fabricated URL on the outcome side of a validation test would corrupt the very thing the test exists to check.

Fan-out queries

Some answer engines run their own web searches before they answer, and the question they search is often not the question you asked. Where the engine reports those searches, we store them against the answer and label each one relative to your prompt: verbatim, a word transformation (a rewording or reordering), an expansion that adds terms, or novel — a query with little in common with your prompt at all. The labelling is a deterministic comparison of the words in each; no model is involved, and no model gets to grade its own work.

Only engines that publish their search list produce fan-out rows, which today means Google-grounded answers. An empty fan-out is therefore not a finding: it means that engine did not tell us what it searched. We keep at most 20 queries per answer, deduplicated.

What we do not claim

We do not see every answer an engine gives. We see the ones we sampled, and every number here describes that sample.

Answer engines are non-deterministic and change without telling anyone. A movement between two days can be a model update rather than anything you did, and a methodology that hid that from you would be worth less than this one.

We do not sell rank as a metric. A position in a single AI answer is not a stable enough thing to sell: ask the same question twice and the order of the names moves, so one position is largely a record of which run you happened to catch. What survives repetition is the appearance rate — how often you are named across the answers we sampled — and that is the number everything here is built on. We do show an ordering, and we will tell you when it moves; what we will not do is treat a position as a measurement in its own right. The ordering is a view of the measured appearance rates, each with its interval attached, and a move in it is reported only when the two subjects’ intervals are separated — never because two numbers swapped places inside the noise.

We measure what is said and show you what is wrong with it. Nobody has a lever inside the model, and we do not claim one.