You measure AI citations by asking the engines directly. Run a fixed set of queries against ChatGPT, Perplexity and Google's AI surfaces, and record which sites each answer links to. Then score only the answers that could have cited you, because an answer with no sources had nothing to give anyone.

I built a measurement harness for pooyagolchian.com, a script that asks the engines the same questions and scores what comes back. Its first run lied to me. It reported 23 defeats on queries where Google never showed an AI Overview at all. The engines were fine. My scorer had counted a non-event as a loss, and most of the method below exists to stop that happening again.
This is the measurement half of generative engine optimization, or GEO, the work of getting quoted inside AI answers. If you want the difference between GEO and classic SEO first, read generative engine optimization vs SEO.
Why can't Search Console measure AI citations?
Search Console holds data from Google Search and nothing else. It cannot tell you whether ChatGPT or Perplexity cited your page. Google does count AI Overview and AI Mode appearances, but it reports them inside the Web search type of the Performance report. They sit in the same totals as ordinary results.
So the only way to measure the other engines is to ask them. My harness calls them through searchapi.io, a search API that exposes ChatGPT, Perplexity and Google AI Mode as engines you can query. The ChatGPT engine and the Perplexity engine each return the answer text plus the sources the answer linked. That source list is the raw material for everything below.
What goes in the query set?
Start with a fixed list of the questions your buyers ask, grouped by intent. My baseline on 22 August 2026 held 30 queries in five groups. Brand queries ask about me by name. Topic queries ask about the subjects I write on, such as "what is spec driven development". Comparison, commercial and how-to queries cover the rest. On 6 September I appended ten more, including a new group on SEO and GEO, which brought the set to 40.
Append new queries and never reword old ones. A reworded query starts a new series, and the trend line breaks at that point. Read each new query as a fresh baseline rather than as a decline. The groups matter too, because each one gets its own verdict instead of vanishing into one blended average.
Which surfaces should you measure?
Measure five surfaces per query. Four of them produce generated answers. The fifth, Google's organic results, is the control, the baseline that tells you what a citation gap means.
| Surface | What it returns | Its job in the measurement |
|---|---|---|
| ChatGPT | A generated answer, with sources when it searched | Main AI surface. Skips search on some queries |
| Perplexity | A generated answer with a source list | Main AI surface. Held identical across two passes |
| Google AI Mode | Google's conversational answer with sources | Google's own generated layer |
| Google AI Overview | The summary above the classic links, when one renders | Renders on only some queries |
| Google organic | The first ten links | The control |
The control turns a score into a diagnosis. A page that ranks but never gets cited has an extractability problem. Extractability means an engine can lift a clean, self-contained answer from your page. A page that neither ranks nor gets cited has an authority problem, and that needs a different fix entirely.
How do you score each answer?
Every answer gets exactly one outcome. The order matters, because an owned link outranks an adjacent one, and any link outranks a bare mention.
| Outcome | What happened | How it counts |
|---|---|---|
| cited | The answer links to a page on your own domain | Win |
| adjacent | It links to you on a site you do not control, like your GitHub or LinkedIn profile | Tracked, not a win |
| mentioned | It names you in the prose but links elsewhere | Tracked, not a win |
| absent | It searched, cited others and left you out | Loss |
| no_search | ChatGPT answered from memory and cited nobody | Removed from the denominator |
| no_surface | Google showed no AI Overview for the query | Removed from the denominator |
| error | The API call still failed after two retries | Kept as a loss |
Keep the brand match narrow. My scorer matches my full name and my product names, never a bare first name. "Pooya" alone matches unrelated people and would inflate every run.
Adjacent citations still matter. They build the picture an engine holds of you, but no change to your own site can move them. So they get their own column instead of padding the win count.
Why does the denominator decide the score?
The denominator decides whether your score means anything. Two outcomes are non-events. When ChatGPT answers from memory, its payload sets is_web_search_performed to false and lists no sources. When Google shows no AI Overview, there was no overview to appear in. Neither answer had a citation to give, so neither belongs in the attempts.
The difference is large. On 22 August 2026 ChatGPT cited my site on 9 of 30 queries. It answered 10 of those 30 from memory. Scored against the 20 it searched, the rate is 45%, not 30%. Google's AI Overview rendered on only 5 of the 30 queries, so its honest score is 1 of 5.
Failed calls go the other way. My harness keeps them in the denominator as losses. A run that quietly drops a failed query reports a better score than the site earned.
Which payload traps corrupt the numbers?
Each engine returns a payload, the raw data behind the answer, and each one has a shape that can fool a scorer. Four traps cost me time on the first build.
- Google's overview stub. Google returns an
ai_overviewobject even when no overview ran. It carries an error, "An AI Overview is not available for this search", plus a page token. A check that only asks whether the key exists reads that as a rendered overview. That is where my 23 phantom defeats came from. - Two names for the source list. The inline overview lists its sources under
reference_links, notreferences. A scorer that reads only one field marks every rendered overview as a loss. Mine reads both. - ChatGPT's skipped searches. ChatGPT answered 10 of my 30 baseline queries without searching. Seven came from the ten questions about AI-DLC, the AI-driven development life cycle. The other three were how-to queries. Check
response_metadata.is_web_search_performedbefore you call anything a loss. - Locale. Google served an AI Overview on 5 of 6 test queries with
gl=usand on 2 of 6 withgl=ae. Theglparameter sets the searcher's country. My harness defaults tous. Run commercial queries as a separate pass from the country your buyer searches in.
One habit protects you from the traps you have not found yet. Keep every raw payload. Scoring rules change as you learn each engine, and a rule you cannot apply to old runs makes the series incomparable. My harness re-scores a saved day with --rescore and makes no API calls to do it.
How much does one run move?
Most surfaces hold still. ChatGPT does not. On 22 August 2026 I ran two full passes twenty minutes apart. Perplexity returned 14 of 30 both times, and Google organic returned 7 of 30 both times. Google AI Mode moved by one query. ChatGPT moved from 6 of 18 to 9 of 20, because it re-decides on every ask whether to search and what to cite.
Treat the ChatGPT figure as plus or minus ten points, and judge it on trend. Google's AI Overview is the least stable surface of all. Whether an overview renders varies by locale and by the hour, so its denominator moves between runs.
Single queries swing harder still. On 23 August 2026 one ChatGPT probe returned 0 of 1, then 2 of 3, on the same query twenty minutes apart. Pool at least six runs before you quote a rate for one query.
What did the first baseline show?
The 22 August 2026 baseline ran 30 queries across all five surfaces.
| Surface | Cited | Could have cited | Rate |
|---|---|---|---|
| Perplexity | 14 | 30 | 47% |
| ChatGPT | 9 | 20 | 45% |
| Google AI Mode | 10 | 30 | 33% |
| Google organic (control) | 7 | 30 | 23% |
| Google AI Overview | 1 | 5 | Too few to read |
The AI engines cited my site more often than Google ranked it. Perplexity and ChatGPT cited it on nearly half the queries they could. Google's first ten links held it on under a quarter.
Brand queries went 4 of 4 on every surface that answered. Google showed no AI Overview for any brand query, so that surface had nothing to score there.
The control split the 30 queries into three groups. Seven ranked and earned an AI citation. Eleven earned an AI citation without ranking. Twelve did neither. Not one query ranked and then went uncited on every AI surface, so extractability was not my bottleneck.
The losses had names. My harness lists the domains that took each citation it lost, because that list names the pages to beat. On answers my site did not win, YouTube drew 74 citations across 17 of the 30 queries. Reddit came second with 29 across 16.
What does a run cost?
Each query costs one API call per surface. My 30-query baseline across five surfaces took 150 calls. Forty queries take 200.
Save credits by measuring one slice at a time. My harness takes a --category flag to re-run one group and a --surface flag to re-run one engine. A --limit 5 flag tests five queries before you spend real credits. A partial run merges into that day's file, so re-checking ChatGPT leaves the morning's Perplexity results intact. A --compare flag then diffs the new run against the last one, query by query.
Why can an empty run mean a dead key?
Check the account before you trust a run that found nothing. In September 2026 the searchapi.io key behind my harness stopped working. The account endpoint answered "Invalid API key." From then on, every engine call would fail the same way.
That failure hides in plain sight. My harness keeps failed calls in the denominator, so every surface scores zero. The error count sits at the end of the same line, easy to skim past. The run reads like "no citations found", not like an authentication problem.
So call the account endpoint, GET /api/v1/me, before every run. It returns your remaining credits when the key works and an error when it does not. My harness already calls it to print the credit balance. On a dead key that line reads "unknown", and the run carries on anyway. A zero score beside an unknown balance means a dead key, not a dead site.
What should you do with the numbers?
Match the fix to the cell each query lands in.
| Ranks on Google | Cited by an AI engine | Queries on 22 Aug 2026 | The fix |
|---|---|---|---|
| Yes | Yes | 7 | Protect it. Re-measure after every rewrite |
| Yes | No | 0 | Extractability. Answer first, in passages that stand alone |
| No | Yes | 11 | Working on AI surfaces. Treat the ranking as ordinary SEO |
| No | No | 12 | Authority. Earn presence where the engines already look |
When a page ranks but goes uncited, fix extractability. Put the answer in the first sentence, and write each passage so it still makes sense when quoted alone. The sibling post on how to get cited by ChatGPT covers those page changes in full.
When a page neither ranks nor gets cited, fix authority. First confirm that a page on your site answers the query at all. Then build presence where the engines already cite, which for me means YouTube and Reddit rather than another schema block.
When ChatGPT does not search, change nothing on the page. The model answered from its own memory, so no on-page edit can reach that answer. Only presence off your site moves how well a model already knows you.
Then re-measure the same set, on the same surfaces, three to four weeks after the change ships. My audit schedules its formal re-measure at 60 days. Compare query by query, not total against total.
Is a readiness check the same as measurement?
A readiness check and a citation measurement answer different questions. The free AI visibility checker tests whether AI crawlers can reach and read your site. It cannot tell you whether any engine cites you.
Only live queries against the engines answer that. My SEO and AEO audit runs them on a fixed question set and re-measures 60 days later. AEO, answer engine optimization, is the half of that audit that asks the engines. The measurement section of my SEO and AEO reference holds the short version of this method.