The proof

How the Inspector is tested, in public.

This page used to show websites as proof. Now the proof is the instrument: how the Inspector reads a page, and how we check that it tells the truth.

40
Checks it can run
9
Requests, at most
113
Pages with known answers
One inspection

What one inspection does.

The Inspector reads one page, the front page, from the outside, the way a stranger's first visit receives it, without running its scripts. It makes at most 9 requests: the page, and a few small files like robots.txt, the file where a site says which automated readers are welcome. It stops after 12 seconds or 3 megabytes.

It can run 40 checks. Every one of them is listed below with what it is worth, because a score you cannot take apart is a score you have to take on trust.

The score is a weighted average. Each check that applied earns a share of its weight: all of it for a pass, part of it for a warning, none for a fail. Add up what was earned, divide by the weight of every check that applied, and that is your number out of 100.

When it cannot measure a check, the report says so and leaves that check out of both totals. A site is never marked down for what we could not see, and the engine never guesses.

Every report ends with a table of evidence for every request it made: what was asked for, where, the answer, the time and the size.

What it cannot see is written down on its own page.

All 40 checks, and what each one is worth

Weights are read from the engine when this page is built, so this table cannot drift from the code it describes. A check marked for one trade only runs when the page reads as that trade.

CheckWorth
A way to get in touch3
Built for phones3
Content arrives with the page3
Missing pages behave3
Page title3
Secure address (HTTPS)3
Tappable phone number3
Visible to Google Search3
Business information for Google2
Image descriptions2
Keyboard navigation shortcut2
License number shown2
Menu on the site2
Menu readable on phones2
No insecure resources2
One clear headline2
Online booking2
Page language declared2
Page size2
Return and shipping policy2
Search description2
Security headers2
Server response time2
Stylesheet adapts to screens2
Assistants can read the site1
Hours where Google reads them1
Images hold their place1
Images load when needed1
Link preview tags1
Looks current1
One official address1
Outside dependencies1
Preview image actually loads1
Script load1
Search engine instructions1
Service area written out1
Site icon1
Sitemap1
Spanish version1
Written to be understood1
Known weights

Two known weights on the scale.

A kitchen scale is checked with a weight you already know. So is the engine: 5 live websites every test session, two of them reference weights.

A known-excellent site

It must score at least 87, with at most 1 failed check, on the middle of 3 reads, because response time moves with the network.

A near-empty page

It must score no more than 70. A page with almost nothing on it must never look good.

If either weight drifts, we suspect the instrument first. The floor and the ceiling move only with a written reason.

What else the session checks, on every site it reads

It asserts 9 things each time, the reference weights among them. The grade must match the score on the engine's own ladder. Every quote the report puts in a site's mouth must really be on the page. Every request the engine made must show in the evidence table. Every skipped check must say why. And the partial credit a page earned on each check stays inside the engine, while every check in the report must carry its published weight.

Known answers

113 saved pages with known answers.

A fixture is a saved web page whose right answer was decided before the engine saw it. A security challenge page must be refused, not graded. A restaurant inside a casino must still be graded.

Our test suite runs 177 cases on those 113 saved pages and on test pages written into the suite itself. We run it when the engine changes. A wrong answer on any case is a reason to stop, though no automatic step blocks the change. Some cases were written after a real mistake.

The 177 cases, and what each one must do

Each row names a test page and the answer the engine must give on it. The answers are in the suite's own words, except the skip-link rows, which we put in plain words.

"Schema" here is the business information a page hands to Google, the check listed above as Business information for Google.

A skip link lets someone using a keyboard jump past the menu to the content. Its check is listed above as Keyboard navigation shortcut.

CaseWhat the engine must do
skiplink/a-span-in-link-div-targetthe skip-link check must pass
skiplink/a-span-in-link-main-targetthe skip-link check must pass
skiplink/a-aria-label-emojithe skip-link check must pass
skiplink/a-img-alt-in-linkthe skip-link check must pass
skiplink/b-unquoted-hrefthe skip-link check must pass
skiplink/b-unquoted-role-mainthe skip-link check must come back with a warning
skiplink/b-single-quoted-hrefthe skip-link check must pass
skiplink/c-meet-the-skipperthe skip-link check must fail
skiplink/c-skipping-the-queue-in-mainthe skip-link check must come back with a warning
skiplink/c-anchor-menu-servicesthe skip-link check must come back with a warning
skiplink/c-cta-before-navthe skip-link check must come back with a warning
skiplink/d-missing-target-no-mainthe skip-link check must fail
skiplink/d-missing-target-with-mainthe skip-link check must come back with a warning
skiplink/d-target-in-templatethe skip-link check must fail
skiplink/d-hash-top-no-idthe skip-link check must fail
skiplink/d-hash-top-main-id-topthe skip-link check must pass
skiplink/d-base-href-other-paththe skip-link check must fail
skiplink/d-root-slash-hashthe skip-link check must pass
skiplink/d-target-before-navthe skip-link check must fail
skiplink/d-target-wraps-headerthe skip-link check must come back with a warning
skiplink/d-target-anchor-end-of-navthe skip-link check must pass
skiplink/d-script-hook-missing-targetthe skip-link check must be skipped as not verified
skiplink/e-data-role-mainthe skip-link check must fail
skiplink/e-main-aria-hiddenthe skip-link check must fail
skiplink/e-main-hiddenthe skip-link check must fail
skiplink/e-role-foo-mainthe skip-link check must come back with a warning
skiplink/e-main-wraps-headerthe skip-link check must fail
skiplink/f-skip-link-in-footerthe skip-link check must fail
skiplink/f-logo-nav-then-skipthe skip-link check must fail
skiplink/f-logo-skip-div-menuthe skip-link check must pass
skiplink/f-tabindex-minus-onethe skip-link check must fail
skiplink/f-inline-display-nonethe skip-link check must fail
skiplink/f-hidden-by-classthe skip-link check must pass
skiplink/f-link-aria-hiddenthe skip-link check must come back with a warning
skiplink/g-link-in-script-stringthe skip-link check must fail
skiplink/g-link-in-templatethe skip-link check must come back with a warning
skiplink/g-link-in-noscriptthe skip-link check must come back with a warning
skiplink/g-wp-block-theme-scriptthe skip-link check must be skipped as not verified
skiplink/g-wp7-server-sidethe skip-link check must pass
skiplink/h-no-links-h1-prosethe skip-link check must be skipped
skiplink/h-no-links-mainthe skip-link check must be skipped
skiplink/h-content-then-footer-linkthe skip-link check must be skipped
skiplink/h-menu-at-bottomthe skip-link check must be skipped
skiplink/h-wp-plain-permalinksthe skip-link check must come back with a warning
skiplink/i-plain-skip-linkthe skip-link check must pass
skiplink/i-spanish-saltarthe skip-link check must pass
skiplink/i-jump-to-main-contentthe skip-link check must pass
skiplink/i-breadcrumb-nav-inside-targetthe skip-link check must pass
skiplink/i-article-header-inside-targetthe skip-link check must pass
skiplink/i-target-hero-inside-headerthe skip-link check must pass
skiplink/i-two-skip-links-g124the skip-link check must pass
skiplink/i-skip-link-first-inside-headerthe skip-link check must pass
skiplink/j-nav-then-headings-no-mainthe skip-link check must come back with a warning
skiplink/j-headings-only-in-div-footerthe skip-link check must fail
skiplink/j-heading-inside-div-mega-menuthe skip-link check must fail
skiplink/x-T1-div-header-skip-wraps-main-article-headerthe skip-link check must pass
skiplink/x-T1b-breadcrumb-home-only-inside-targetthe skip-link check must pass
skiplink/x-T1c-breadcrumb-two-links-inside-targetthe skip-link check must pass
skiplink/x-T15-target-hero-inside-headerthe skip-link check must pass
skiplink/x-T2c-logo-skip-div-menuthe skip-link check must pass
skiplink/x-T3-div-nav-div-footer-h4-onlythe skip-link check must come back with a warning
skiplink/x-T3b-div-mega-menu-h3-onlythe skip-link check must fail
skiplink/x-T5-wp-plain-permalinksthe skip-link check must fail
skiplink/x-T6-anchor-menu-services-in-mainthe skip-link check must come back with a warning
skiplink/x-T7-cta-before-navthe skip-link check must come back with a warning
skiplink/x-T8-noscript-link-before-skipthe skip-link check must pass
skiplink/x-T19-content-then-footer-elementthe skip-link check must be skipped
skiplink/x-T19b-content-then-footer-divthe skip-link check must be skipped
skiplink/x-N1-minified-no-whitespacethe skip-link check must pass
skiplink/x-N2-name-split-across-inline-and-commentthe skip-link check must pass
skiplink/x-N3-id-twice-first-hiddenthe skip-link check must come back with a warning
skiplink/x-N4-target-inside-svgthe skip-link check must pass
skiplink/x-N4b-target-inside-maththe skip-link check must pass
skiplink/x-N5-uppercase-tags-and-attributesthe skip-link check must pass
skiplink/x-N6-percent-encoded-fragment-utf8the skip-link check must pass
skiplink/x-N7-title-only-name-img-empty-altthe skip-link check must pass
skiplink/x-N8-button-before-skip-outside-blockthe skip-link check must pass
skiplink/x-N8b-button-then-skip-inside-header-blockthe skip-link check must pass
skiplink/x-N9-article-header-before-targetthe skip-link check must pass
skiplink/x-N10-target-wraps-the-link-itselfthe skip-link check must fail
skiplink/x-N11-js-shell-onlythe skip-link check must be skipped as not verified
skiplink/x-N12-a-inside-a-adoptionthe skip-link check must pass
skiplink/x-N13-link-in-table-cellthe skip-link check must pass
skiplink/x-N13b-link-foster-parented-out-of-tablethe skip-link check must pass
skiplink/x-N14-adoption-agency-b-a-skipthe skip-link check must pass
skiplink/x-N15-unclosed-p-before-linkthe skip-link check must pass
skiplink/x-N16-percent-encoded-id-literalthe skip-link check must pass
skiplink/x-N17-role-navigation-uppercase-hidden-drawerthe skip-link check must pass
skiplink/x-N18-inline-script-builds-skip-linkthe skip-link check must come back with a warning
skiplink/x-N19-target-in-closed-detailsthe skip-link check must pass
skiplink/x-N20-area-skip-linkthe skip-link check must pass
skiplink/x-Z1-one-megabyte-pagethe skip-link check must pass
skiplink/x-S1-plain-skip-link-with-stylesheetthe skip-link check must pass
skiplink/x-S2-classless-skip-link-with-stylesheetthe skip-link check must pass
skiplink/x-S3-wp7-server-side-with-stylesheetthe skip-link check must pass
honesty-challengeengine returns an error, not a grade
redirect-hijackengine returns an error, not a grade
shell-viterendering check fails on a shell page (shell was detected)
schema-jsonldschema check is not a fail
schema-microdataschema check is not a fail on a Microdata page
spanish-elementspanish check is not a flat fail on element-level lang=es
spanish-full-pagespanish check is not a fail on a full-page lang=es
spanish-none-floridaspanish check runs (not skipped) on a Florida business page
viewport-tag-onlyviewport check passes when the tag is present (regardless of layout)
same-domain-redirectengine grades the page (no error) on a same-domain redirect
promise-third-party-licensedengine does not fire promise check on third-party "licensed" advice
promise-self-licensedengine fires promise check on first-person "We are licensed"
fresh-license-commenta year inside <style>, <script> or a comment does not fail "Looks current"
fresh-template-yeara copyright year ahead of today fails "Looks current"
gate-hijackedengine returns an error, not a grade
gate-parkedengine returns an error, not a grade
gate-placeholderengine returns an error, not a grade
gate-casino-resorta restaurant in a casino hotel is graded, not refused
redirect-labelledredirect refusal is labelled elsewhere
sitemap-fallback-on-ledgerthe sitemap robots.txt names is on the ledger
unreachable-namefield says name
unreachable-refusedfield says refused
unreachable-certificatefield says certificate
unreachable-timeoutfield says timeout
unreachable-otherno field when the cause is not one we can name
noindex-meta-nonenoindex state is fail
noindex-meta-googlebotnoindex state is fail
noindex-meta-crawler-prefix-keptnoindex state is fail
noindex-text-is-not-a-tagnoindex state is pass
noindex-comment-inside-scriptnoindex state is fail
noindex-custom-elements-are-not-raw-textnoindex state is fail
noindex-shapes-that-must-not-countnoindex state is pass
noindex-meta-googlebot-newsnoindex state is pass
noindex-header-other-crawlernoindex state is pass
noindex-header-nonenoindex state is fail
noindex-header-googlebot-newsnoindex state is pass
noindex-header-googlebot-inheritsnoindex state is fail
noindex-header-joined-lines-are-ambiguousnoindex state is skip
noindex-header-robots-prefix-keptnoindex state is fail
noindex-header-values-are-not-rulesnoindex state is pass
noindex-google-two-line-examplenoindex state is pass
noindex-meta-and-headernoindex state is fail
noindex-google-kept-out-by-robotsnoindex state is fail
noindex-google-allowed-in-by-longest-matchnoindex state is fail
noindex-landed-page-not-rootnoindex state is fail
schema-phone-under-contactpointschema passes: a phone under contactPoint is a phone
schema-business-beside-website-blockschema passes: one real business block is enough; a WebSite block beside it is not a defect
schema-empty-address-stubschema warns: an address object carrying only a type is not an address
schema-one-block-broken-beside-a-real-oneschema passes on the real block
imgweight-unquoted-lazy-is-lazyimgweight state is pass
imgweight-three-eager-warnsimgweight state is warn
imgweight-shapes-that-stay-eagerimgweight state is warn
imgweight-shapes-that-stay-lazyimgweight state is pass
imgweight-noscript-pixel-is-not-an-imageimgweight state is pass
imgweight-data-src-waits-for-a-scriptimgweight state is pass
imgweight-lazysizes-transparent-srcsetimgweight state is pass
imgweight-data-uri-src-is-inlineimgweight state is pass
imgweight-whitespace-src-is-no-addressimgweight state is pass
imgweight-picture-and-srcsetimgweight state is warn
imgweight-svg-image-is-not-imgimgweight state is skip
imgweight-picture-source-is-taken-as-usedimgweight state is warn
imgweight-svg-style-and-title-are-not-raw-textimgweight state is warn
imgweight-img-inside-svg-breaks-outimgweight state is warn
imgweight-script-end-tag-in-a-string-ends-the-scriptimgweight state is warn
image-list-feeds-alt-and-dimsdims reads the size after a quoted ">" and rejects width=""
comment-strip-reads-comments-the-way-a-browser-doesthe tap-to-call link after the script string is real
readinglevel-menus-do-not-merge-into-sentencesreadinglevel passes on the two paragraphs alone
readinglevel-spanish-page-is-not-scoredreadinglevel skips
readinglevel-spanish-section-is-left-outthe English paragraphs alone are scored
readinglevel-not-enough-running-textreadinglevel skips
readinglevel-form-wrapped-page-is-scoredreadinglevel is warn on the warm paragraph, not skip
readinglevel-table-layout-page-is-scoredreadinglevel is warn on the warm paragraph, not skip
readinglevel-hero-header-inside-main-is-scoredreadinglevel is warn on the warm paragraph, not skip
readinglevel-mismatched-heading-close-is-scoredreadinglevel is warn on the warm paragraph, not skip
readinglevel-class-named-hidden-is-scoredreadinglevel is warn on the warm paragraph, not skip
readinglevel-two-mains-use-bothwith two mains, both are read (the standard names one main as the dominant content; two is not that page)
readinglevel-hidden-dialog-and-data-table-are-left-outonly the warm paragraph is scored
walkaway-1.7.0-retiredno walkaway block in the response
platform-ordering-page-is-refuseda Menufy page is refused, not graded
builder-domain-site-is-still-gradeda site on a builder's domain is the business's own site and is graded
phone-and-licence-values-are-keptthe tel check keeps one business line and the tap-to-call numbers, ten digits each, the country code dropped
a-number-with-no-phone-cue-is-not-kept-as-the-linethe line is the number beside the phone cue, not the invoice reference
The fingerprint

A version, and a seal on it.

The engine is version 1.8.1. On September 23, 2026 it read 164 pages written for the purpose, offline, and everything it produced was hashed into one fingerprint: 0ff07078bb262f37.

The fingerprint covers the grade, the score, the recognized trade and every check's state. It leaves out wording and timings on purpose: a better sentence never costs a version. A moved line in a check costs one only when a locked page sits on that line, and not every line has one yet.

Before a change can ship, the engine reads those pages again. If the fingerprint moves and the version has not, the build stops, and so does the crawler.

The census does not meet that standard yet. Of its 78,807 sites, 361 were read before the engine had a version, and 48 by code that was never saved. It will be read again under one sealed version, and the figures switch to that version only when every address has been tried under it.

The same roster

The same websites, every few days.

Nobody at those businesses asked to be graded. The engine has read the same 100 websites 2 times since October 12, 2026. On October 15, 2026 it graded 87 of them; the middle score was 82 out of 100.

A refusal is a refusal, never a grade. The benchmark page holds the whole record.

The guards

Our own pages, held to a standard first.

Strangers are graded by the engine. Our own pages are held to our house rules before every deploy: every standing rule, one runner, one verdict. If one fails, the site does not deploy.

Below is part of a real run of the program that checks our own pages. On October 12, 2026, that run held 53 rule sections. Shown are 3 of its passing lines, shortened where they ran long, and its verdict. An exit code of 0 means it finished with no failure.

$ npm run watchdog
PASS zero em dashes across all pages and 3 download(s), entities...
PASS 1 files post to web3forms, every one of them carries a key ...
PASS R67: git tracks only register/SUMMARY.json under register/;...
VERDICT: all rules hold. 4 WARNs (prompts, not drift).

Exit code 0. Any warnings the verdict counts are prompts to look again, not failures; their lines are not shown here.

Before a deploy, 131 mistakes are planted on purpose in a built page or our own files. Each of 39 hard rules gets at least one, and has to catch its own. A rule that cannot fail is decoration.

What stays home

What we will not show, and will not claim.

The weights are published, above. What stays home is where each check draws its lines, and the fractional credit a page earned against them.

We will not pretend that makes the lines a secret. Anyone who tests their own page against the inspection can find roughly where one sits, because we tell you what we measured. What we will not do is hand over the curve ready made, or spend our time defending a number instead of improving it.

We will not claim a better score earns more money. We hold scores, not sales. A score describes a front page, not a business. The Three Rings lists every refusal.

Run it

Read your own site the same way.

The free inspection runs the same 40 checks on your site in a few seconds and shows what it looked at. If the site is good, it says so.

If it read your site wrong, write to hello@truemeasurewebdesign.com. True Measure Inspector corrects its own work in public.

Inspect my website free