Two documents were read line by line into this standard: a website checklist written by Colibrity, and a third-party technical SEO audit of a live client site. Between them they carry around 345 checkable items. Most became rules. Thirty did not, and the first two sections here are the thirty.
The third section is different in kind: a rule this standard published and then withdrew, because the 2026-08-26 citation audit found the document it cited did not contain it. That is rarer and more embarrassing than declining someone else's item, which is exactly why it is on the same page rather than in a changelog nobody opens.
It exists because a requirement we quietly skip is a requirement the client still believes is being met, and the first time that surfaces will be in a review where it looks like we missed it. So each item below says what was asked for, what we do instead, and why. Several of these make the work easier rather than harder.
Three of them are worth reading even if you skip the rest, because they are the ones where doing what was asked would make a site measurably worse: the IP address in the consent log, the Core Web Vitals thresholds, and rel=prev/next.
Nothing here is a rule. If you want any of it graded, say so and it becomes one.
From the Colibrity checklist
Written by a designer, and most of it became rules. These are the items where the measurable was the problem rather than the intention - usually because the number behind it cannot be defended, or because we already grade the same outcome a different way.
Consent log stores the IP address
Checklist, section 5
What we say instead. We log everything needed to prove a consent - who, what they chose, when, and the exact sentence they saw. We deliberately do not log IP addresses: no regulator asks for them, they do not identify anyone reliably behind carrier NAT, a VPN or a CDN, and storing them would add directly identifying personal data to a record we have to keep for years.
Art. 7(1) asks you to demonstrate that a given person consented, to what wording and when; an IP adds none of those, and it is itself personal data under Art. 4(1), so logging it CREATES a minimisation and retention obligation rather than discharging one. Record it only where the client's own DPO asks in writing, and then say so in the privacy policy. Separate task, not buried in the rule: wp-starter's wps_log_consent() writes REMOTE_ADDR unconditionally with no toggle, so the reference implementation currently over-collects against what the standard says.
Filters lead to clean URLs, not query parameters
Checklist, section 8
What we say instead. Google crawls and indexes parameterised URLs fine, and we already take the opposite position deliberately - filter state has to live in the query string so a filtered view can be copied, reloaded and opened in a new tab. What we do decide, per filter, is which filtered URLs are indexable.
Shipping this would put two blockers already in the registry in direct contradiction: colibrity.filter-url-state REQUIRES filter state in the query string. Pre-adjudicated, not re- litigated.
The six-item Golden minimum summary
Checklist, the per-page list
What we say instead. Kept verbatim, as the opening of the SEO section rather than as six more rows.
It is a summary of checkboxes already inventoried individually (S7.1, S7.2, S7.4, S7.6, S7.7, S7.10, S7.13), so shipping it would duplicate seven rules and give the reader two places to look for the same threshold. It is also the best short statement of what that section is for, and it maps one-to-one onto seo.canonical, seo.sitemap, crawl.indexability-decided, crawl.internal- reachability and crawl.signals-agree - which is worth showing her, because it demonstrates her own summary is fully covered.
What you do for Google, do for humans
Checklist, meta-principle 3
What we say instead. This is the reasoning behind four rules we did ship, so it opens the section rather than sitting inside it.
No threshold means no acceptance test, and a rule nobody can fail teaches the reader to skim the ones they can. Its four parts each have a rule that does carry one: html.buttons-vs-links and colibrity.pagination-crawlable for real links, the seo.structured-data visibility widening for visible content in schema, crawl.url-format for descriptive URLs, and the seo.title-description fullness widening for full titles.
Separate code from settings
Checklist, meta-principle 5
What we say instead. Half of this is already asserted twice and the other half has no threshold, so it goes in the section intro next to the human-versus-Google principle.
seo.canonical demands exactly one canonical per page, and seo.structured-data's do already says a plugin plus a theme both emitting Organization is a validation error rather than redundancy - which is this principle's real failure mode. The rest is a working convention, and a good one, but not something a build can pass or fail.
All media files properly named
Checklist, section 6
What we say instead. Kept as an upload convention for new files, not as something you are graded on.
There is no defensible threshold behind 'properly named' - the proposal had to invent one - Google states the filename is one weak signal among many, and it only ever grades the build's own assets since a content editor can upload Final_v3 copy.png the day after handover. The one real consequence, that a space forces %20 encoding and breaks on some CDNs, is small enough to live in the handover notes.
SVGs delivered as a sprite or inlined, one request per icon avoided
Checklist, section 6
What we say instead. The optimisation half survives as a hard requirement; the delivery half does not need its own rule.
On an HTTP/2 host with far-future caching the request cost of separate files is small, and 'no asset requested more than once per page load' is now inside perf.enqueue-hygiene and practices.console-clean. The half that always pays - an untouched editor export carrying namespaces, hidden layers and full-precision paths at 5 to 20 times the SVGO size - is now a clause of perf.image-formats, so nothing is lost and no slot is spent.
Tested on throttled 3G
Checklist, section 10
What we say instead. Read and answered rather than skipped - PSI mobile already throttles to slow 4G on every run our LCP rule depends on, and hand-throttling to 3G in 2026 measures a network almost nobody in France is on.
The half of this item that IS real - a real mid-range Android and a real iPhone - survives as a widening of practices.real-device-check, which drops its animated-pages-only scope so it applies to every project. Worth saying the answer out loud in the do so the client sees the item was considered.
Max 2 font families, 3-4 weights
Checklist, section 10
What we say instead. We kept your guidance and changed the measurable. Two unsubset families at four weights each is far worse than three subset ones, so we cap the bytes - all faces under 150 KB on first load - and keep 2 families and 3-4 weights as the design guidance that usually gets you there.
It also fixes the ownership honestly: the family count is a designer decision made in the UI kit, the byte budget is ours to prove, and the current rule already caps per-file size with no cap on the total.
External link behaviour defined - rel=noopener and a new-window warning
Checklist, section 15
What we say instead. Both halves of this are now theatre. rel=noopener has been implied by target=_blank in every major browser since 2021, so requiring it changes nothing, and warning the user before opening a new window is WCAG 3.2.5 at Level AAA - above the AA bar this standard commits to.
What survives is a one-line consistency decision (do links open in a new tab, yes or no, applied everywhere) which belongs in the handover notes, not a registry slot. The 'all links tested' half IS a rule and is seo.internal-links-resolve, widened to crawl external links too and report them.
The Edge row of the five-browser test matrix
Checklist, section 15
What we say instead. Your list of five is really three engines, so we test three and say why. Edge is Blink, the same engine as Chrome, so testing both buys almost nothing. Desktop Safari and iOS Safari are both WebKit but not the same WebKit, because iOS ships its version with the OS - so the honest matrix is four passes over three engines.
The requirement survives as delivery.browser-matrix; only the Edge row is deleted, and deleted with a reason on the page rather than quietly, because a silently shortened list reads as a corner cut.
From the technical SEO audit
A third-party audit of a live site, with our counter-verification alongside. Several rows below were marked as defects and are not: they score against guidance that was retired, or against a number the auditor chose. Where a row was a genuine false positive we say so, and why, because the next auditor will raise it again.
Descriptive image filenames, hyphens not underscores
Audit, row 104
What we say instead. Same answer as your naming checkbox - a convention for new uploads, not a gate.
Google does not penalise underscores, and the remediation runs the wrong way: renaming an indexed image changes its URL and needs a redirect, so the fix costs more than the defect. Dropped together with the proposed practices.asset-naming so the standard does not carry the same weak requirement twice under two names, which is exactly the kind of near-duplicate the rule ceiling exists to catch.
Navigation elements between pages are in text form
Audit, row 14
What we say instead. Verified false positive, and worth knowing because the next auditor will raise it again.
The audit saw link labels split across several spans for a hover animation and asked for the full text in one span; the 30/07 source-HTML check found the label already complete in a single element, with the split done by JavaScript after load, so Google reads the whole label. A rule here would fire on a working pattern the standard elsewhere encourages. It looks wrong in DevTools, which is precisely why it needs a written answer.
No more than 150 to 200 links per page
Audit, row 37
What we say instead. There is no number here anyone can defend. Google retired the 100-link guideline years ago and never replaced it with a figure, and your home page passed this row at 167 links - inside a limit whose upper bound the auditor chose.
A rule whose pass and fail are one link apart on an unsourceable number teaches a client to argue about the number instead of the page. What is actually at stake - crawl depth and internal link paths - is measured properly by crawl.internal-reachability, and payload by perf.page-weight.
The most important pages receive the most internal links
Audit, row 38
What we say instead. Not measurable without a page-priority list, and nobody in the build owns that list - it is your commercial judgement and the agency information architecture.
Stated as a rule it becomes an argument about which pages are important, held during a technical review. The buildable half is already guaranteed: crawl.internal-reachability requires every indexable page to have at least one inbound HTML link, which is the failure that actually costs an index. Weighting beyond that is SEO strategy, outside this volume's stated scope.
Filter systems do not use hyperlinks visible in the source
Audit, row 46
What we say instead. We have taken the opposite position deliberately, and your auditor softened this one themselves to le point est a nuancer.
colibrity.filter-url-state and colibrity.pagination-crawlable are both blockers requiring real anchors and URL-visible state, on the argument that a control invisible to a crawler is also invisible to anyone opening a link in a new tab. The real defect on that row is different and IS caught: blog filters crawlable at ?cat=38 and ?cat=39 when /category/eau-dure/ already exists and sits in the sitemap - point the filter at the indexable page that already exists.
Filters use JavaScript/Ajax or the Post-Redirect-Get pattern
Audit, row 47
What we say instead. This prescribes an implementation where we already grade the outcome.
colibrity.filter-url-state fixes what the visitor and the crawler can observe - state in the URL, reload restores the view, a cleared filter deletes its parameter - and colibrity.filter- indexability decides which of those URLs may be indexed. Ajax and PRG both satisfy them; so does a plain GET form, which is what our starter theme actually ships and the only one of the three that works with JavaScript disabled. A rule naming the mechanism would fail the implementation the standard itself dogfoods.
link rel=prev and rel=next on paginated series
Audit
What we say instead. Out of date rather than unmet - Google stopped using rel=prev/next for indexing in March 2019 and said so publicly. Any auditor raising it is scoring against a signal Google retired seven years ago.
Worth adding that the audit itself agrees: it marks all three rows KO, assigns them NO Correctif, and writes aucune action. One correction to carry back: Correctif H is NOT this item, as the brief assumed - H is the actionable Ajax-pagination fix at L53, L54 and L56, which three colibrity.* rules already cover exactly.
URL structure does not mirror the site tree
Audit, row 64
What we say instead. House style, not guidance. Google has no preference between flat and nested URLs and has said so, this would fail every WordPress site using page hierarchies, and it sits awkwardly beside the breadcrumb rule that asks the site to expose that same hierarchy.
The real risk it names - a rename breaking child URLs - is genuine and is handled where it belongs: crawl.url-format puts slug decisions in the setup phase, and crawl.slug-change-redirect plus seo.canonical and seo.sitemap grade the follow-through when a rename happens anyway. The audit behind this grid is the proof that the follow-through is the thing worth ruling on, not the shape: one rename left 87 sitemap URLs no longer self-canonical.
Canonical declared by HTTP header for PDFs
Audit, row 70
What we say instead. No defect behind it - there is no PDF duplicating an HTML page in scope, and the proposed fix would have added a plugin and a server rule to solve nothing.
A rule here would fire on every PDF on every project and be waived every time, which is how a checklist loses its authority. If a real PDF-versus-HTML duplicate ever appears it is one clause on seo.canonical, not a rule of its own. The 'avoid declaring the canonical in the sitemap' half is already implicit in seo.sitemap, which generates rather than curates.
Pages that must not be indexed declare no canonical URL
Audit, row 73
What we say instead. Removing canonicals from your legal pages achieves nothing and costs you the self-reference if the page is ever un-noindexed.
A noindexed page carrying a self-referencing canonical is not a conflict - Google simply does not consume the canonical. The genuine conflicting signal is a page that is noindex AND canonicalises to a DIFFERENT URL, which tells a crawler to drop this page and consolidate onto another at the same time, and that is now a clause of crawl.signals-agree.
nofollow added alongside noindex
Audit, row 78
What we say instead. Google treats a long-lived noindex page as nofollow anyway, and pairing them removes the only remaining route by which the crawler discovers legitimate pages linked from it.
No threshold to test and no build action behind it, so asserting it would be a rule nobody can fail - and every one of those trains the reader to skim the rules they can.
h1 tags under 70 characters
Audit, row 90
What we say instead. Google publishes no h1 length limit, so a client held to 70 characters is being held to nothing.
The part that is real - a heading should describe the section under it - is already carried by seo.headings-describe-content as prose rather than as a character count. This is the same class of invented threshold as the 44 px touch target and the 150-link ceiling, and it is worth naming the pattern back to the auditor rather than answering three rows separately.
A single navigation menu, not a desktop and a mobile one
Audit, row 93
What we say instead. Rendering a desktop and a mobile menu in one document is normal practice and is not a crawl, indexation or duplicate-content defect - Google reads one DOM and no guidance forbids it.
The cost that IS real is DOM weight, and it now has a number: perf.page-weight caps the rendered DOM at 1400 elements and names markup duplicated to serve two breakpoints as the usual cause, which also explains the inflated img count the audit reported. A measurable beats a prohibition, and it points at the right fix - render once and let CSS reorganise.
Blog and product pages could add an aside; article should wrap the whole item
Audit, row 94
What we say instead. Taste rather than defect, and your own team classed it as continuous improvement.
There is no threshold behind 'could add an aside', and html.landmarks plus html.lists-and-tables already cover the checkable half - exactly one main, everything inside a landmark, no layout tables. Turning it into an acceptance test would give the reader a row nobody can objectively fail, which is worse than not having it.
LCP under 4 s, INP under 500 ms, CLS under 0.25
Audit
What we say instead. Those three are Google POOR boundaries, not targets. A site scored against them can be told it passed while every visitor waits nearly four seconds for the main image. We grade against the GOOD boundaries - 2.5 s, 200 ms and 0.1 - so adopting your grid numbers would loosen rules we already have.
The findings behind all three survive and fail harder at our bar: 324 ms INP across templates and 581 ms on the home page. One instrument note worth passing back gently - the grid reports CLS in milliseconds, and CLS is unitless.
HTTP/2 used for all resources
Audit, row 130
What we say instead. A property of the host, universal on any host we would ship to in 2026, and there is no build-side action behind it.
Where a host really does still serve HTTP/1.1 the symptom appears in perf.lcp and perf.score- floor, which are measured on every project anyway - so the cost shows up where it can be acted on rather than as a row that goes green by default.
document.write() is not used
Audit, row 155
What we say instead. Chrome has intervened against parser-inserted document.write on slow connections since 2017, so the browser already handles the case, and in practice it now appears only inside third-party tags nobody can edit.
Where such a tag exists, perf.third-party is where it gets challenged by name, owner and stated purpose - which is a better outcome than a row that can never realistically fail.
No intrusive interstitial covering the content on arrival
Audit, row 124
What we say instead. The row passed, and the only reservation was that the deferred triggers were never tested - so it is a re-measure, not a defect.
Proposed as seo.no-intrusive-interstitial and cut here as the weakest of the batch, on its own author's recommendation: it was argued off a PASSING row, its accept is hard to make objective ('more than a banner-sized strip'), and a consent banner is exempt while a newsletter lightbox is not, which puts a design conversation inside a technical gate. Re-open it the first time a project actually ships a timed lightbox.
URL language reflects page content - two reviewers reached opposite verdicts
Audit, row 116
NOT dropped, reported here because two slices disagreed on the same requirement and the disagreement is worth showing rather than quietly resolving. It survives as a clause of crawl.url- format, and it is settled by the PHASE rather than by picking a winner: the rule sits in setup, so the language clause binds before launch and never becomes a retro-rename gate on a live indexed rubric. Say back: 'We will not let /whitepapers/ ship on a French site again, and we are not going to rename it on the live site now - that costs a 301, a title and an h1 edit for a signal Google does not read. The archive title and h1 saying Blog we will fix, because those are read.'
One correction to carry back to the audit rather than leave buried: Correctif H is not the rel=prev/next item, which the audit itself marks as needing no action. H is the actionable Ajax-pagination fix, and three rules in this standard already cover it exactly.
Rules this standard withdrew
Published, then taken back. A rule is withdrawn when the document it cited turns out not to say it and nothing else does - not when it is merely hard, and not when our own delivered work fails it. Being ahead of our own estate is the normal condition of this standard and is recorded per rule rather than treated as a defect.
Every account the site depends on is listed with an owner
Withdrawn 2026-08-26, was ops.account-inventory
What it asked for. A handover table of every account the live site depends on - registrar, DNS zone, hosting, database, mail sender, analytics, monitoring, certificate renewal, paid licences - each with its holder, login route and renewal date, and no row held by a developer's personal account.
Why it is gone. It cited the Twelve-Factor App, and the Twelve-Factor App is about application
architecture: all twelve factors were read and none of them mentions a registrar, a DNS zone, an
account holder or a renewal date. Nothing else in the registry carries it either, and neither
delivered reference build does it - one has a single line pointing at a password manager, the other
has nothing. So the rule had no document behind it, no evidence behind it, and a required
severity in front of it.
What we still think. The registrar row is the one that matters and the argument has not changed: a lapsed domain takes everything down at once and is slow and expensive to recover. This is now something to raise at handover rather than something the gate checks. Ask for it back and it becomes a rule again, on this standard's own decision record rather than on a borrowed citation.
What still covers part of it. security.admin-accounts-at-handover covers the WordPress
administrator list, and delivery.client-handover covers the training and documentation. The
account table itself is nobody's rule now.