How the AI Visibility grade is built
Every one of the 48 checks behind the AI Visibility grade: what it measures, whether it observes your server or reads a declaration you make, the severity it is charged at, and what it is worth out of 100. Rubric v1.4.0.
We do not publish a leaderboard. This page names no site but our own, carries no example grade attached to anybody, and there is no public index of the reports we produce: a report is a private page behind a share token, marked noindex, belonging to whoever asked for it.
Everything below is generated from the scorer itself — the ids, the titles, the pillars, the severities and the point values are read out of the same module that produces your report, at the moment this page is served. If the rubric changes and this page does not, that is a bug rather than a lag.
The arithmetic
A check either passes, fails, or could not be measured. A failure costs its severity; a pass is worth exactly what the failure would have cost, which is what keeps a pillar on a 0–100 scale. A critical failure costs 6× what a minor one costs, and an important one 2×.
A check we could not measure leaves the denominator entirely. We never charge a site for our own timeout, and we never print an unmeasured check as a zero — it reads "not measured", which is a different statement.
Each pillar scores its own passes over its own counted checks, and the five are combined at the declared weights. A pillar that measured less than 50% of its own severity points drops out of the total rather than concentrating its weight on whatever survived — its percentage is still reported, because "of the two checks we could run here, you passed both" is a true thing to say and a misleading thing to grade. Dropping only happens while at least 50 of the declared 100 points survive it; below that we keep every pillar that measured anything, so a site whose server timed out is never graded on a tenth of the rubric.
Bands: A+ 95 · A 90 · B+ 85 · B 80 · B- 75 · C+ 60 · C 50 · D 35 · F 0. The letter is a pure function of the total and nothing rewrites it.
What each check is actually worth
The declared pillar weights are the number this product has always published. They are not the number that decides a check's leverage: the pillar's scoreable check count is, because a pillar's weight is divided across the severity points inside it. So one "minor" is worth more in a small pillar than in a large one, and the spread between the widest pair is 2.67×.
Nobody chose those ratios. They fell out of how many checks each pillar happened to accumulate, and they are published here rather than repaired because repairing them means moving a pillar weight, and no pillar weight may move until it has been validated against measured visibility on a held-out half. This is the honest interim: the number, and the reason it is that number.
| Pillar | Declared | Scored checks | Points per severity point |
|---|---|---|---|
| Retrievability |
30% | 13 | 0.75 |
| Parseability |
25% | 8 | 1.25 |
| Answerability |
20% | 7 | 2.00 |
| Entity and trust |
15% | 9 | 1.25 |
| Agent readiness |
10% | 5 | 2.00 |
What each check reads
The column worth having. A check either measured your server or read something your site says about itself, and those are not the same kind of evidence.
- Observed — 31 checks
- Measured on a response your server actually gave us — a status code, a header, a timing, or the bytes we received.
- Declared — 13 checks
- Read out of a declaration your site makes about itself. We parse it and take it at face value; we do not verify that it is true. These are the checks a determined site can satisfy without changing anything a reader would notice, and saying so is more useful than pretending otherwise.
- Third party — 4 checks
- Read from an index somebody else owns, which we neither control nor can reproduce on demand.
- Typed URL — 0 checks
- Read from the URL typed into the form rather than from the server that answered it. Nothing is in this class at v1.4.0 — R2 left it when it started reading the final response — and the name is kept so a check cannot fall back into it unnamed.
The 48 checks
In the order the scorer emits them. "Points" is what the check is worth out of 100 on a run where everything was measurable; on your run it will differ, because unmeasured checks leave the denominator.
Retrievability — 30% of the total
| Id | Check and what it measures | Reads | Severity | Points |
|---|---|---|---|---|
| R1 | Canonical URL responds Whether an ordinary anonymous request for this exact URL came back with a 200, and how long it took.Fix: Return 200 for the URL you want quoted; if it redirects, audit the destination instead. |
Observed | Critical | 4.50 |
| R2 | Served over HTTPS Whether the URL the server finally answered on — after every redirect — is an https one. Before v1.4.0 this read the URL typed into the form, which is not a fact about your server.Fix: Serve the canonical URL over HTTPS and redirect http to https. |
Observed | Important | 1.50 |
| R3 | Short redirect chain How many redirect hops stood between the URL we asked for and the response we got.Fix: Collapse the chain so the canonical URL answers in one hop. |
Observed | Minor | 0.75 |
| R4 | robots.txt is readable Whether /robots.txt answered, and how many bytes it held. No robots.txt is not a failure — it permits everything. |
Observed | Minor | 0.75 |
| R5 | Retrieval crawlers allowed What your own robots.txt says about the eight retrieval agents, read under RFC 9309 rules. This is your declaration, not a test that your server honours it.Fix: Allow OAI-SearchBot, Claude-SearchBot and PerplexityBot. Blocking these removes you from answers, not from training. |
Declared | Critical | 4.50 |
| R6 | Training crawler posture What your robots.txt says about the eight training agents. Reported so the choice is visible; never scored, because refusing model training is a legitimate decision. |
Declared | Not scored | |
| R7 | Crawlers reach the edge Whether your edge served a 200 to requests carrying a retrieval crawler’s user-agent token. We send those tokens from a Prompeteer address, not the vendor’s, and the vendors publish IP lists precisely so you can refuse a stranger sending their name — so a site that verifies crawlers properly refuses us and shows here as blocked.Fix: Allow these user agents at the CDN or WAF, then upload your server logs so the finding rests on your own records rather than on our probe. |
Observed | Critical | 4.50 |
| R8 | Responds quickly Wall-clock time to the first byte of the anonymous response, measured once from our network.Fix: Aim for under 800ms to first byte. |
Observed | Minor | 0.75 |
| R9 | Response is compressed Whether the response carried a content-encoding header, meaning the origin compressed it.Fix: Enable gzip or brotli. |
Observed | Minor | 0.75 |
| R10 | Sitemap reachable Whether /sitemap.xml answered with a 200 when we asked for it, which is how a crawler finds the pages nothing links to.Fix: Publish a sitemap and reference it from robots.txt. |
Observed | Minor | 0.75 |
| R11 | Self-referential canonical Whether the page’s own canonical link points back at the URL we audited. Host and path are compared after ignoring case, a trailing slash, a leading www and any query string; the scheme is R2’s question, not this one.Fix: Point the canonical at this URL, or audit the URL the canonical names — a page that canonicalises elsewhere is asking engines to quote that other page. |
Declared | Important | 1.50 |
| R12 | Page is indexable Whether a robots meta tag or X-Robots-Tag header on this page says noindex, or the bare `none` that means noindex and nosnippet together.Fix: Remove noindex, or the `none` directive, from the page you want quoted. |
Declared | Critical | 4.50 |
| R13 | Present in the open training corpus Whether Common Crawl holds captures for this domain. Reported at minor and never critical: measured, a site that blocks CCBot outright can still return index rows, and well-known sites can return none.Fix: Allow CCBot if you want to be in the open corpus, and earn inbound links. This moves over months and is not something to optimise for directly. |
Third party | Minor | 0.75 |
| R14 | Snippet extraction allowed Whether a robots directive forbids showing text from this page — nosnippet, max-snippet:0, or a bare `none`. A page can be perfectly indexable and still never quotable.Fix: Remove nosnippet and max-snippet:0. They permit indexing but forbid quoting, which is the whole of an answer engine citation. |
Declared | Critical | 4.50 |
Parseability — 25% of the total
| Id | Check and what it measures | Reads | Severity | Points |
|---|---|---|---|---|
| P1 | Content present without JavaScript How many words of visible text sat inside the page’s main region in the raw HTML, with no JavaScript executed. Under 120 words there is nothing to quote; 120 to 299 is thin.Fix: Server-render the body, and give the page 300+ words of substance in its main region. |
Observed | Critical | 7.50 |
| P2 | Not an empty SPA shell Whether the document is an empty mount point and nothing else — a div the framework fills in later, with no words in it and no words anywhere around it either.Fix: Pre-render or server-render this route. |
Observed | Critical | 7.50 |
| P3 | Bots and humans get the same page Whether a crawler user-agent and a browser user-agent received the same amount of text for this URL, in both directions. Serving crawlers more is cloaking; serving them less starves them.Fix: Serve one document to everybody. |
Observed | Important | 2.50 |
| P4 | Exactly one H1 Whether the raw HTML carries exactly one H1, so an extractor has one unambiguous title for the page.Fix: Use exactly one H1. |
Observed | Important | 2.50 |
| P5 | Heading levels are not skipped Whether the heading levels descend without skipping a level.Fix: Do not jump heading levels. |
Observed | Minor | 1.25 |
| P6 | Content sits in a landmark Whether the body copy sits inside a main or article landmark rather than loose in the body.Fix: Wrap the body copy in <main>. |
Observed | Minor | 1.25 |
| P7 | Content outweighs boilerplate What share of the document’s visible words are inside the main region rather than in navigation, chrome and footers.Fix: Reduce chrome relative to content. |
Observed | Minor | 1.25 |
| P8 | HTML within size limits Whether the response was HTML and arrived under our 2MB read cap.Fix: Serve text/html and keep the document small enough to be read whole. |
Observed | Minor | 1.25 |
| P10 | Graded document Which of the responses we collected the content checks actually read, and its word count. Reported so a reader can check every other finding against the right document; never scored. |
Observed | Not scored |
Answerability — 20% of the total
| Id | Check and what it measures | Reads | Severity | Points |
|---|---|---|---|---|
| A1 | Answer-first opening The length of the first real paragraph in the main region. 40 to 120 words is a passage an engine can lift whole.Fix: Open with a self-contained 40-120 word answer that can be lifted as a citation. |
Observed | Important | 4.00 |
| A2 | Question-shaped headings How many headings are real questions — a wh-word or an auxiliary inside the clause a question mark closes, so "How it works" and "What we do" do not count. Carries A5’s points since v1.4.0.Fix: Phrase section headings as the questions buyers actually ask. |
Observed | Important | 4.00 |
| A3 | Paragraphs are extractable The median paragraph length in the main region. 40 to 150 words is a paragraph that survives being quoted on its own.Fix: Aim for self-contained 40-150 word paragraphs. |
Observed | Minor | 2.00 |
| A4 | Structured content present Whether the main region contains a list or a table.Fix: Add a list or a comparison table. |
Observed | Minor | 2.00 |
| A5 | Visible FAQ How many of A2’s question headings carry a visible question mark. Reported and not scored since v1.4.0: it counted a subset of what A2 had already counted, so scoring both charged one measurement twice.A5 was folded into A2 in v1.4.0. A5 counted the visible questions among exactly the headings A2 had already counted, at the same threshold, so a page could not pass A5 without passing A2 — you were being charged twice for one measurement. A2 carries the points now. |
Observed | Not scored | |
| A6 | FAQ schema matches visible Q&A Whether every question in your FAQPage markup also appears as copy a person can see, matched by text against the whole visible document.Fix: Every FAQPage question must appear as visible copy. Schema without visible Q&A is a penalty, not a win. |
Observed | Important | 4.00 |
| A7 | Sentences are readable Mean sentence length across the prose in the main region, counted on the document we received.Fix: Shorten sentences toward 25 words. |
Observed | Minor | 2.00 |
| A8 | Summary near the top Whether the page opens with a heading followed by prose, rather than with a bare hero or a form.Fix: Lead with a heading and a summary. |
Observed | Minor | 2.00 |
Entity and trust — 15% of the total
| Id | Check and what it measures | Reads | Severity | Points |
|---|---|---|---|---|
| E1 | Structured data present Whether the page carries JSON-LD and whether every block of it parses. Carries E2’s points since v1.4.0.Fix: Emit valid JSON-LD, and fix any block that fails to parse. |
Declared | Important | 2.50 |
| E2 | Organization identified Which Organization type, if any, the JSON-LD graph declares — LocalBusiness and its descendants count. Reported and not scored since v1.4.0: it reads the same parsed graph E1 tests.E2 was folded into E1 in v1.4.0. E2 read the Organization node out of the same JSON-LD graph E1 parses, and over 500 seeded pages the two never disagreed. E1 carries the points now; E2 still reports what type it found. |
Declared | Not scored | |
| E3 | sameAs links How many sameAs links the graph carries out to profiles elsewhere.Fix: Link the Organization to at least two authoritative profiles. |
Declared | Minor | 1.25 |
| E4 | Connected entity graph Whether every @id this page references is also defined on this page. References to another host — Wikidata, a parent company — are deliberate links out and are not asked for.Fix: Define every @id you reference on this page. |
Declared | Important | 2.50 |
| E5 | Author is resolvable Whether a page marked up as an authored work also names an author in the graph. A homepage marked up as WebPage is not expected to have one.Fix: Name an author and resolve it to a Person node. |
Declared | Important | 2.50 |
| E6 | dateModified is precise Whether dateModified is an ISO 8601 timestamp with a time, rather than a bare date.Fix: Emit dateModified as ISO 8601 with a time and offset. |
Declared | Minor | 1.25 |
| E7 | Freshness is real Whether dateModified differs from datePublished. Having no dates at all is reported, not scored — an absence of evidence is not freshness.Fix: Update dateModified when the content actually changes. |
Declared | Minor | 1.25 |
| E8 | Social card complete Whether all three of og:title, og:description and og:image are present in the head we read.Fix: Complete the Open Graph tags. |
Declared | Minor | 1.25 |
| E9 | Resolvable public entity Whether a Wikidata entity resolves for this brand, giving engines a canonical thing to attach your name to.Fix: A Wikidata entry gives engines something to resolve your name to; it is written by other people, over months. |
Third party | Minor | 1.25 |
| E10 | Off-site brand mentions How often this brand is mentioned on the off-site source we track.Fix: Models learn brands from what others write about you, not only from your own pages. |
Third party | Minor | 1.25 |
| E11 | Domain first seen The date of the first web-archive capture of this domain. Reported and never scored: it dates the domain string, not the business — monday.com’s first capture is 1996 and the company was founded in 2012. |
Third party | Not scored |
Agent readiness — 10% of the total
| Id | Check and what it measures | Reads | Severity | Points |
|---|---|---|---|---|
| G1 | Markdown twin available Whether a markdown twin of this page exists, either at a .md suffix or through Accept: text/markdown.Fix: Publish a markdown twin. |
Observed | Minor | 2.00 |
| G2 | Well-known discovery Whether any of the seven /.well-known/ paths we ask for answered with a 200.Fix: Publish an agent-content index under /.well-known/. |
Observed | Minor | 2.00 |
| G3 | MCP endpoint declared Whether an MCP endpoint answered, at /.well-known/mcp.json or at /mcp, so an agent can act and not only read.Fix: Expose an MCP endpoint so agents can transact, not just read. |
Observed | Minor | 2.00 |
| G4 | Machine-readable API surface Whether /openapi.yaml or /.well-known/api-catalog answered, which is how an agent learns what it can call here.Fix: Publish an OpenAPI document. |
Observed | Minor | 2.00 |
| G5 | Link: alternate header Whether the response carried a Link header advertising alternate representations.Fix: Advertise alternates in a Link header. |
Observed | Minor | 2.00 |
| G6 | llms.txt (reported, not scored) Whether /llms.txt exists. Reported and never scored: Google states it has no effect on Search and no engine has confirmed reading it. |
Observed | Not scored |
Checks that stopped charging
An id is never reused and two checks are never folded into one, because the id is the join key for every audit we have already stored. A check that turns out to be measuring the same thing as another one keeps its id, keeps reporting, and stops charging.
- A5 → A2. A5 was folded into A2 in v1.4.0. A5 counted the visible questions among exactly the headings A2 had already counted, at the same threshold, so a page could not pass A5 without passing A2 — you were being charged twice for one measurement. A2 carries the points now.
- E2 → E1. E2 was folded into E1 in v1.4.0. E2 read the Organization node out of the same JSON-LD graph E1 parses, and over 500 seeded pages the two never disagreed. E1 carries the points now; E2 still reports what type it found.
Retired ids
When a critical failure holds the grade
A failing critical check can hold the headline grade rather than being averaged away. The letter itself never changes — remapping it would put a report's dot above a guide line labelled with a different letter — so the hold travels beside the score as its own state.
No check is admitted to that gate today. The mechanism ships inert on purpose: a gate turns our measurement error into somebody’s letter, so a check joins it only against a stated, measured false-positive bound, and we do not have one yet for any check.
Two checks are named as permanently excluded, with the reason kept beside the rule so a later reader cannot mistake it for an oversight:
- R7 — The block is inferred from our own fetch carrying somebody else's crawler token from our address. Vendors publish IP lists precisely so a site can refuse that, so a well-configured site fails it — the false positive rate is high and unmeasured, and it points the wrong way.
- R13 — A third-party corpus that archives a randomly selected subset of the web. Absence from it is not absence from anything a reader cares about, and no site can fix it.
What this rubric does not measure
A grader that lists only what it measures invites you to assume the rest was considered and passed. It was not.
- Anything off your site
- Who links to you, who writes about you, how often your brand is mentioned anywhere we do not fetch ourselves. Four checks are declared for third-party indexes and every one of them returns unmeasured on every audit today, because the collector behind them is not wired to anything — they take no points off anybody and they add none. When off-site signals do arrive they will sit beside the grade as evidence and not inside it, because they come from third parties we do not control and cannot reproduce on demand.
- Anything only your own data can answer
- Server logs, Search Console and Bing exports, analytics, referrals from assistants, conversions. A file you upload is a text file: a check that reads it is a check you grade yourself, so nothing you upload moves your score, now or later. Those uploads exist to tell you things the rubric cannot, not to change the number.
- Whether a real crawler is actually blocked
- We fetch your page several times presenting different crawlers' user-agent tokens, from our address rather than the vendor's, and every one of those requests also carries our own token. The vendors publish IP lists precisely so a site can refuse a stranger sending their name — so a site that verifies crawlers properly refuses us, correctly, and that shows up as a block. It is evidence worth having and it is not proof. Details are on /bot.
- What a model already knows about you
- Whether a brand appears in an answer without retrieval is a property of text written before the model was trained, not of the page we fetched this morning. Nothing on your site changes it this month, so nothing in this rubric claims to.
- Whether your content is any good
- Accuracy, originality, expertise, whether the claims are true. Every check here is structural: it asks whether a machine can retrieve, parse, quote and act on the page, never whether it should. A page can score well and be worthless, and the grade should not be read as saying otherwise.
- Ranking, traffic or revenue
- The rubric has never been validated against measured visibility. The weights below are expert priors, and until they clear a held-out half against real outcomes they are exactly that. We would rather publish the arithmetic and let you argue with it than imply an evidence base we do not have.