How scoring works
A 0–100 score with a letter grade, built from six weighted categories of individual audits (rubric v2.1). Every audit returns a finding with evidence and a recoverable point value, judged against llms.txt v2 (Aug 2026) — the report reads as a work queue, not a verdict.
The work this measures goes by several names: generative engine optimization (GEO), answer engine optimization (AEO), LLM SEO and AI readiness. Google’s own term for the on-site half is agentic browsing, the Lighthouse category that checks a site’s llms.txt, its WebMCP surface and the accessibility tree agents read, deliberately without producing a score. They describe one thing — making a site legible to the models that now answer on its behalf — and this page is how we score it. The audits are the individual checks behind the number.
Principles
- Weight by consequence, not by effort. An element’s weight reflects how much it changes whether an AI finds, trusts, and correctly uses your content — not how hard it is to write.
- You are scored only on what applies to you. An audit that doesn’t apply — no API, no volatile data, unregulated vertical — is removed and its weight redistributed, never scored as a zero. Anything the scan couldn’t verify is likewise excluded, not assumed absent. A brochure site is never punished for lacking an endpoint table, and a 100 must be reachable by a simple site.
- Critical failures cap the total. Some problems make everything else irrelevant. A flawless file that no crawler may fetch is worth zero, and the score must say so rather than average it away.
- Every audit is actionable. Each returns a finding with evidence and a recoverable point value, so the report reads as a work queue, not a verdict.
- Versioned rubric. Scores carry a rubric version; changes are announced. Historical grades stay comparable — see the changelog.
Categories and weights
The profile is selected by the site’s industry: regulated verticals weight compliance higher, technical sites weight agent readiness higher. A site that declares its industry in its llms.txt (an Industry: line, rubric v2.1) gets the regulated profile once that industry’s playbook is scored; otherwise the profile comes from the domain. Compliance & Trust itself is opt-in: without a scored declaration it is Not applicable and its weight is redistributed. The profile is stated on every report, so users see why compliance is worth twice as much on their scan as on someone else’s.
| Category | Generic | Regulated | Commerce | Technical |
|---|---|---|---|---|
| Retrievability & Access | 15 | 15 | 15 | 15 |
| Spec Conformance | 10 | 10 | 10 | 10 |
| Curation Quality | 25 | 20 | 25 | 20 |
| Agent Readiness | 25 | 20 | 25 | 30 |
| Compliance & Trust | 10 | 20 | 10 | 5 |
| Ecosystem Integration | 15 | 15 | 15 | 20 |
Grade bands
| Score | Grade | Meaning |
|---|---|---|
| 90–100 | A | Reference-quality. Publishable as an example. |
| 80–89 | B | Strong. Real gaps, none structural. |
| 70–79 | C | Competent content, meaningful gaps in plumbing or curation. |
| 60–69 | D | Present but underpowered — likely a generator’s output plus edits. |
| 0–59 | F | Missing, unreachable, or a link dump. |
Critical failures (caps)
Applied before category math, before the profile weights above ever run. The lowest applicable cap wins, and the report leads with it — a flawless file that no crawler may fetch is worth zero, not a discounted average.
| Condition | Cap | Why | Status |
|---|---|---|---|
no_file — No llms.txt covers the URL, at its path or any ancestor up to the root | 0 | No llms.txt covers the URL: none at its path or any ancestor path, up to the root. Reported as Not Present, not as a bad score. Applied upstream: the engine only runs on a file. | Defined, not yet applied |
self_blocking — robots.txt blocks the AI crawlers from the covering llms.txt | 25 | robots.txt (RFC 9309) disallows the covering llms.txt for an AI reader, through its own group or User-agent: *. A file no agent may fetch has no visibility value. The single most expensive mistake available. | Applied today |
unreachable — File behind auth, JS-rendered, or a cross-host redirect chain | 40 | Most fetchers will not follow it. | Defined, not yet applied |
no_h1 — Not parseable as markdown / no H1 | 30 | The one element the spec requires. Downstream tooling cannot consume it. | Applied today |
served_as_html — Served as text/html with markup | 50 | Parses badly; many clients reject. | Defined, not yet applied |
The three states
The governing rule: a site is never docked points for an element that doesn’t apply to it. Every audit resolves to one of three states. Only the first affects your score.
| State | Meaning | Effect on score |
|---|---|---|
| Scored | The gate passed. This element is relevant to your site. | Scored 0.0–1.0 and counted. |
| Not applicable | The gate failed. The element is irrelevant here. | Removed entirely. Its weight is redistributed across the applicable audits in its category, and it’s listed in the report’s Not Applicable panel with the reason. |
| Not verified | The element may apply, but the scan couldn’t determine it (render failure, rate limit, sampling gap, host timeout). | Removed from scoring and flagged for you to confirm. Never scored as absent — our measurement failure is not your deficiency. |
Weight redistribution
Removal is proportional, within the category, so the remaining audits keep their relative importance:
applicable = [a for a in category.audits if a.state == Scored]
effective_weight(a) = a.weight / Σ(applicable weights) × 100
category_score = Σ effective_weight(a) × a.scoreIf every audit in a category is removed, the category itself drops out and its profile weight is redistributed across the remaining categories by the same formula.
Worked example. Curation Quality’s audit weights add up to 100, among them Signal-to-noise (weight 16), Link descriptions (weight 16) and Curation, not a sitemap (weight 8), which applies only when the sitemap lists at least 50 pages. On a smaller site Curation, not a sitemap is Not applicable, and its 8 points don’t vanish — they’re redistributed across the audits that still apply. Signal-to-noise now carries 16 / (100 − 8) × 100 = 17.4 points of effective weight instead of 16, and Link descriptions gains in the same proportion, so the category score is still built from 100 points of weight — just spread across fewer audits.
Computing the total
The category scores and profile weights combine into a single total, then the cap applies:
for each category:
applicable = [a for a in audits if a.state == Scored]
if applicable is empty:
drop the category; redistribute its profile weight
effective_weight(a) = a.weight / Σ(applicable weights) * 100
category_score = Σ effective_weight(a) * a.score # 0–100
live_categories = [c for c in categories if not dropped]
for c in live_categories:
effective_profile_weight(c) = c.profile_weight / Σ(live profile weights) * 100
total = Σ category_score * effective_profile_weight / 100 # 0–100
total = min(total, lowest_applicable_cap)Reported alongside the number — the denominator is never hidden:
- The qualified count — “78 / 100 across the 66 elements that apply to your site.”
- Element coverage — present / qualified, from the coverage matrix.
- A Not Applicable panel — every removed audit, with the reason it was removed.
- An Unverified panel — anything the scan couldn’t determine, excluded from the score and flagged for confirmation.
- Top findings — sorted by recoverable points, so the first fix is the highest-leverage one.
- Profile and rubric version — so the grade is reproducible and comparable over time.
Recoverable points
Every audit row on the report carries a “+N pts” figure — the points that audit would add to the total if it scored a perfect 1.0, all else held equal:
recoverable_points(a) = (1 − a.score) × effective_weight(a) within its category × its category's effective profile weightSummed across every applicable audit, these figures add up to exactly 100 minus the uncapped total — the recoverable-points list and the score are the same number, just broken apart by audit.
Worked example. Say Signal-to-noise scores 0.8, carries an effective weight of 50 within Curation Quality, and Curation Quality’s effective profile weight is 25. Its recoverable points are (1 − 0.8) × (50 / 100) × 25 = 2.5 — 2.5 points of the total are still on the table for that one audit.
Recoverable now is a second, stricter number: how much the displayed — capped — total would actually move if that one audit were fixed today. When a cap is binding, recoverable now is 0 for almost every audit, because the cap holds the total down regardless of what else improves. The exception is the audit whose fix removes the cap itself: Single H1 clears the no_h1 cap, and AI crawler access or Named AI crawlers clears the self_blocking cap — those audits can recover points up to the next-lowest cap, because fixing them changes which cap (if any) applies. N/A and Not verified audits recover nothing: they were never part of the score.
Versioning
This page describes rubric v2.1. Scores carry their rubric version, and changes are announced rather than applied silently — see the changelog for what changed between versions and how it moved the corpus. Historical grades stay comparable within a version; a rescan is needed to see a grade under a newer one.