How to Track AI Citations โ A Practical Guide to Measuring Your GEO Performance
You published twenty articles optimized for AI search. AI crawlers visit every week.
But when someone asks ChatGPT a question in your niche โ does your site get cited? Which page? On which platform?
There is no "Search Console" for AI answers. No platform will email you a citations report.
This guide shows you how to build the measurement system yourself: server log analysis, crawler monitoring, brand mention tracking, and honest attribution.
I. Why Tracking AI Citations Matters
If you can't measure it, you can't improve it โ and in Generative Engine Optimization (GEO), measurement starts with citations. GEO without tracking is guessing: you publish, you wait, and you hope.
An AI citation is any reference to your brand, content, or URL inside an AI-generated answer โ with a link, or without one.
In traditional SEO you get impressions, clicks, and rankings from Google Search Console. In AI search you get none of that. The answer appears, the user reads it, and the moment is gone unless you measured it yourself.
That is why AI citation share is the new organic traffic โ it is the headline number that tells you whether AI engines consider you a source worth quoting (see our citation share metric guide). Three practical reasons to start measuring today:
- Budget justification: "Citations grew from 3% to 18% of tested answers" defends your GEO budget far better than intuition.
- Direction: Tracking reveals which pages and platforms respond to optimization, so effort goes where it compounds.
- Early warning: Models update monthly. Without a baseline, you cannot see a citation collapse until it has already cost you a quarter.
II. Server Log Analysis: The Foundation
Your server logs are the only first-party, real-time record of which AI systems read your content. AI platforms offer site owners no dashboard, so the request log โ not a third-party estimator โ is where credible measurement begins.
What to Record for Every Request
| Field | Why It Matters |
|---|---|
| Timestamp | Crawl frequency and trends over time |
| Crawler name | Which AI platform visited (from User-Agent) |
| Path | Which page was read โ your content inventory as AI sees it |
| Status code | 200 vs. 404/403 โ a blocked or broken page is a wasted crawl |
| Referer host | Rare for crawlers, but valuable for human click-through later |
The Cloudflare Worker Approach
This is exactly how we measure geo010.com: a small Cloudflare Worker sits in front of the static site, classifies each request by User-Agent, and writes one row per page request into a Cloudflare D1 database. We shared what two weeks of that data looked like in our crawler data experiment and the follow-up attribution study.
Start with a table that stores path, crawler, status, and time:
CREATE TABLE IF NOT EXISTS crawler_logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ts TEXT NOT NULL,
date TEXT NOT NULL,
ua TEXT,
crawler_name TEXT,
path TEXT NOT NULL,
status INTEGER NOT NULL
);
Then classify the User-Agent and log only what matters:
const AI_CRAWLERS = [
{ name: 'GPTBot', re: /GPTBot/i },
{ name: 'OAI-SearchBot', re: /OAI-SearchBot/i },
{ name: 'ClaudeBot', re: /ClaudeBot/i },
{ name: 'PerplexityBot', re: /PerplexityBot/i }
];
function classifyCrawler(ua) {
if (!ua) return null;
for (const c of AI_CRAWLERS) {
if (c.re.test(ua)) return c.name;
}
return null;
}
async function logIfCrawler(env, request, status) {
const ua = request.headers.get('user-agent') || '';
const crawler = classifyCrawler(ua);
if (!crawler) return; // human traffic: skip
const now = new Date().toISOString();
await env.DB.prepare(
'INSERT INTO crawler_logs (ts, date, ua, crawler_name, path, status) VALUES (?, ?, ?, ?, ?, ?)'
).bind(now, now.slice(0, 10), ua, crawler,
new URL(request.url).pathname, status).run();
}
Keep the list current: OpenAI and Anthropic both publish official bot documentation, and new crawlers appear regularly. For the full access-control picture, pair logging with the rules described in AI crawler management.
Read the Log Like an Analyst
- Frequency: a bot that visited daily and suddenly stops signals a discovery or blocking problem.
- Status codes: clusters of 404s mean the crawler is following dead links โ fix or redirect them.
- Entry files: hits on
robots.txt,llms.txt, andsitemap.xmltell you bots are actively discovering; log these separately.
III. Crawler Behavior Patterns by AI Platform
Every AI platform crawls differently โ and each difference tells you what to fix. Treating all bots alike wastes effort; matching fixes to behavior is what makes log data actionable.
| Crawler | Operated By | Crawl Pattern | What It Means for You |
|---|---|---|---|
| GPTBot | OpenAI | Deep crawl, largely sitemap-driven; feeds training and retrieval corpora | Keep sitemap.xml current so new pages enter the queue fast |
| OAI-SearchBot | OpenAI | Selective; fetches pages surfaced by ChatGPT Search | A visit is a strong signal ChatGPT Search may cite that page |
| ClaudeBot | Anthropic | Enters via robots.txt permissions plus sitemap entries | Verify ClaudeBot is allowed and key pages are listed in the sitemap |
| PerplexityBot | Perplexity | Content page crawler focused on answer-ready text | Question-style headings and answer-first paragraphs pay off directly |
| Googlebot | Frequent, comprehensive crawling | Feeds AI Overviews and Gemini grounding โ classic SEO hygiene still counts |
Three behavioral differences matter most in practice:
- Discovery path: sitemap-driven bots (GPTBot, ClaudeBot) punish a stale sitemap; if they never arrive, check discovery files before blaming content quality.
- Selectivity: OAI-SearchBot fetching one deep page is a compliment โ it means a real user question surfaced that URL.
- Appetite: comprehensive crawlers like Googlebot mask problems; judge your GEO health on the selective bots' behavior, not the greedy ones.
Watch the patterns for a few weeks and you can attribute most "mystery" citation drops to one of these three causes.
IV. Brand Mention Tracking Across AI Platforms
Log files prove crawlers came; only asking the AI proves it cites you. Manual brand mention testing is the second pillar โ unglamorous, cheap, and impossible to outsource fully.
The Testing Routine
- Fix your query set: choose the 10โ20 questions your customers actually ask, phrased the way they ask them.
- Use fresh sessions: start a new conversation on ChatGPT, Claude, and Perplexity each time to limit personalization bias.
- Record what happens: mentioned or not, page cited or not, link included or not, position within the answer.
- Repeat weekly for key terms; go deeper monthly with competitor comparisons and description-accuracy checks.
Weekly cadence is deliberate: models update frequently, and a monthly-only rhythm hides swings that weekly sampling catches early. Ten minutes per week is enough once the routine is set.
A Minimal Tracking Spreadsheet
| Date | Platform | Query Tested | Mentioned? | Page Cited | Linked? | Position | Notes |
|---|---|---|---|---|---|---|---|
| 2026-08-14 | ChatGPT | how do i track ai citations | Yes | /technical/track-ai-citations.html | Yes | #1 source | fresh session |
| 2026-08-14 | Perplexity | how do i track ai citations | No | โ | โ | โ | competitor cited |
| 2026-08-21 | Claude | geo performance metrics | Yes | /metrics/citation-share.html | No | mid-answer | mention w/o link |
A mention without a link still counts. AI often names a source inline while omitting the URL โ recording "mentioned, not linked" separately keeps your numbers honest (more on this in Section VI).
V. Building a GEO Dashboard
A useful GEO dashboard needs five numbers, not fifty. Together they cover the full funnel: discovered โ crawled โ cited โ recommended โ clicked.
| Metric | Data Source | Healthy Signal |
|---|---|---|
| Crawler visits by bot | D1 log / Cloudflare Analytics | Steady weekly visits from 3+ AI crawlers |
| Content pages crawled | D1 GROUP BY path | Priority answer pages crawled at least monthly |
| AI citation frequency | Weekly manual tests | Citations trending up on priority queries |
| Brand mention rate | Weekly manual tests | Mentioned in a rising share of tracked answers |
| Referral traffic from AI platforms | GA4 referral filters | Growing clicks despite missing referers |
Tooling Options
- Cloudflare Analytics: free request-level overview; good for spotting spikes, too coarse for per-bot detail.
- Custom D1 queries: the geo010.com approach โ two SQL statements produce the whole report:
-- Crawler visits by bot, last 30 days
SELECT crawler_name AS bot, COUNT(*) AS visits
FROM crawler_logs
WHERE date >= '2026-07-22'
GROUP BY crawler_name ORDER BY visits DESC;
-- Most-crawled pages by AI bots
SELECT path, COUNT(*) AS visits
FROM crawler_logs
WHERE crawler_name IS NOT NULL AND date >= '2026-07-22'
GROUP BY path ORDER BY visits DESC LIMIT 20;
- Google Analytics 4 referral filters: build a segment or report filter for sessions with source
chatgpt.com,perplexity.ai, andcopilot.microsoft.com. Expect undercounting โ treat it as a floor, not a total (see data dashboard setup).
Put all five metrics on one page with last month's values beside them. If a number has no owner and no action, cut it โ dashboards die of clutter.
VI. Common Attribution Challenges
Even with perfect logging, some citations will stay invisible โ the gaps are structural, not bugs. Plan around them instead of chasing perfect data.
Challenge 1: Browser-Based AI Sends No Referer
When a user clicks a link inside ChatGPT's web or mobile app, the browser frequently opens the page without a referer header. Your analytics then records the visit as direct traffic, and the AI platform gets zero credit.
Challenge 2: API-Based AI Has No User-Agent
Retrieval backends sometimes fetch pages with generic HTTP clients rather than their branded crawler. Those requests look like anonymous humans in your logs and cannot be classified by User-Agent matching alone.
Challenge 3: Partial Credit โ Mentions Without Links
AI may describe your product, quote your phrasing, or recommend you by name while citing a different URL entirely โ or none. Log-based and referral-based measures both miss this; only manual testing sees it.
The Workaround: Triangulate Three Sources
Treat every single source as a lower bound. Make decisions when at least two sources agree โ logs, manual tests, and referral analysis are checks on each other, not substitutes.
- Logs answer "who read my pages?" โ objective, instant, but blind to citations.
- Manual tests answer "who cited me?" โ ground truth, but sampled and subjective at the edges.
- Referral analysis answers "who sent visitors?" โ proof of end impact, but heavily undercounted.
When all three move together, you have a real trend. When they disagree, investigate before celebrating either direction.
VII. From Data to Action
Data becomes GEO progress only when it changes next month's plan. Close every month with a 30-minute review against this checklist:
- [ ] Which pages were crawled most โ and which priority pages were skipped?
- [ ] Which AI platforms cite us, and did the platform mix shift this month?
- [ ] Where are the content gaps: crawled by bots but never cited?
- [ ] Which currently cited pages are over 90 days old and due for a refresh?
- [ ] Which competitors gained citations on our priority queries โ and on which exact questions?
The most diagnostic line item is crawled but not cited. It isolates content quality from discoverability: the bots found the page, read it, and chose not to use it. That combination calls for structural edits โ question-style headings, answer-first openings, stronger entity signals โ the pattern we document in the GEO content template.
The opposite gap โ cited but rarely crawled โ points back to Section III: fix discovery with a fresh sitemap, clear robots rules, and internal links before touching the prose.
In short: log every crawler visit, test your key queries weekly, and turn the numbers into next month's edits โ measurement is what turns GEO from guesswork into a compounding system.