Swipefile
Not public 16 September 2026 swipefile.com

Swipefile.com technical SEO and AI search audit

A free and helpful swipe file for marketers.

Nick Gray
Presented byNick Gray, for Neville Medhora

The one sentence

Swipefile is a 4,877-post library that Google and AI systems can fetch without trouble, but the page markup is missing the signals that make a library easy to trust, index, and cite: no structured data on any URL checked, no meta description on any post checked, no byline on the post template, and a catch-all route that answers every missing URL with HTTP 200.

Most of that is template work. A handful of changes to the Next.js templates cover most of the 4,995 URLs at once, and each one can be verified with a curl.

The content work behind it (thin older posts, one-sentence category hubs) has the larger upside and the larger uncertainty, and it should be driven by Search Console and Ahrefs data that only Neville has.

What was checked, in numbers

URLs in the sitemap

4,995

23 pages, 4,877 posts, 95 categories

raw/all-sitemap-urls.txt

Posts crawled, newest first

1,974

all HTTP 200

crawl/crawl.jsonl

Crawled posts with no meta description

1,856 of 1,856

the other 118 rows are the 23 pages and 95 categories

crawl/crawl.jsonl

Pages with any JSON-LD, Microdata, or RDFa

0

0 of 1,974 crawled, 0 of 23 templates

crawl/crawl.jsonl, raw/jsonld/

Stratified word-count sample

150 posts

newest, mid, oldest

crawl/rsc-wordcount-summary.json

Median body words, whole sample

138

sample, not the archive

crawl/rsc-wordcount-summary.json

Median body words, oldest / mid / newest 50

127 / 132 / 361

plain median of the rows; the summary script reports 365 for the newest bucket

crawl/rsc-wordcount-sample.json

Sample posts under 300 words

99 of 150

sample

crawl/rsc-wordcount-sample.json

Sample posts with a meta description

0 of 150

sample

crawl/rsc-wordcount-sample.json

Ahrefs Domain Rating

58

free endpoint, not Site Explorer

raw/ahrefs-dr.json

Phone Core Web Vitals, p75, latest 4 weeks

LCP 3,253 ms

INP 221 ms, CLS 0.0

raw/psi/crux-history-phone.json

Desktop Core Web Vitals, p75

LCP 2,255 ms

INP 68 ms, CLS 0.01

raw/psi/crux-history-desktop.json

The crawl stopped at 1,974 URLs on purpose. Every post uses the same template, and the 1,974 rows already agreed with the 23 hand-fetched templates on every structural fact. The word-count sample was drawn separately so that old posts are represented: 50 from the oldest sitemap file, 50 from the middle, 50 from the newest.

Data: every URL in the sitemap, a crawl of the 1,974 newest posts, a 150-post stratified word-count sample across the whole archive, 23 template pages fetched and 5 of them rendered in a headless browser, Chrome field data for 25 weeks, PageSpeed lab runs on 5 templates, and the free Ahrefs Domain Rating endpoint. No Search Console, GA4, or Ahrefs Site Explorer data was used.

The site as tested

Homepage, desktop
Homepage, phone

Both screenshots are from 16 September 2026. The homepage HTML behind the desktop view is 695,495 bytes, of which about 361 KB is the card catalog serialized a second time as inline React Server Component data.

Do these first

Ranked by evidence strength and how many URLs each item touches. No time estimates. Owner is who has to touch it.

A

Template fixes

Each one is verifiable with a curl and covers most URLs at once.

1

Return a real 404 from the catch-all route

Every missing URL answers 200 today, so no tool can find the dead internal links.

Touches Every missing URL, plus /index.html, /llms.txt, /random, /secret

DevAgent
For the engineer
  • /[...slug] returns 404 (or 410) in the first response, not a 200 with noindex. The existing noindex already keeps these out of the index, so this is a correctness fix, not an index-bloat emergency.
  • /index.html 308 to /.
  • /random becomes a server-side 302 to a post. /secret returns 404 (or 401) for logged-out visitors. Do not pair noindex with a robots Disallow; a blocked page cannot show its noindex.
  • Check with GET, not only HEAD, on a cold and a warm request.

Check it

curl -s -o /dev/null -w "%{http_code}" https://swipefile.com/this-does-not-exist-9d8f
# expected: 404

Agent prompt

In the Next.js app, make the catch-all [...slug] route resolve the post before anything streams, and call notFound() when it does not exist, so the HTTP status is 404 and not a streamed 200. Add a redirect from /index.html to / in next.config with permanent: true. Verify in production with GET requests on a cold and a warm cache that an unknown slug returns 404 and that /llms.txt no longer returns the app shell.
2

Canonicals, redirects, and pagination

The definition page canonicalises to a URL that redirects back to it, and 19 sitemap pages have no canonical at all.

Touches 19 sitemap pages, both definition slugs, pagination on 96 listings

Dev
For the engineer
  • Pick /what-is-a-swipe-file. Self-canonical it. Put it in the sitemap. Keep the 308 from the other slug.
  • Self-referencing canonical on /tools, the nine tool pages, /profiles, the profile pages, /popular/all, /popular/week, /popular/month, /contact, and /database.
  • og:url equals the canonical on every page. Twelve inner pages point at the homepage today.
  • 308 /page/1 to / and /category/{slug}/page/1 to /category/{slug}. Page 2 and later keep their own self-canonicals.
  • On /category/{slug}, make the next link go to /category/{slug}/page/2, not /page/2. Google ignores rel=next/prev as a hint; the fix is the crawl path the plain links create.
  • 308 uppercase slugs to lowercase.

Check it

curl -s https://swipefile.com/what-is-a-swipe-file | grep -o 'rel="canonical" href="[^"]*"'
# expected: the hyphenated URL itself
3

Add JSON-LD in the server HTML

No page on the site carries structured data, so nothing ties the library to its author or its organisation.

Touches All 4,995 URLs

DevAgent
For the engineer
  • Shared layout: recommended/organization.jsonld and the WebSite node from recommended/website-searchaction.jsonld. WebSite supports the site name in Google results. SearchAction is optional; Google retired the sitelinks search box in November 2024, and the /search?q= page renders no results server-side today.
  • Post template: recommended/article.jsonld. Author must match a visible byline (item 4). recommended/breadcrumb.jsonld is optional; mobile results no longer show breadcrumbs.
  • Profile template: recommended/profilepage.jsonld and recommended/person-neville.jsonld.
  • Category template: recommended/collectionpage.jsonld.
  • Check with the Google Rich Results Test on one post. Use the Schema.org validator for ProfilePage and CollectionPage, which produce no rich result and are there for entity clarity.
  • What this buys: eligibility for Article rich results and a machine-readable entity graph. It is not by itself a ranking lift.

Agent prompt

Add a <script type="application/ld+json"> block to each Next.js template using the JSON in recommended/. Fill fields from the same data the page already renders (title, canonical URL, published date, share image, category, author profile). Render it in the server HTML, not in a client effect. Keep @id values stable: https://swipefile.com/#organization and https://swipefile.com/#website.
4

Visible byline on every post, and say who runs the site on About

The post template credits Swipebot. No human name appears on the page that a reader or a model can attach the work to.

Touches 4,877 posts and /about

NevilleDev
For the engineer
  • Post template: a byline that names the real author or curator, with an accurate label ("Curated by", "Analysis by", or "Reviewed by"), linking to that person's profile. article:author and the same Person node in Article JSON-LD. Do not put a name on work that person did not write or review.
  • About: first paragraph says who runs Swipefile.com, links the profile, and states the site is free and curated. State the founding date only from a real record, not from the profile's Joined Aug 2017 line.
  • Keep "Analyzed by Swipebot" as a tool credit if wanted. Put a person first.
5

The definition paragraph

Nothing on the site says in one quotable sentence what Swipefile.com is.

Touches /, /about, /what-is-a-swipe-file

NevilleDev
For the engineer
  • One short self-contained paragraph: what Swipefile.com is, that it is free, who curates it, how many examples, how often it updates. Numbers inside the sentence, not in a widget.
  • Today no such paragraph exists anywhere on the site. It gives Google and AI systems something to quote for the brand query. No length guarantees a citation.
B

Content work

The larger upside and the larger uncertainty. Gated on Neville's data and reviewed by a person.

6

Content inventory and decisions, with data

The order of every content change depends on reports only Neville can open.

Touches The whole archive

Neville
For the engineer
  • Search Console page and query performance (full history, device and search-type splits including Image), the Pages indexing report, and Ahrefs page-level backlinks decide it. Top pages alone is not enough.
  • "No traffic, no links, short" is a review filter, not a deletion rule. Check impressions, image search, age, internal discovery, and unique value. Keep useful swipes. Improve pages with unmet demand. Consolidate real overlaps with redirects. noindex pages kept for users but not for search. 404 or 410 only for removed content with no replacement. Do not remove swipes to raise an average word count.
7

Upgrade posts by opportunity, not by age

The archive median is about 130 words on one repeated skeleton, and that is the largest content upside on the site.

Touches The older half of 4,877 posts over time

NevilleAgent
For the engineer
  • Do not pad, and do not swap one skeleton for a longer one. Add one self-contained paragraph a reader could quote alone: who made the ad and when if known, the persuasion device, why it plausibly works, any documented result. "Unknown" is allowed. An advertised price is not proof the ad performed. Keep the image and source link.
  • Order: posts with impressions but weak clicks, posts with links, posts in ranking decay (Search Console and Ahrefs, item 6). The oldest sitemap file (post-sitemap-5.xml, 877 URLs; the 50 oldest sampled at median 127 words) is the fallback order only where that data is missing.
  • Run a cohort first: 50 to 100 posts against comparable unchanged posts. Track impressions, clicks, and indexing before scaling. A bulk, unreviewed AI rewrite is the scaled-content pattern Google's guidelines warn about; human review of every batch is part of the job.
  • Set the real modified date when a post is rewritten so the visible "Updated on" line is true.

Agent prompt

For each URL in this CSV, read the live page and its source link. Draft one paragraph that names the advertiser and year if visible, the medium, the single persuasion device, why it plausibly works, and any documented number from the ad or its source. Write 'unknown' rather than guess. First sentence answers 'what is this swipe and why does it work'. Match the site's voice: direct, specific, no filler. Flag anything uncertain for review. Output url, draft_paragraph, uncertainties.
8

Category hub copy and taxonomy

95 hubs are the natural landing pages for example queries and each carries one sentence of its own text.

Touches 95 category pages

NevilleAgent
For the engineer
  • First check whether several hubs split one search intent (ads, outdoor-advertising, billboards; social, instagram, tweets). Merge before writing.
  • Then a real introduction per hub, sized to the topic: what the cluster is, when a marketer reaches for it, a few featured swipes with one sentence each on why, linked. Keep the H1 count and the grid.

Agent prompt

For each category URL, read the page and its first 20 posts. Draft an introduction: what this kind of marketing example is, when a marketer would use one, and three featured posts from the list with one sentence each on why. Link the three posts. No generic advice, no fixed length. Flag any category that overlaps another.
C

Cheap insurance

Template one-liners that remove a wrong signal rather than add a new one.

9

Meta description on every post

1,856 of 1,856 crawled posts have none, so Google writes every snippet from whatever text it finds first.

Touches 4,877 posts

DevAgent
For the engineer
  • This is snippet copy, not a ranking fix.
  • Template fallback: first analysis sentence plus advertiser and device. Programmatic is fine. Also emit og:description.
  • Hand-written descriptions only where Search Console shows impressions and weak click-through (item 6), and only later.

Agent prompt

Using site/swipefile-posts-crawled-1974.csv and the live page, write a unique meta description for each post in the list. Use the post title, first paragraph, and category. Name the advertiser or brand and the tactic. No stock call to action, no fixed length. Output a CSV with url, meta_description.
10

Sitemap hygiene

70 percent of posts share one batch lastmod, so the dates describe a migration and not an edit.

Touches The sitemap index and its six children

Dev
For the engineer
  • Keep one content record with real published and modified dates. Feed the visible date, Open Graph, JSON-LD, and sitemap lastmod from it. Where no trustworthy modified date exists, omit lastmod rather than invent one. 7 of 10 recent posts currently show lastmod before publish.
  • Do not batch-stamp lastmod on migrations. 3,410 of 4,877 posts share 7 or 8 November 2025; 109 share 27 to 28 August 2026.
  • Remove /popular/week and /popular/month. Add /financial-escape-velocity-calculator, /profiles/alexlieberman, /profiles/benpixel, the live /case/* pages, and any post published after the last sitemap write.
  • Update the index lastmod for page-sitemap.xml when the child changes.
11

A real /llms.txt

/llms.txt answers 200 with 217 KB of the app shell, which is worse than either a real file or a 404.

Touches /llms.txt and robots.txt

DevNeville
For the engineer
  • Optional. Google's AI features do not use it. Serve as text/plain from public/ or a rewrite that bypasses the catch-all, or let item 1 return 404.
  • recommended/llms.txt is drafted from the live site structure. Its descriptive lines are draft copy for Neville to edit, not site text.
  • Which AI crawlers to allow for search, retrieval, and training is a business decision. Today all 14 tested crawlers get 200. A Content-Signal: line in robots.txt can state the policy; it is not a ranking lever.

Check it

curl -sI https://swipefile.com/llms.txt | grep -i "^content-type"
# expected: text/plain
D

Later

Real work with a real payoff, but nothing here blocks anything above.

12

Phone speed

Phone LCP 3,253 ms and INP 221 ms, both in needs improvement, and neither was good in any of the 25 weeks.

Touches Homepage, category, profile, and the pricing calculator

Dev
For the engineer
  • Confirm the URL groups in the Search Console Core Web Vitals report before choosing where to start.
  • YouTube: poster image facade, load the player on click (homepage and profile).
  • Defer GTM until after first paint; drop the <head> preload. Load the PostHog session recorder after consent or on a sample.
  • Stop inlining the full card catalog as RSC data on /, /popular/*, and categories. 361 KB on the homepage.
  • Serve card images as WebP or AVIF at display size. Preload only the real LCP image.
  • Replace or lazy-load the Leadpages embed on the pricing calculator.
13

Cleanup

None of these is a ranking factor. They are correctness.

Touches Shared layout and the post template

Dev
For the engineer
  • Security headers (nosniff, Referrer-Policy, frame-ancestors).
  • One-hop redirect for http://www.swipefile.com/.
  • Move "Command Palette" off the heading outline. One H1 in the delivered homepage HTML.
  • Descriptive alt text on post hero images.
  • 48 pixel tap targets on mobile header buttons and post chips.
  • Fix the doubled /profiles title and add an intro line.
  • Watch for <title>X</title> on real posts on cache misses.
  • Label owned-product links on posts.

What already works

1Every missing URL returns HTTP 200

Fix first

The Next.js catch-all route answers unknown paths with a 200 status, no <title> in <head>, a noindex tag, and a canonical pointing at the missing URL itself.

URLStatusPage title in <head>Bytes
/this-does-not-exist-9d8f200none217,557
/index.html200none217,431
/llms.txt200none217,413
/sitemap_index.xml200 (HTML)none

Some SEO tools report the title of these pages as X. That is the <title> inside the X logo SVG in the footer, which every page carries. There is no page title.

Why it matters: Google calls this a soft 404. The noindex tag keeps these pages out of the index, so this is hygiene, not an emergency. The cost is elsewhere. Because everything is 200, no crawler or monitoring tool can find the dead internal links. Internal links already point at at least five dead slugs that get this treatment, for example /act-like-a-new-neighbor-not-a-brand and /olgivy-then-and-now-mission-statement. Any tool that trusts a 200 status (AI clients asking for /llms.txt, sitemap validators, uptime checks) is misled.

Two more routes share the pattern with no noindex at all. /random and /secret return a Next.js error shell (<html id="__next_error__">), no canonical, no robots tag, and they are linked from the site header. Both are indexable empty documents.

2Zero structured data on every URL checked

Fix first

This is entity and machine-readability work, not a ranking lever on its own. Article markup makes posts eligible for Article rich results. Organization and Person markup with sameAs is what ties the site to its author and social accounts for search engines and AI systems. The audit found no application/ld+json, no Microdata, and no RDFa on any of the 23 templates, the 5 Playwright renders, or the 1,974 crawled posts. Open Graph tags exist. They are not Schema.org.

OrganizationWebSiteArticleProfilePageCollectionPageBreadcrumbListShared layout00Post template00Category template00Profile template00 of 23 templates0 of 1,974 crawled pages carry any JSON-LD, Microdata or RDFa
Every cell is a JSON-LD type that belongs on a template. Every cell is empty.

The facts Schema.org needs are already on the page. A recent post, /ditch-the-generator-for-695-backup, shows a headline, a 1200 by 630 share image, article:published_time, a visible date, category chips, and a canonical. The profile at /profiles/nevmed shows a name, handle, join date, avatar, and five social links. Category pages show a count in the H1 and a description.

FileTypeWhere it goes
organization.jsonldOrganizationevery page (shared layout)
website-searchaction.jsonldWebSite + SearchActionevery page
article.jsonldArticle with author as Personpost template
person-neville.jsonld, profilepage.jsonldPerson, ProfilePage/profiles/*
collectionpage.jsonldCollectionPage/category/*
breadcrumb.jsonldBreadcrumbListposts and categories

Drafts with live site values, no placeholders, are in recommended/.

3No post has a meta description

Template fix

1,856 of 1,856 crawled posts with a publish date have no meta description. 150 of 150 in the stratified sample have none. The PageSpeed SEO audit on the recent post fails on exactly this item, score 92, not 100. Category pages are mostly fine: 87 of 95 have one.

Posts0 with a description, 1,856 withoutCategory pages87 with a description, 8 withouthas onenone
Crawled posts and category pages, by whether a meta description is present.

A meta description is snippet copy, not a ranking signal. Google writes its own snippet when the tag is missing and may rewrite one that exists. On a swipe page the first text it finds is often a category chip or the "Command Palette" heading. Posts also lack og:description, so shared links show only a title and image.

4The post template has no byline

Fix first

The default post template has no byline. The analyzer credit reads "Analyzed by Swipebot". The About page, /about, is 134 words and never says who runs the site. The person exists at /profiles/nevmed, but of 1,856 crawled posts only 152 link to any profile, and those are card links, not bylines.

The one page that does name Neville is the Friday SWIPES email, for example /the-swipes-email-friday-september-11st-2026, which opens "100% human written by Neville Medhora" and is the longest page in the sample at 1,058 words. That is the pattern the rest of the site lacks.

A recent post. Date, categories, and share image are all present. No person is named.

5The definition page fights itself, and 19 pages have no canonical

High

/what-is-a-swipe-file is the strongest content page on the site: 927 body words and a question H1. It is also the one page the sitemap and canonical get wrong. Its best block is the only one in the toolkit's 134 to 167 word target length, and it scored 60, still under the 70 citation-ready line.

URLStatusCanonical
/what-is-a-swipefile (in sitemap)308 to the hyphenated URL
/what-is-a-swipe-file (live)200points at the 308 URL above

The live page tells Google its canonical is a URL that redirects back to it. The sitemap lists the redirecting one. Pick the hyphenated URL, self-canonical it, and put that in the sitemap.

Nineteen sitemap URLs have no canonical tag at all: /tools, all nine tool pages, /profiles and the four profile pages, /popular/all, /popular/week, /popular/month, and /contact. Twelve inner pages set og:url to the homepage. And two pagination paths are indexable duplicates: /page/1 duplicates the homepage with its own self-canonical, and /category/images/page/1 duplicates the category page.

6In the sample, older posts run about 130 words on one skeleton

High, bulk work, data-gated

From the 150-post sample. The mid and oldest buckets are 100 posts; the three old posts read in full share one structure.

toolkit citation heuristic, 134 to 167 words8747141675300 words1003005007009001,050870body words per post, 50 word bins, 150 post sample
Every post in the sample, in 50-word bins. The shaded band is the toolkit heuristic, not a Google rule. Google states no preferred word count.
0100200300400Oldest 50127Middle 50132Newest 50361median body words per bucket, 50 posts each
Median body words by bucket: oldest 50 from post-sitemap-5.xml published around 2020, middle 50, newest 50 from 2026.

99 of 150 posts sit between 100 and 299 words. One post exceeds 1,000 words, and it is a newsletter. Old and middle posts share one structure: one or two sentences, an H2 "Why It Works" with four bullets, an H2 "Real-World Examples" with three names, then "Analyzed by Swipebot: Loading analysis...". Two live examples: /more-experiments-in-2024 (103 words) and /joseph-sugarman-slippery-slope (138 words).

Google's Search Quality Rater Guidelines have a section on scaled content: many pages with the same shape and little added value. The audit does not claim these pages are deindexed. It cannot see that without Search Console. It does say that thousands of URLs match that description.

Newer posts are better and still short. The BASE post at /ditch-the-generator-for-695-backup has unique H2s, real prices ($13k vs $695), and 253 rendered words. That format is the target for the archive, not a 1,500-word article.

795 category hubs carry one sentence of their own text

High, bulk work

The hub's own text is the single line under the H1. Everything below it is card titles.

/category/images has an H1, one intro paragraph identical to its meta description, and a card grid. Playwright extracted 422 words, almost all of it card titles. The category sitemap lists 95 of these. They are the natural landing pages for "billboard examples" or "pricing page examples" queries and they have nothing to rank with beyond a title.

8Sitemap dates do not describe real edits

Medium

The sitemap is valid, split correctly, and HTTPS-only. The dates in it are not trustworthy, and Google only uses lastmod when it is consistently accurate.

15 Sep 00:0015 Sep 12:0016 Sep 00:00sitemap lastmod, 15 September 01:30published, 16 September 00:00changed 22.5 hours before it existedone recent post: /make-fiber-the-star-in-product-comparisons
One recent post. The sitemap says it changed before it was published. 7 of the 10 newest posts do this.
3,410 posts stamped 7 or 8 November 202570% of 4,877 posts109 posts stamped 27 or 28 August 20262% of 4,877 posts21 pages share one rebuild stamp91% of 23 pages16 categories share a midnight stamp17% of 95 categories
The rest of the sitemap dates are batch stamps from rebuilds and migrations.

10Speed: phones fail, desktops pass

Medium, later

Chrome field data, 75th percentile, latest 4-week window.

Form factorLCPINPCLSVerdict
Phone3,253 ms221 ms0.0Does not pass. LCP and INP are in needs improvement, not poor, and neither was good in any of the 25 weeks.
Desktop2,255 ms68 ms0.01Passes. LCP and INP good in all 25 weeks. CLS sat in needs improvement (0.12 to 0.14) for four weeks in March and April and is 0.01 now.
Homepage URL, desktop2,669 ms74 ms0.01 (all form factors)The homepage alone misses the LCP threshold on desktop too.
good threshold 2,500 ms3,253 ms04,0742026-03-012026-09-12Phone LCP, 75th percentile, 25 weeksgood threshold 200 ms221 ms02802026-03-012026-09-12Phone INP, 75th percentile, 25 weeks

25 weeks of phone field data from Chrome, 1 March to 12 September 2026. The shaded zone is the good threshold. The line never enters it.

Trust these over Lighthouse. Lab mobile LCP on the homepage was 12.2 seconds and that number is not what real visitors see. The lab run still names the causes.

PerformanceAccessibilityBest practicesSEOHome63 / 5492 / 91100 / 77100 / 100Post56 / 6393 / 91100 / 10092 / 92Category62 / 7692 / 91100 / 100100 / 100Pricing calculator29 / 6991 / 9173 / 73100 / 100Profile57 / 5391 / 9173 / 73100 / 100mobile / desktopLighthouse lab runs. Field data above is the number to trust.
PageSpeed lab scores on five templates.
/popular/all1,156 KB/popular/month1,075 KB/popular/week724 KB/695 KB/category/images522 KB/database495 KB/profiles/nevmed486 KB/page/2408 KBpost (recent)235 KB404 shell218 KBuncompressed HTML in the first response
Uncompressed HTML in the first response. Brotli brings the homepage wire size down to about 44 KB (gzip would be about 86 KB), but the browser still parses all of it.
Homepage HTML, 695,495 bytes in the first responseInline React Server Component data, 361,169 bytesMarkup, 328,000 bytesOther inline script, 6,281 bytesInline CSS, 107 bytes
About 361 KB of the homepage HTML is the card catalog serialized a second time.
Time to first byte589 msResource load delay1,054 msResource load duration209 msElement render delay1,021 mshomepage field data (CrUX), LCP subparts
The delay is before the image request and after the download, not the download itself.

11AI search readiness

This section uses both toolkits. Where they agree, the finding is stated once.

citation ready, 70Home43.4About55What is a swipe file45.2Recent post42.7Hathaway post (2017)196 copywriting formulas29Category: images37.4top five blocksevery block0100
Citability scores from citability_scorer.py. The homepage drops to 27.3 across all blocks because 16 of its 24 blocks are 20-word card captions. Post scores come from three URLs: a recent post, the 2017 Hathaway post, and /6-copywriting-formulas.
Perplexity63Claude62ChatGPT59Google AI Overviews46Gemini46geo-seo-claude platform rubric, out of 100
Platform readiness from the geo-seo-claude rubric.

9What Neville can check that this audit could not

Second opinion

The draft action plan was sent to ChatGPT (gpt-5.6-sol, xhigh effort) through the Codex CLI on 16 September 2026, with the report summary and the verified facts. Its headline objection: the priorities overvalue metadata and undervalue discovery, content usefulness, and mobile performance. Number of URLs touched measures implementation reach, not organic impact.

What the audit changed because of it

Where the audit still disagrees

A separate fact-check pass then recomputed every number on this page from the raw crawl, sample, and API files before publication. Its corrections are already applied.

12Cleanup list

Small items, each with a file reference in findings/.

14Scores, for reference only

How this was done