The GEO audit gave NowServingTO a 74/100 on Perplexity and a 58/100 on Google AI Overviews – and that gap isn’t a bug. Perplexity’s citation algorithm rewards specificity. Google’s rewards authority. For a new site with unique, verified, government-sourced data, that means Perplexity will cite you weeks before Google does. This post is a full Claude SEO/GEO audit on a real production site – six parallel agents, real scores across every dimension, and the specific findings that explain why the AI citation landscape looks nothing like traditional SEO.
Perplexity vs Google: The Core Insight
Google AI Overviews require three things that take time to accumulate: domain age, external editorial links from high-authority domains, and a track record in Google’s crawl history. A site that launched six weeks ago with zero backlinks simply doesn’t meet the bar, no matter how good the content is. Google AIO is an authority game.
Perplexity is a specificity game. Its citation algorithm has the lowest domain age threshold of any major AI search platform and actively prefers sources that are the most specific available answer to a query. If someone asks “newest Ethiopian restaurant in Toronto” and NowServingTO is the only source that cross-references the City of Toronto business licence registry, DineSafe inspection records, and Google Places verification to answer that exact question – Perplexity will cite it. The six-week-old domain doesn’t matter. The government-sourced specificity does.
This is the central GEO finding from the audit, and it changes how you should think about content strategy for a new site: build for Perplexity first, then age into Google AIO eligibility. The content structures that win on Perplexity – specific, citable, answer-first prose passages with declared data provenance – are exactly what ages into Google AIO eligibility later. They’re the same investment, just with a different timeline for each platform.
Claude SEO is an open-source plugin for Claude Code that runs this analysis (and five other audit dimensions) in parallel. Here’s everything it found on a real site.
What Claude SEO Is
Claude SEO installs as a plugin inside Claude Code and gives you 27 SEO commands that run as subagents in parallel. A full audit fires seven agents simultaneously – technical SEO, content quality (E-E-A-T), schema markup, performance (Core Web Vitals), AI search readiness (GEO), search experience (SXO), and sitemap – then synthesizes results through a 10-principle PERCEIVE→ANALYZE→VALIDATE→ACT framework before emitting a prioritised action plan.
What separates it from a crawl tool: every recommendation carries three mandatory fields. The first-principle observation it rests on. The dependency relationship to other recommendations. An explicit falsifiability check – “how would we know this failed?” – with a measurable leading indicator before you change anything. Ahrefs tells you your LCP is 4.2s. Claude SEO tells you the LCP is dominated by render delay caused by a specific render-blocking script in <head>, and names which Chrome DevTools measurement confirms the fix worked.
Installation
/plugin marketplace add AgriciDaniel/claude-seo
/plugin install claude-seo@agricidaniel-claude-seo
Requires Claude Code 1.0.33+. No API keys needed for base audits. Full source: github.com/AgriciDaniel/claude-seo
The Audit: NowServingTO
NowServingTO is a static-HTML Toronto restaurant directory – no framework, no build step, no backend. A Python ETL pulls the City of Toronto business licence feed every morning, classifies each new restaurant by cuisine using Claude Haiku, verifies it against Google Places, and writes pre-rendered HTML files that Apache serves directly. 253 active listings across 45 cuisine categories. The site was 26 days old at the time of the audit. Here is what six parallel subagents found.
| Audit Dimension | Score | Status |
|---|---|---|
| Technical SEO | 74/100 | Pass with issues |
| E-E-A-T / Content Quality | 74/100 | Pass with issues |
| Schema / Structured Data | 84/100 | Pass (post-fix) |
| Search Experience (SXO) | 61/100 | Structural gaps |
| Core Web Vitals | 82/100 | Estimated Good |
| AI Search Readiness (GEO) | 67/100 | Strong foundation, citation gaps |
1. Technical SEO – 74/100
The site passed crawlability (95/100), JavaScript rendering (96/100), mobile (92/100), and URL structure (88/100) cleanly. All 253 restaurant pages are pre-rendered static HTML – no client-side fetch gates primary content. Googlebot and AI crawlers read everything on first byte without executing JavaScript. The audit confirmed: “there is no rendering dependency on JavaScript for any indexable content.”
Where it failed: security headers (38/100) and a Cloudflare caching gap. All seven standard HTTP security headers are absent – HSTS, CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, X-XSS-Protection. HSTS is the most significant gap: without it, repeat visitors on untrusted networks don’t get the cached HTTPS upgrade. Five minutes in the Cloudflare dashboard and a single Transform Rule fixes all seven.
The caching finding: despite Cache-Control: public, max-age=3600, HTML pages return cf-cache-status: DYNAMIC – Cloudflare is not edge-caching them. Apache is streaming the response without an ETag, which prevents Cloudflare from forming a cacheable entry. Edge-caching HTML for five minutes would eliminate most origin round-trips and improve LCP for non-local visitors. Falsifiability check: curl -I https://nowservingto.com | grep cf-cache-status should return HIT.
One flagged finding turned out to be a false positive: the agent reported Restaurant schema “in inline JS rather than a proper ld+json block.” Spot-checking the live page found four <script type="application/ld+json"> blocks including a complete Restaurant entity. The agent had read a page variant. Lesson: use the falsifiability checks. The specific check provided – a Python one-liner to count ld+json blocks containing “Restaurant” – catches this in 30 seconds.
2. E-E-A-T and Content Quality – 74/100
| Dimension | Score | Key finding |
|---|---|---|
| Experience | 16/20 | Government data signals are strong; no first-person voice visible in body text |
| Expertise | 19/25 | Methodology expert-grade on /press; author credentials absent from page copy |
| Authoritativeness | 18/25 | City of Toronto data is non-replicable authority; no external coverage yet |
| Trustworthiness | 26/30 | Correction pathways on every listing, HTTPS, daily freshness, AI allowlist |
Individual restaurant pages average 147 extracted words against a 300-word minimum for product-page equivalents. The audit was precise: “thinness here is structural, not a quality failure.” The path to 250 clean words per page runs through existing data – DineSafe inspection date, nearest cross-street, neighbourhood restaurant count, licence address with unit. Most of this is already in the JSON data; it just isn’t being rendered.
A mechanical flaw in the AI-generated blurbs: every listing page was repeating the card-level summary sentence as the first sentence of the expanded page blurb. The same sentence appearing twice is a low-quality signal that both raters and crawlers notice. Fix: make the expanded blurb begin with a new sentence. The card summary already serves as the meta description and schema description – the page body shouldn’t restate it.
The wire pages (/wire/ethiopian, /wire/vietnamese, etc.) were flagged at 111-160 extracted words against a 500-word editorial minimum. Under the September 2025 Quality Rater Guidelines, pages that exist primarily to route users elsewhere without independent informational value qualify as low-value doorway content. The audit’s recommendation: either add 300-400 words of editorial context per wire page, or add noindex.
3. Schema – Detailed Field-Level Findings
The schema audit validated every block on three pages (homepage, one restaurant page, one cuisine page) and produced findings at the property level.
Finding: foundingDate is the wrong property on all 253 restaurant pages. foundingDate is an Organization property. The correct property for a LocalBusiness is openingDate – listed in Google’s LocalBusiness documentation as recommended for rich results. Same value, one-line change. Fixed.
// Before - wrong type
"foundingDate": "2026-05-29"
// After - correct LocalBusiness property
"openingDate": "2026-05-29"
Finding: CollectionPage blocks were anonymous nodes. Every CollectionPage – on cuisine pages, district pages, and the homepage – was missing a @id field. Without it, Google cannot form a graph reference and the entity is opaque to the knowledge graph. Adding "@id": "https://nowservingto.com/cuisine/vietnamese#collection" takes each entity from anonymous to referenceable. Fixed across all pages.
Finding: ItemList sort order undeclared. Every list is sorted newest-first with no declared order. Adding "itemListOrder": "https://schema.org/ItemListOrderDescending" makes the sort semantics machine-readable – directly useful for AI systems answering “what’s the newest Vietnamese restaurant in Toronto.” Fixed.
Correctly absent: AggregateRating. AggregateRating requires a native review system. Using scraped Google Places ratings in your own schema violates Google’s guidelines and risks a manual action. Correctly omitted.
4. Search Experience (SXO) – 61/100
The SXO audit performed backwards SERP analysis for five core queries and found a consistent pattern: the pages contain the right data but are the wrong page type for how Google reads those SERPs.
For “new Vietnamese restaurants Toronto 2026,” the SERP is dominated by editorial curated lists – blogTO, TasteToronto, Foodism. These are narrative opinion pieces with hero images, review excerpts, and editorial framing. NowServingTO’s /cuisine/vietnamese is a chronological, licence-ordered data list. The data is the right data. The page type is wrong.
The individual /r/ restaurant pages were the exception. For “El Maracucho Toronto,” NowServingTO appeared on page one alongside the restaurant’s own site, DoorDash, and Instagram. Restaurant schema with GeoCoordinates, hasMap, and verified-operational AdditionalProperty matches what Google rewards for navigational queries. The restaurant pages work. The collection pages don’t, yet.
The most important finding in the entire audit: neighbourhood pages were returning 404 on prod. Twenty-one HTML files existed – Koreatown, Little Italy, Little Portugal, Greektown, Thorncliffe Park, and sixteen others – but a 2.1 MB GeoJSON file that assigns entries to named corridors had never been deployed to the production server. Without it, the ETL assigned zero entries to any neighbourhood, wrote zero pages, and the cleanup pass deleted the twenty-one pages from the previous build. Every single neighbourhood page on the site was silently 404ing. Fixed by deploying the missing file and rebuilding. All 21 pages are now live.
Persona scoring illustrated the structural impact. The Neighbourhood Browser persona (someone searching “new restaurants Koreatown Toronto”) scored 52/100 – the lowest of five. The Confirmatory Searcher (someone verifying a restaurant they heard about) scored 71/100 – the restaurant pages work for this, but “verified open as of [date]” only exists in schema, not visible body text.
5. Core Web Vitals – Estimated Good
PageSpeed Insights quota was exhausted during the audit; the performance assessment used direct HTML analysis and response header inspection. Estimates: LCP 0.8s-1.5s, INP 80-180ms, CLS 0.02-0.08. All within Good thresholds. The architecture earns this: no external CSS, no render-blocking scripts, GA4 and Clarity deferred to first user interaction, Leaflet lazy-loaded on demand.
One specific gap: four of the six self-hosted woff2 font files are not preloaded. The Latin Basic subsets for Fraunces and Newsreader are preloaded correctly. The Latin Extended and Vietnamese diacritics subsets are discovered only after CSS parsing. Since the first entry in the feed is AND BANH MI – with “bánh mì” in the blurb – those characters trigger the Vietnamese subset on the first above-fold row. Adding preload hints for the four remaining files would close the CLS risk from font swap on non-Latin characters.
6. AI Search Readiness (GEO) – 67/100
The GEO audit is the most consequential for a site built explicitly for AI citation. NowServingTO was designed from day one to be cited by ChatGPT, Perplexity, Claude, and Gemini for queries like “newest Tamil restaurant in Toronto.” The audit scored it across five dimensions with platform-specific breakdowns.
| Dimension | Weight | Score |
|---|---|---|
| Technical Accessibility | 20% | 92/100 |
| Structural Readability | 20% | 78/100 |
| Citability (answer passages) | 25% | 64/100 |
| Authority & Brand Signals | 20% | 38/100 |
| Multi-Modal Content | 15% | 45/100 |
| Overall GEO Score | – | 67/100 |
AI Crawler Accessibility – 92/100
The robots.txt AI allowlist is comprehensive and correct. GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-User, PerplexityBot, Perplexity-User, Google-Extended, CCBot, Applebot-Extended, Meta-ExternalAgent, Bytespider, Amazonbot, cohere-ai, DiffBot, and YouBot are all explicitly Allow: /. Every commercially relevant AI indexing pipeline has access. The audit noted: “explicit allow above any potential Disallow wins the precedence contest per the spec.” The two-point deduction is for a missing crawl-rate directive that some enterprise crawlers look for as a confidence signal.
llms.txt – Grade: B+
The file does the three things an AI system most needs before citing a source: identifies what the site is, declares data freshness, and provides a structured traversal map including the machine-readable JSON feed URL with CORS enabled. The explicit statement that “multi-location chains deliberately excluded” is a strong trust signal – it pre-empts the accuracy objection an AI would have about any restaurant directory.
Two gaps. First: no RSL 1.0 license declaration. RSL 1.0 signals to AI citation pipelines that content may be cited with attribution. Bing Copilot’s attribution layer treats sources without it as usage-unknown. Adding License: https://llms-txt.org/rsl/1.0 as the second line is a 30-minute fix with direct impact on Bing citations. Second: no query-intent declaration. Adding a Primary queries: block – “What is the newest Tamil restaurant in Toronto?”, “New Ethiopian restaurant Toronto 2026” – directly improves RAG pipeline routing for exactly the queries this site was built to answer.
Passage-Level Citability – 64/100
This is the highest-impact gap for near-term citations. The /answers corpus – 57 Q&A pairs – is structurally correct: answer leads with the fact, geography is specific, data sourcing is named. The problem is length. Each answer runs approximately 35 words. The optimal citation window for AI systems is 134-167 words. At 35 words, the AI evaluates the answer as a fragment, rephrases rather than cites, and attribution is lost.
The audit produced a four-sentence expansion template: direct answer (“The newest verified-open Tamil restaurant in Toronto is [NAME] at [address] in [neighbourhood]”) → grounding context (when first seen, verified via Google Places) → differentiating detail (neighbourhood context, cuisine count) → source attribution (City of Toronto licence feed, DineSafe, Google Places). This structure produces a self-contained passage an AI can extract verbatim with full attribution confidence. The entire /answers corpus could be regenerated to this template in a single Haiku batch at under $1.
A secondary finding: the /answers questions mix navigational queries (“What is the newest Ethiopian restaurant in Toronto?”) with procedural questions (“How often is it updated?”). Procedural questions serve documentation, not citation. Moving procedural content to a /methodology page and filling the freed space with navigational answers across all 45 cuisine keys would double the citation surface.
Platform-Specific Scores
| Platform | Score | Key finding |
|---|---|---|
| Perplexity | 74/100 | Best near-term opportunity – lowest domain age threshold, prefers specificity over authority |
| ChatGPT Search | 71/100 | Direct JSON feed via llms.txt; expand /answers to 134-167 words for verbatim citation |
| Google AI Overviews | 58/100 | NewsMediaOrganization schema correct; 3-6 month timeline as domain ages |
| Bing Copilot | 52/100 | Add RSL 1.0 + Wikidata Q-entity to unlock the two signals Copilot requires |
Perplexity scored highest because it has the lowest domain age threshold of the four platforms and the strongest preference for specificity. A directory that answers “newest Ethiopian restaurant in Toronto” with a verified, dated, government-sourced result competes on specificity against evergreen review aggregators regardless of backlink authority. The audit’s assessment: this site should produce Perplexity citations within 2-4 weeks of expanding the /answers entries to the target word count.
Google AI Overviews (58/100) is the most time-constrained platform. The technical implementation is correct – NewsMediaOrganization with publishingPrinciples and actionableFeedbackPolicy are exactly the signals Google’s AIO eligibility pipeline looks for. The constraint is domain age and external editorial links. At 26 days old with no inbound links from high-authority domains, the site won’t appear in AIOs for competitive queries yet. For specific long-tail navigational queries (“newest verified-open Filipino restaurant in Toronto”), the structured data is competitive now. Timeline for broader AIO visibility: 3-6 months.
Authority and Brand Signals – 38/100
The weakest dimension, and the one most constrained by age. No Wikipedia entity, no Wikidata Q-number, no Reddit threads, no YouTube mentions (highest statistical correlation with AI citations at ~0.737), no editorial media coverage. The audit was direct: “a site with identical architecture and six months of history would score 78-82.”
The actionable items that don’t require waiting: create a Wikidata Q-entity for NowServingTO (website type, inception May 2026, country Canada, main subject: restaurants in Toronto – no notability threshold, 30 minutes), then add sameAs pointing to the Q-number in the Organisation schema and areaServed with Toronto’s Wikidata entity (Q172) for geographic entity resolution. Then add RSL 1.0 to llms.txt. These three changes move Bing Copilot from 52 to roughly 65-68 without requiring any external links.
What Changed as a Result
Ten specific fixes were made the same day as the audit.
- Neighbourhood pages un-404’d. The SXO agent caught that /neighborhood/koreatown and twenty other neighbourhood pages were returning 404. Root cause: a 2.1 MB GeoJSON file used to assign entries to named corridors had never been deployed to the production server. Without it, the ETL wrote zero neighbourhood pages and the cleanup deleted the previous ones. Deployed, rebuilt, 21 pages now live at nowservingto.com/neighborhood/koreatown and equivalents.
foundingDate→openingDateon all 253 restaurant pages. One-line template change from the schema audit. Re-deployed across all listings.- CollectionPage
@idadded to all collection pages. Every cuisine page, district page, neighbourhood page, and the homepage now has a stable@idURI. Entity graph nodes go from anonymous to referenceable. itemListOrder: Descendingdeclared on all ItemLists. Signals sort order to AI systems answering recency queries.- Three-day silent build failure diagnosed and fixed. A nested f-string using Python 3.12 syntax was running on a Python 3.10 server. The daily build had been silently failing since June 5 – the live site was three days stale and Googlebot was correctly returning 304 Not Modified. One-line fix.
- Social share URLs pointed at wrong page. The lottery game’s share button was generating
/game?pick=sluglinks pointing at a page with generic OG tags. Fixed to share/r/slug– every restaurant’s dedicated page with restaurant-specific OG title, description, and card image. - 485 editorial blurbs regenerated. Content quality analysis found second sentences collapsing into interchangeable filler. Before: “roots connecting to the Kurdish diaspora… time-honored techniques passed through generations of family cooks.” After: “Kurdish shawarma rooted in Duhok, the city in northern Iraq that anchors this West Toronto kitchen’s identity.” All 258 blurbs regenerated via Haiku batch at ~$0.50 total.
- “Taking over from X” removed from all blurbs. A specific false positive: La Casa de la Abuela (1165 St Clair Ave W) was described as taking over from Al Chile – which operates at 1159 St Clair, is still open, and is a different business on the same block. DineSafe address matching was imprecise. Removed from blurb generation entirely.
- SOPRESA AFRICAN CARIBBEAN GROCERIES blocked. A grocery store had passed every verification gate: confirmed open, Google Places OPERATIONAL, website live, LLM tagged as “Caribbean.” It was hours away from appearing in the feed as a new Caribbean restaurant. Blocked via the LLM cuisine cache.
- Homepage page-intro block removed. A prior GEO audit had added a static text block above the feed. Removed at the operator’s direction – the listing feed itself is the answer.
The Methodology That Makes It Different
Most SEO tools produce a list of issues. Claude SEO produces a structured argument for why each issue matters and what order to fix things in. The PERCEIVE→ANALYZE→VALIDATE→ACT framework means every recommendation has been through a validation step before being emitted. The dependency chains are visible: fixing HSTS unblocks the Cloudflare edge-caching configuration, which unblocks the LCP improvement, which is measurable via cf-cache-status: HIT vs DYNAMIC. You know what order to work in.
One caveat: agents can produce false positives on specific facts. Verify before acting. The specific falsifiability checks the tool provides – often a one-liner you can run in 30 seconds – are there precisely for this purpose. Use them.
Verdict
Claude SEO found ten real issues on a three-week-old site that I had been actively maintaining. Nine were fixed the same day. The neighbourhood 404 alone – 21 pages silently dead, caused by a missing GeoJSON file – would not have been found by any standard crawl tool that checks HTTP status codes without understanding why they’re returning 404.
The GEO audit’s finding about answer length – 35 words vs the 134-167 word citation window – is the kind of specific, measurable, falsifiable recommendation that distinguishes this from generic SEO advice. It’s not “write longer content.” It’s “your answer passages are 35 words and AI citation windows are 134-167 words, here is the four-sentence structure that closes the gap, here is the Haiku batch that regenerates the corpus overnight.”
The SXO analysis – specifically the SERP backwards pass identifying the page-type mismatch between NowServingTO’s collection pages and the editorial-curated-list pages Google rewards for cuisine queries – is the finding that will take the longest to act on. It’s not a bug. It’s a strategy gap. An agent identified it in five minutes by reading the actual SERP rather than auditing the page in isolation.
The tool is at github.com/AgriciDaniel/claude-seo. MIT license, no telemetry, no subscription. The site used as the audit subject throughout this post – NowServingTO, Toronto’s daily-refresh directory of newly licensed restaurants across 45 cuisine categories, chains excluded – is live and updates every morning.
