AEO audit template: audit a site in 90 minutes
An AEO audit checks 40 items in four groups (Access, Clarity, Answers, Proof), saves one piece of evidence per check, scores each as pass, partial, fail or unverified, and ranks the fixes. The workbook does the arithmetic. The score measures checklist completion; it does not predict AI citations.
Last verified 28 October 2026 · Reviewed by Adarsh Kant
- AEO audit workbook (Excel) ↓40 checks with weights and rationales, findings log, summary with formulas, and the citerlabs.com checks 1 to 10 example.
- AEO checklist scorecard (CSV) ↓The plain 40-check list if you prefer a simple pass/fail sheet.
What does a 90-minute AEO audit cover, and what does it leave out?
It covers one site, sampled. Pick the home page, one product or service page, one article or guide, and the pricing or contact page. Four pages is enough to see patterns; it is not a crawl of every URL. Our own self-test sampled four pages for the noindex check, and we say so in the evidence.
It uses the 40 checks on our AEO checklist, grouped as Access (can AI crawlers reach the page), Clarity (who you are and what you do), Answers (does a page answer the question directly) and Proof (does the rest of the web agree with you).
It does not measure whether AI engines currently name or cite you. That needs a prompt panel and repeated runs, which is a separate exercise: see the AI visibility audit. An audit finds likely causes and hygiene gaps; a visibility measurement shows outcomes. Run both if you can, and do not mix their numbers.
How should you split the 90 minutes?
Some checks cannot be finished in the time. Check 8 (is your CDN or firewall blocking bots) needs access to security logs, and check 31 (do you appear on the sites engines cite) needs a prompt run. Mark those unverified rather than guessing. The workbook leaves unverified checks out of the score and shows coverage, so a gap in testing is never counted as a pass.
| Minutes | Step | What you produce |
|---|---|---|
| 0 to 10 | Scope: choose four sample pages, note who owns the site, CDN and CMS, set up the workbook | Filled Settings in your notes; sample page list |
| 10 to 35 | Access, checks 1 to 10: robots.txt, status codes, HTML source, noindex, sitemap, CDN rules, canonicals | Evidence URL or saved output per check |
| 35 to 55 | Clarity, checks 11 to 20: identity, About page, JSON-LD, pricing, llms.txt, contradictions | Result and evidence per check |
| 55 to 70 | Answers, checks 21 to 30: question list, direct openings, headings, tables, dates | Result and evidence per check |
| 70 to 80 | Proof, checks 31 to 40: third-party sites, reviews, citations, video | Result and evidence per check; list of sites to investigate |
| 80 to 90 | Score and log: fill Findings log, read the Summary sheet, note what stayed unverified | Ranked findings and a one-paragraph readout |
What evidence should you save for each check?
Save enough that a colleague could repeat the check and get the same answer. For every check, record: the URL tested, the date and time, the tool or command used, the result you saw, and where you saved the proof. Paste a URL or file path into the Evidence column of the workbook.
- Status and headers: the output of a command-line request, saved as text, with the user agent string you sent.
- HTML source: a saved copy of the raw server response, not a browser screenshot of the rendered page, so you can see what a simple fetcher sees.
- robots.txt: a dated copy of the file as served, plus the HTTP status.
- Structured data: the JSON-LD block and the validator output, with the date.
- Third-party presence: the URL of each profile, listing or review page, and the date you looked.
- Anything you could not test: write what blocked you (no log access, no login), who could unblock it, and mark the result unverified.
- Location and tooling: note where you ran the test from. Our own tests ran from one location and said so.
# Check 1: status of robots.txt
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/robots.txt
# Check 4: status of a key page with a normal browser-style user agent
curl -s -o /dev/null -w "%{http_code}\n" -A "Mozilla/5.0" https://example.com/pricing
# Check 5: is your headline in the HTML the server sends?
curl -s -A "Mozilla/5.0" https://example.com/ | grep -i -c "your exact headline text"
# Check 6: any noindex in headers or markup?
curl -sI -A "Mozilla/5.0" https://example.com/ | grep -i "x-robots-tag"
curl -s -A "Mozilla/5.0" https://example.com/ | grep -i -o '<meta[^>]*robots[^>]*>'What should the robots.txt checks (2 and 3) look for?
Vendors publish separate crawler names for separate jobs, and they say the settings are independent. OpenAI documents OAI-SearchBot (search), GPTBot (training) and ChatGPT-User (user-initiated visits). Anthropic documents ClaudeBot (training), Claude-User (user questions) and Claude-SearchBot (search). Perplexity documents PerplexityBot (search results) and Perplexity-User (user actions). Google says Googlebot crawling follows robots.txt, and that appearing in AI Overviews or AI Mode needs no extra technical requirement beyond being indexed and eligible to show with a snippet.
Check 2 asks whether you made a deliberate decision per crawler. Check 3 asks whether you separated search from training. The example below shows only the syntax of per-crawler rules. Whether to allow or block each one is your decision, and nothing here claims that allowing a crawler raises citations.
Two vendor caveats matter when you read logs. OpenAI says robots.txt rules may not apply to ChatGPT-User because users start those visits, and Perplexity says Perplexity-User generally ignores robots.txt for the same reason. Vendor pages change, so copy the current names from the vendor documents on the day you audit, as check 2 itself says.
# Search-related crawlers
User-agent: OAI-SearchBot
Allow: /
User-agent: Claude-SearchBot
Allow: /
User-agent: PerplexityBot
Allow: /
# Training crawlers (separate decision)
User-agent: GPTBot
Disallow: /
User-agent: ClaudeBot
Disallow: /
Sitemap: https://example.com/sitemap.xmlHow do you score the 40 checks?
Each check gets one result. Pass scores 1 point, partial 0.5, fail 0. Unverified, or blank, is not scored. Each check also carries a weight of 1, 2 or 3 that is our own judgment: 3 for a gate (if it fails the page may be unreachable or ineligible), 2 for checks that affect how clearly you are understood or verified, 1 for supporting or low-cost items and for the two hypothesis checks.
The workbook gives a one-line rationale for every weight and tags it [Source] where a vendor or standard document supports it, [Judgment] where it is our call, and [Hypothesis] where no source shows a citation effect. We did not derive the weights from measured citation outcomes, because we have none. Change them for your context and write down why.
Weighted points = weight x points (scored checks only)
Group score /100 = sum(weighted points) / sum(weight of scored checks) x 100
Coverage % = weight of scored checks / weight of all checks in the group
Worst case /100 = weighted points / all weight (unverified treated as fail)
Best case /100 = (weighted points + unscored weight) / all weight (unverified treated as pass)
Gap points = weight x (1 - points) (scored checks only)How do you prioritise the findings?
Severity is a label for the reader; gap points and effort set the order. If your team disagrees with a weight, change the weight in the Checks sheet and keep a note, rather than overriding the order by hand.
- Resolve unverified gates first. An unverified weight-3 check could be a total block or a non-issue, and you cannot rank it until you know.
- Then rank failures and partials by gap points (weight x shortfall). A failed weight-3 check has a gap of 3; a partial weight-2 check has a gap of 1.
- Divide by fix effort once your team has estimated it: S = 1, M = 2, L = 3. The Findings log computes gap points divided by that factor. Highest first.
- Break ties by owner availability. A fix someone can ship this week beats a slightly bigger one that waits on a vendor.
- Record status and date closed, then re-run only the checks you changed. Keep the old evidence; do not overwrite it.
Worked example: CiterLabs' own self-test of checks 1 to 10
This uses only the results we recorded when we tested citerlabs.com on 28 October 2026, checks 1 to 10 (the Access group). Checks 11 to 40 were not part of that test and we show no results for them. Weights are the ones in the workbook. The workbook has this same table on its own sheet, with live formulas.
- Scored weight: 3 + 2 + 2 + 3 + 3 + 3 + 1 + 1 + 2 = 20. Available weight including check 8: 23.
- Weighted points: 3 + 0 + 0 + 3 + 3 + 3 + 1 + 1 + 1 = 15.
- Access score = 15 / 20 x 100 = 75.0. Coverage = 20 / 23 = 87%.
- Worst case if check 8 fails: 15 / 23 = 65.2. Best case if it passes: 18 / 23 = 78.3.
- Read-out: Access is 75.0 on 87% coverage, somewhere between 65.2 and 78.3 once check 8 is known.
| Check | Result | Weight | Points | Weighted | Our recorded note |
|---|---|---|---|---|---|
| 1 robots.txt returns 200 | pass | 3 | 1 | 3 | /robots.txt returns 200. |
| 2 Per-crawler rules written | fail | 2 | 0 | 0 | No per-crawler rules, only a blanket allow. |
| 3 Search and training bots separated | fail | 2 | 0 | 0 | Not treated separately yet. |
| 4 Key pages return 200 to plain curl | pass | 3 | 1 | 3 | Five AI crawler user agents got 200 from one location; verified-bot rules at the CDN not tested. |
| 5 Main content in server HTML | pass | 3 | 1 | 3 | Fixed on 28 October 2026. Before the fix the server HTML held a heading and one sentence. |
| 6 No noindex on target pages | pass | 3 | 1 | 3 | None on the four pages sampled. |
| 7 Pages in sitemap, sitemap in robots.txt | pass | 1 | 1 | 1 | Both true. |
| 8 CDN or firewall not blocking bots | unverified | 3 | not scored | not scored | Needs a look at CDN security logs, not done. |
| 9 Pages load in reasonable time | pass | 1 | 1 | 1 | About 0.3 to 0.4 seconds per fetch, one location. |
| 10 Canonicals and 301s correct | partial | 2 | 0.5 | 1 | Canonicals correct on sampled pages; www.citerlabs.com serves 200 instead of redirecting. |
What does the worked example say to fix first?
What the method says to do next, using gap points: check 8 first, because it is an unverified gate. Then checks 2 and 3 (gap 2 each) and check 10 (gap 1). We did not estimate effort for these here, so the page does not rank them further; with a real effort estimate the Findings log would. The check 5 result is the state after the fix, and the score of the earlier state was never recorded, so we do not calculate one.
What can this audit not tell you?
- Whether any single fix will raise how often AI engines name or cite you. We found no source that shows this for the checks on the list, and we label the two checks that are only hypotheses (llms.txt and video) as such.
- Whether your pages are currently cited. Use the AI visibility audit for that.
- How a CDN treats verified bots. That needs logs or the CDN's own bot reports.
- Anything about pages you did not sample. State the sample in the readout.
Honest limits
What we do not know.
- We do not know how much each check contributes to being named or cited by AI engines. The weights are our judgment and have not been tested against outcomes.
- We do not know whether the 90-minute split is realistic for your site. It is a plan we have not timed across sites, and larger sites will likely need a longer sample.
- We have not tested which AI engines execute JavaScript, so check 5 is weighted as a gate by caution, not from a measured effect.
- llms.txt is a community proposal; its own page reports growing use by sites and tools but does not show AI engines relying on it, and Google says no AI-specific files are needed. Whether any engine uses it for retrieval is unknown to us.
- Vendor crawler names and behaviour change. The names in this page were read from vendor documents on 2026-10-28; Google-Extended was not covered by the Google page we opened, so we make no claim about it.
- Our own self-test covers checks 1 to 10 only, from one location, and check 8 is still unverified.
- The workbook was recalculated and error-checked in LibreOffice and with test data; we have not opened it in every spreadsheet app.
Sources
- CiterLabs AEO checklist data (aeoChecklist.ts: 40 checks and 28 October 2026 self-test), read from the repository (opened 28 October 2026)
- OpenAI: Overview of OpenAI crawlers (OAI-SearchBot, GPTBot, ChatGPT-User) (opened 28 October 2026)
- Anthropic Help: Does Anthropic crawl data from the web, and how can site owners block the crawler? (opened 28 October 2026)
- Perplexity docs: Perplexity crawlers (PerplexityBot, Perplexity-User) (opened 28 October 2026)
- Google Search Central: AI features and your website (opened 28 October 2026)
- Google Search Central: Overview of Google crawlers and fetchers (Googlebot respects robots.txt) (opened 28 October 2026)
- Google Search Central: Introduction to robots.txt (opened 28 October 2026)
- Google Search Central: General structured data guidelines (opened 28 October 2026)
- IETF RFC 9309: Robots Exclusion Protocol (opened 28 October 2026)
- llmstxt.org: The /llms.txt file (proposal, version 2) (opened 28 October 2026)
How this page was made: An AI assistant drafted this page and the workbook from the cited sources and from CiterLabs' own checklist data, and it awaits human review.
Questions
- Can I really audit a site in 90 minutes?
- A sampled audit of four pages, yes, if you can reach the site, its robots.txt and a command line. Checks that need logs or a prompt run will stay unverified. The workbook shows that as lower coverage instead of hiding it.
- Does a higher score mean AI engines will cite me more?
- No source we opened shows that. The score counts completed checks, weighted by our judgment. Measure outcomes separately with a frozen prompt panel.
- Why are unverified checks left out of the score?
- Counting them as passes would hide gaps in your testing, and counting them as fails would punish you for something you did not check. The workbook leaves them out and shows a worst-case and best-case range.
- Should I add llms.txt?
- The checklist marks it as a hypothesis. Google says AI features need no AI-specific files. The llms.txt proposal is a community proposal. It is cheap to add, so it is your call, but do not count on it.
Free, no call needed
See who AI namesin your category today.
Tell us your domain and category. We run 10 buyer questions and send a short report with the raw answers attached.
Get a free AI Visibility CheckOr write to [email protected]