SEO·AEO for builders

Lesson 0005 · Did it work?

Measuring It

Two scoreboards, wildly asymmetric. Classic search hands you a first-party API. AI citations hand you nothing — so you build the proxy everyone else builds.

Recap from Lesson 0004: you made a page eligible (0002), labelled its facts (0003), and shaped its prose for retrieval (0004). All of that is a bet. This lesson closes the loop — how do you know it landed?

The two pipelines don’t measure the same way, and the gap is the whole story. For classic search, Google gives you ground truth through an API. For AI-answer citations, no engine exposes one — so every tracker on the market, and the one you’ll build, is a proxy.[1]

Your win: run citation_share.py on a set of answer-engine responses and get your coverage (% of prompts that cite you) and share of voice (your slice of all citations) vs competitors — the same proxy metric Profound and Ahrefs Brand Radar sell.

Two scoreboards

Classic search — first-party API

Google Search Console API. Real impressions, clicks, average position, and the exact queries — from Google's own logs.[2]

The Web search type now folds in traffic from AI features, so AI-Overview clicks already show up here.

✓ ground truth, queryable, free

AI citations — no API exists

No OpenAI / Anthropic / Perplexity / Google endpoint answers "how often is my site cited?" Google's June 2026 gen-AI reports are a Console UI view, not in the API yet.[3]

So you sample: run a prompt library, parse the citations, tally.

✗ proxy only — synthetic, not real traffic

Classic side: just call the API

This one’s a solved problem — authenticate, then POST a date range and the dimensions you want. No tool to build; the platform is the tool.

# Search Console: top queries by clicks, last 28 days
POST https://www.googleapis.com/webmasters/v3/sites/{siteUrl}/searchAnalytics/query
{
  "startDate": "2026-05-20", "endDate": "2026-06-17",
  "dimensions": ["query"],
  "rowLimit": 100
}
# -> rows of { keys:[query], clicks, impressions, ctr, position }

Poll it on a schedule, store the rows, and you have rank/impression/click trends over time — the backbone of any SEO monitor.

AEO side: the proxy you build

Because there’s no ground truth, every commercial AEO tracker does the same three steps — and so does tools/citation_share.py:

StepWhat it isWho owns it
1 · Prompt libraryA fixed set of buyer questions in your spaceyou (the API key + prompts)
2 · Run the engineSend each prompt, capture response + cited linksyou (one API call)
3 · Parse & scoreExtract cited domains → coverage + share of voicecitation_share.py

A second helper, tools/build_prompts.py, owns step 1: it assembles that buyer-question prompt library — from an LLM fan-out or your Search Console rows — in the exact shape citation_share.py consumes. The tool is the offline, testable core. It scores cited links (the AEO equivalent of a rank), not bare brand mentions:

# coverage = prompts that cite me; SOV = my citations / all citations
cited = cited_domains(entry)          # links in response + citations[]
hit   = bool(cited & my_domains)
sov   = mine / total_citations
Do this now:
  1. Self-check (offline): python3 tools/citation_share.py --demo
  2. Hand-make a tiny results.json — 3–4 buyer questions, paste in real answers + links from ChatGPT/Perplexity — then score it: python3 tools/citation_share.py results.json --domain yourdomain.com
  3. Re-run it next week. The single number that matters is your own coverage trend — not the absolute value.
$ python3 tools/citation_share.py results.json --domain myseo.io

AI-citation share — 4 prompts, you = myseo.io
────────────────────────────────────────────────────
COVERAGE  50%  cited in 2/4 prompts
SHARE OF VOICE  33%  of all citations are yours
────────────────────────────────────────────────────
Top cited domains:
3ahrefs.com
2myseo.io  ← you
1moz.com
────────────────────────────────────────────────────
Per prompt:
[HIT ] best seo audit tool for developers?
[miss] how to track rankings via api?
[HIT ] what is generative engine optimization?
[miss] cheapest backlink checker?
Proxy ≠ ground truth — read your own numbers honestly. Your prompt library is a sample you chose, not the engine’s real query distribution, and answers are non-deterministic. So absolute share-of-voice means little, and two tools’ numbers aren’t comparable — they ran different prompts.[1] Treat it like a poll: a fixed prompt set re-run over time gives a trustworthy trend; a single run’s headline % does not. Hold the prompts constant or you’re measuring your prompts, not your site.

Ceiling to know: citation_share.py counts cited links only. “Brand mentioned without a link” is a different (softer) metric; domain matching is naive (no public-suffix list). Both are noted in the tool’s docstring as upgrade paths.

Retrieval practice · no peeking

Read the scoreboard

Answer from memory — that effort is what makes it stick. One try each; pick before you read the others.

Question 1 / 4
Which has a first-party measurement API you can call today?
Question 2 / 4
How does every AEO citation tracker get its numbers?
Question 3 / 4
Why not compare your share-of-voice across two different AEO tools?
Question 4 / 4
What does the Search Console API give you that an AEO proxy can't?
Primary source — read this next (≈12 min)
"Search Analytics: query" — Search Console API reference

The exact request body and the rows you get back — your classic-search ground-truth feed. Start at the <a href="https://developers.google.com/webmaster-tools/about">API overview</a>. For the AEO side, see the proxy-method walkthrough in <a href="https://ahrefs.com/blog/chatgpt-visibility-tracking/">Ahrefs' ChatGPT-visibility guide</a> and the gaps note in <a href="/resources/"><code>RESOURCES.md</code></a>.

Stuck or curious? This agent is your teacher. Ask it anything — “show me a real robots.txt”, “do Claude and Perplexity retrieve differently?” — followups are the fastest way to learn.