Method

How the AI Visibility Score is built.

Every number in a Lantad report comes from arithmetic you can check. This page publishes the formula, the corpus rules, and the cases where the scanner refuses to grade at all. Nothing is estimated from third-party indexes.

Published 16 July 2026 · Updated 7 August 2026 · Lantad engineering

Three things to take from this page.

  • The score is a measurement of one page at one moment, not a prediction of what any assistant will do with it.
  • Prose Parity carries the largest weight because a crawler that cannot read the words cannot use anything else on the page.
  • Two readings, Retrievability and Entity confidence, are reported and deliberately kept out of the 100.

Four weighted parts

One score out of 100, built from four sub-scores. The weights reflect what actually decides whether an assistant can use your page: everything else is downstream of whether the words arrived.

The composite, to scale 100 points
  • Prose Parity 50%
  • Access 25%
  • Structure 15%
  • Schema 10%

Two readings sit outside this bar and never enter the 100: Retrievability, and Entity confidence. Both are diagnostic.

A recalibration moves the scanner and this page together.

The sub-scores

What each part measures

Four questions, asked in the order that matters. A page can pass three and still be invisible if it fails the first.

  • 50% of the score

    Prose Parity

    The share of your rendered, human-visible content that ships in the initial HTML an AI crawler reads, measured as containment of the rendered text. One hundred percent means a crawler sees everything your visitors see.

  • 25% of the score

    Crawler access

    Whether the named AI crawlers can reach the page at all: the robots.txt rule resolved for each of 15 tokens, plus a live probe as their own user agent for the 12 that publish one.

  • 15% of the score

    Structure

    Title, meta description, heading order and extraction-friendly blocks. This is how a retrieval system decides which passage of your page answers a question.

  • 10% of the score

    Structured data

    JSON-LD present in the source rather than injected after render, with the properties the content type actually needs. Scored separately from parity on purpose.

Prose parity

Two fetches, then a diff

Parity is a comparison, not a guess: one raw-HTML crawler fetch and one real browser render, measured against each other. The wider the gap between them, the less of your page an AI can quote.

Access

Every deduction is published

Access opens at a perfect sub-score. Each block an AI crawler runs into subtracts a fixed amount you can look up, so a low access score always points at a specific rule, never a mood.

The run

How a scan executes

Two passes over the same URL, then the difference between them becomes the score and the fix list.

  1. Fetch as a crawler

    LantadBot requests the page with no JavaScript execution, the way GPTBot, ClaudeBot and PerplexityBot do, and identifies itself honestly while doing it.

  2. Render in a browser

    The same URL loads in a real browser, scrolled and settled, so there is a full hydrated version of the page to measure the first pass against.

  3. Diff the two

    Prose Parity, headings, links and structured data are compared. Anything present in one pass and missing from the other is flagged with the words that went missing.

  4. Grade and rank

    The four sub-scores combine into the composite, and findings are raised from a catalogue of 24 named defects, ordered by impact rather than by severity label.

Prose Parity

Prose Parity (50% of the score)

We extract the main content text from the browser-rendered page, split it into overlapping 8-token shingles, hash each shingle, and measure what fraction of those shingles also exist in the initial HTML that a non-JavaScript crawler receives. This is containment, not similarity: the question is one-directional. What a browser user sees either shipped in the HTML or it did not.

Two honesty mechanisms apply. Pages without semantic containers are measured on all visible text, stated in the report. Pages that serve different content on every request are detected by comparing two crawler fetches with each other, and parity is judged relative to that self-similarity, also stated in the report.

The corpus

What gets counted

The same boundary applies on both passes, so a menu that survives while the article does not cannot flatter the score. Containment is measured over the text these elements carry.

Element Treatment Why
h1 to h6 Counted Headings are how an assistant works out what a page is about, so a heading that mounts late costs more than its length suggests.
p Counted Body copy is the substance of any answer built from your page.
ul, ol, li Counted List items are prose. They are also the most commonly lazy-rendered block on a page.
nav Boilerplate, not counted A big menu would otherwise inflate a thin page into a healthy score.
header Boilerplate, not counted Repeated on every page, so it says nothing about this one.
aside Boilerplate, not counted Related links and promos are not the content the page is about.
footer Boilerplate, not counted Same reasoning as nav: identical everywhere, informative nowhere.

Measured as containment of overlapping 8-token runs of the rendered text, so one missing paragraph costs more than one missing label. The measure is one-directional on purpose: the question is how much of what a visitor sees a crawler receives, not how closely the two documents match.

Retrievability

Retrievability

The same containment, but the crawler-side corpus additionally includes string values harvested from inline JSON payloads such as __NEXT_DATA__ hydration data. A page with low parity but high retrievability gets a distinct verdict: the content is technically present but poorly structured for extraction.

Access

Access (25%)

Starts at full marks. Blocking AI search crawlers in robots.txt costs 0.4 of the sub-score, and blocking assistant user agents costs the same again; observed server-level user agent enforcement costs 0.2, scaled by the confidence of the observation; a noai or nosnippet directive costs 0.15. Blocking a model training crawler costs nothing: that is a deliberate owner choice, and the report marks it apart from the blocks that lose you answers. A page whose baseline fetch fails outright is access-fatal: no other measurements matter until crawlers can fetch it.

Structure and Schema

Structure (15%) and Schema (10%)

Structure checks the initial HTML for a title, meta description, a single H1, a canonical, heading coverage roughly every 300 words, and the absence of oversized unbroken text blocks. A seventh check, an llms.txt at the site root, counts for half the weight of the others. Schema checks that JSON-LD parses, declares types, and carries the required properties for those types. Structured data that only appears after JavaScript runs is capped at a quarter of the schema score, because AI crawlers never see it.

Grades

Grades

A at 90+, B at 75+, C at 60+, D at 40+, F at 0+. A perfect parity, access, and structure page with no structured data scores exactly 90: readable is not the same as complete.

Entity confidence, the second diagnostic

Every graded report carries a second reading that is not part of the 100. Entity confidence parses the JSON-LD in the HTML a no-JavaScript crawler receives, the same fetch Prose Parity and Schema use, and checks five properties of the identity that markup declares. It measures your markup and nothing else. Nobody outside an AI system can observe what that system does with a given property, so no weight here is a prediction about one, and no sentence in the report says a signal earns you anything.

There is no letter grade. Instead there are three tiers, computed from the signals rather than from the score: Not declared, no identity node in the HTML a crawler receives; Declared, an identity node is present and complete but nothing points at it from outside the page; Anchored, it is present and carries at least one identifier that resolves outside the page. The tier comes from the signals because 50 points is reachable both with an outside identifier and without one, so the number on its own cannot name the state.

  • Identity declared35 The gate. Nothing else in the list can be true without an identity node for it to be true of, so it takes the largest single weight and stays under half, so that "a node exists" is never most of the score. 20 of the 24 pages carry an Organization-family node; 4 ship JSON-LD with no identity node at all. It counts only when a type, a name and an absolute url are all present.
  • External identifiers (sameAs)25 16 of 24, on the identity node itself. The largest non-gate weight because it is the only property here whose own definition is an identity statement: schema.org defines sameAs as a reference page that "unambiguously indicates the item's identity".
  • Stable identifier (@id)15 11 of 24 on the identity node, the closest to half the sample of anything we measured and therefore the single best discriminator in it. An absolute @id is what makes several nodes one linked graph rather than separate islands.
  • Logo declared15 19 of 24 on the identity node, the most common non-gate property, and the only property in this set for which any platform owner documents a consumer: Google's Organization structured-data documentation, updated 15 April 2026, lists logo among its 23 recommended properties and says the markup can influence which logo is shown in Search results and the knowledge panel. Equal to the stable identifier rather than above it, because ranking a commoner-but-documented property against a rarer-but-structural one would mean inventing a basis we do not have.
  • Category declared10 9 of 24 once every machine-readable form is counted: a specific Organization subtype, an additionalType URL, an industry code, knowsAbout, or a SoftwareApplication, Product or Service node. The rarest signal we kept, so the smallest weight. A description no longer counts, because prose is the thing structured data exists to replace.

Five signals, 100 points.

The sample the weights come from

On 26 July 2026 we fetched 30 pages, one per site, as raw HTML with no JavaScript executed. They were chosen by hand as widely referenced technical sources, publishers and well-known products, not sampled at random. 24 returned at least one application/ld+json block, and those 24 are the denominator for every count above. 6 returned no JSON-LD at all, among them developer.mozilla.org and theguardian.com, which is worth saying plainly: whatever makes those pages worth quoting is not structured data on the page. A further 9 sites refused the fetch with a 403, 404, 429 or a TLS reset, and those were excluded rather than counted as absent, because a refused fetch is evidence about the refusal and nothing else. Alongside that sample we re-measured Lantad's 12 stored golden captures; only 3 of the 6 real ones carry any JSON-LD, which is why the fixtures settle almost nothing on their own.

That is a hand-picked sample of 30 pages, not a survey. It is enough to rank one property against another, and it is not enough to support a sentence that starts "most sites". You will not find one on this site.

What changed on 26 July 2026, and why

The signal set was replaced. Scores before and after are not comparable, and every stored report renders the set it was actually measured with rather than being restyled to look current.

  • Named founder, 20 points: removed. Declared by 5 of the 24 pages, against a logo on 19, a sameAs on 16 and an absolute @id on 11. It does not appear anywhere in Google's Organization structured-data documentation, last updated 15 April 2026, which we read in full, and no platform owner documents anything that consumes it. Worse, the old check accepted any standalone Person node carrying a name, so an article byline in a Yoast-style graph scored as a founder: css-tricks.com reached 100 out of 100 on the strength of its post author.
  • Clear name, 10 points: merged into Identity declared. Across all 12 stored captures, name and identity had identical presence: name never once fired on a page where identity did not. It was a rider on identity rather than a second signal. Identity now requires a type, a name and an absolute url together, so a bare typed node no longer earns points.
  • Category declared: 20 points to 10, and a description no longer counts. Counting any non-empty description made a property that 9 of 24 pages declare in a machine-readable form look like a common one, and printed "your markup states what you are" over a marketing sentence.
  • Verified profiles (sameAs): kept at 25 points, renamed External identifiers. Nothing is fetched and no ownership is checked, so calling the targets verified was a word the measurement had not earned. It is now read from the identity node only, and a repeated URL is counted once.
  • Added: Stable identifier (@id), 15, and Logo declared, 15. Both were more common in the sample than several things already being scored, and neither was being checked at all.
  • The letter grade is gone. Bands calibrated for a continuous composite were being applied to a five-item checklist, which put two grades on different scales on one page: our stored capture of astro.build renders 88.8 out of 100, grade B, for the composite beside 0 out of 100, grade F, for entity confidence. Both numbers are right and the pair reads as a contradiction, so the entity grade is now a tier printed with its definition.
llms.txt

On llms.txt

Informational only. Independent 2026 data (Ahrefs, SE Ranking, Google documentation) shows no measurable citation effect from llms.txt. It is checked because it costs nothing and some assistants read it, but it moves neither crawling nor ranking.

Structure sub-checks, to scale
  • Title 1
  • Meta description 1
  • Single H1 1
  • Canonical 1
  • Heading coverage 1
  • No oversized block 1
  • llms.txt 0.5
llms.txt is the only half-weight check: 0.5 of the 6.5 weight units in Structure, and Structure is 15% of the composite. Serving one can move at most 1.2 points of 100.
Calibration

Calibration

The scorer is calibrated against a hand-labelled panel of public sites spanning exemplary server-rendered pages through pure client-side applications. The current build holds a Spearman rank correlation of at least 0.9 against panel labels with zero inversions between server-rendered controls and client-side offenders. Calibration runs are logged in the project record, and every degraded measurement path states in the report what was measured, what was not, and why. The scanner never emits a confident wrong grade: pages it cannot measure honestly get no grade at all.

Visibility Score

The Prompt Tracker Visibility Score

The Prompt Tracker asks a fixed bank of realistic buyer questions on a schedule, across answer engines and countries, and scores whether the brand is in the answer. The score is VS = 100 x (0.45 x MR + 0.25 x CR + 0.2 x PF + 0.1 x SF), weights read from the same config the run engine scores with, so this page and the tracker cannot disagree. MR is the mention rate: the share of runs whose answer names the brand AND means it, over a rolling 7-day window. Those are two separate tests and both must pass. A brand name is not a string: Lantad is also a Tagalog adjective meaning exposed or in full view, and two unrelated companies sit within an edit of the spelling, so an answer can carry the letters while being about a dictionary entry, a different firm, or an engine saying it has never heard of the brand. None of those is visibility, and none of them counts. A run whose identity nothing established, because the extraction judge did not answer, is left out of both halves of every rate rather than counted as a miss: an outage must not print as a zero any more than a homonym may print as a mention. CR is the citation rate: the share of runs whose answer cites the brand's own domain as a source, same window. PF is the position factor: the mean of 1/position across mentioned runs, and 0 when nothing was mentioned; a mentioned answer with no ranked list contributes 0 while staying in the denominator, so one lucky list placement never outweighs ten unranked mentions. SF is the sentiment factor, and it is FIXED at 0.5: a neutral midpoint, not a measurement, held there until a measured perception layer ships. A window with no runs has no score at all; an unmeasured rate is never rendered as a zero one.

The tracker also flags gap prompts: a prompt with relevance of 7 or more (0 to 10, set at prompt creation) whose mention rate stays under 5% across 28 days of measured runs. A prompt with no runs in that window is not a gap; nothing was measured. Detected gaps are ranked by opportunity = 0.4 x relevance + 0.3 x demand + 0.3 x winnability, each input scored 0 to 10: relevance is how directly a mention converts, demand is a keyword-volume proxy, and winnability is computed from what got cited instead, because a citation held by directories and forums can be earned while one held only by high-authority editorial cannot be submitted to.

How to read your report

A report is one page, top to bottom, and every number on it traces to the sections above. In order:

  1. The dial and the headline. The letter grade and the composite out of 100, next to a one-sentence verdict. Beneath them sit the five sub-scores: Prose Parity, Access, Structure, and Schema, which make up the composite at the weights above, plus Retrievability, which is diagnostic and not part of the composite.
  2. What to know about this measurement. Appears only when something changed how we measured: a fallback taken, a page that varies per request, a truncated capture. If this section is absent, nothing needed explaining.
  3. Browser view vs AI crawler view. A screenshot of the rendered page next to the main text actually extractable from the initial HTML, with the token counts of both sides. This is the parity evidence in raw form. Screenshots are kept for 24 hours; the measurements come from the extracted text, not the image, so an expired screenshot changes nothing.
  4. The bot access matrix. One row for each of the 15 crawlers in the registry: its purpose, the deciding robots.txt rule quoted verbatim, and what your server returned when asked for the page with that crawler's published user agent. Blocked training crawlers are marked as your choice, not a fault.
  5. What is holding you back, worst first. Every defect found, ranked critical, major, minor, each with the evidence measured on your page and a concrete fix. These are the same findings the deductions above priced into the score.
  6. Entity confidence. The second diagnostic, described above: five properties of the identity your JSON-LD declares in the crawler-view HTML, a score out of 100, a tier printed with its definition instead of a letter grade, and a JSON-LD block generated from the properties this page is missing. It never enters the composite.
  7. llms.txt, keywords, and monitoring. The honest llms.txt position stated above, a preview of the questions your page could ground, and the option to have the page re-scanned weekly so a drop is noticed rather than discovered.

What this scan cannot tell you

The limits of the method, stated as plainly as the method itself.

  • User agent probes are not the real bot. The probe sends each crawler's published user agent string from our own infrastructure. Servers that verify crawler IPs will block a spoofed user agent from any scanner; the real crawler may pass. That is why enforcement findings carry a confidence level and low-confidence observations count for half the penalty.
  • AI Overviews are one location's public result. In prompt tracking, the Google AI Overviews engine captures the public google.com result for a query in one fixed location and language through a SERP vendor. It is not a signed-in user's personalized result, and results in other countries can differ. A query where Google rendered no AI Overview is reported as exactly that, a measured state, and never counts against your visibility.
  • Some tokens cannot be probed at all. anthropic-ai, Google-Extended, Applebot-Extended are robots-only tokens with no published request user agent, so for those the matrix reports the robots.txt evaluation and marks the server column not tested.
  • Rendering has edges. The browser render scrolls 3 viewports and waits for late hydration, but a feed that keeps loading forever is undercounted below the last scrolled viewport. Text kept inside shadow DOM may also be undercounted in production scans. Cookie overlays are dismissed with decline-style controls first; cross-origin iframe content is excluded from both views by design.
  • Very large pages are truncated. Raw HTML is captured up to 3MB; past that the scan grades the captured portion and flags the truncation, because real crawlers have capture limits too.
  • Some pages get no grade at all. A bot-defense challenge served to our crawler, a login or paywall, a failed render, or fewer than 30 readable tokens on both sides each end in a stated partial verdict instead of a letter grade, with whatever was still honestly measurable, such as robots.txt findings, reported anyway.
  • A scan is one URL at one moment. It measures the page you gave it, not your whole site, and a repeat scan of the same URL inside 24 hours returns the same report. For whole-site coverage and change over time there are the multi-page scan, the bulk audit on the API, and weekly monitoring.
Refusals

When we withhold a grade

A number we cannot back is worse than no number. These are the cases where the report says so instead of producing one.

  • The page did not load

    A timeout, a 5xx, or a challenge page returned to the crawler fetch. There is nothing to measure, and grading an error page would produce a confident wrong answer.

  • The two passes disagree structurally

    If the rendered page and the raw page are different documents rather than the same document with parts missing, a parity percentage would be meaningless.

  • A check could not run

    Individual sub-scores can be marked not measured with the reason, and the composite says which parts contributed rather than silently reweighting.

  • The sample is too small

    On aggregate research, a figure publishes only once enough sites in that stratum have been measured. Until then the row reads not enough yet, with the real count.

The composite is published, not implied. Score equals 50% Prose Parity plus 25% crawler access plus 15% structure plus 10% structured data. Those four weights are read from the same configuration the scoring code reads, so this page cannot drift away from the scanner.

Anything the scan could not measure is reported as not measured, with the reason, rather than folded into the grade as a guess.

Common questions

Why did my score move a point or two between scans?

Render timing, retries, and settle windows can move a score a point or two between identical checks of an unchanged page. That noise floor is why monitoring alerts default to a 6-point drop: above the variance, below the cost of the smallest real defect in the catalog.

Why does my report have no letter grade?

The scanner never emits a confident wrong grade. When the browser render fails, the site answers our crawler with a bot-defense challenge, the page sits behind a login, or both views yield almost no text, the report states what was measured and withholds the grade rather than guessing. What could still be measured honestly, such as robots.txt findings, is reported anyway.

Is Retrievability part of the composite score?

No. The composite weighs Prose Parity 50%, Access 25%, Structure 15%, and Schema 10%. Retrievability is diagnostic: next to a low parity it separates content that is genuinely absent from content shipped as hydration JSON, which changes which fix applies.

Is Entity confidence part of the composite score?

No. It is the second diagnostic alongside Retrievability and never enters the 100. It reads five properties of the identity your JSON-LD declares in the HTML a no-JavaScript crawler receives, and it carries no letter grade: three tiers, each printed with its definition, replace the bands. Reports scanned before 26 July 2026 used a different five-signal set and say so, because their scores are on a different scale.

Do you ask ChatGPT or Claude what they see on my page?

No engine is queried to compute the score: it comes entirely from this scan's own fetches and render. Where Lantad does run model calls, in the separate prompt tracking and brand checks, coverage comes from the 8-engine registry: the open-weight Workers AI chain, Gemini with Google Search grounding, the metered vendor APIs on paid plans, and Google AI Overviews captured from the public google.com result through a SERP vendor. Every engine answers through its official API or a disclosed capture, never by automating a consumer app, and the result pages name what answered and how.

How do you measure Google AI Overviews?

Through SERP capture on a vendor (DataForSEO): the tracked question is submitted as a google.com query for one fixed location and language, and whatever AI Overview Google renders on that public result is recorded, with its source links. What this measures is the public result for that query in that location, not a signed-in user's personalized result. When Google renders no AI Overview for a query, the report says exactly that, as a measured state, and it counts toward nothing: a surface that did not appear is not an answer that omitted you.

Why is Prose Parity worth half the score?

Because everything else is downstream of it. Perfect structured data on a page whose text never reaches the crawler describes a document the assistant cannot read. The weights are ordered by what actually decides whether you can be quoted.

Why measure containment of the text rather than count blocks?

Because blocks are not equal. A missing paragraph of product detail and a missing one-word label are the same defect counted by block, and obviously different measured over the text itself. Containment of overlapping runs of the rendered words weights a loss by how much text it takes with it.

Does a high score guarantee citations?

No, and nothing on this site claims it does. The score measures whether an assistant can read your page. What it does with a readable page is its decision. Anyone promising placements is selling something they do not control.

Why do only 12 of the 15 crawlers get probed?

3 tokens exist only inside robots.txt: anthropic-ai, Google-Extended, Applebot-Extended. They are switches a vendor reads, not bots that send a request of their own, so there is no user agent to test and the report says so rather than implying a probe that never ran.

Are the per-bot probes honest?

The baseline fetch always identifies itself as LantadBot. The per-bot probes send each bot's published user agent string once, to detect blocking, and the results are caveated because servers that verify crawler IPs behave differently for the real crawler.

Can I check the arithmetic myself?

Yes, and that is the point. Every report shows its own two corpora and the words that separate them, so any figure on it can be verified line by line rather than taken on trust.

See the method applied

Or see the method run at scale, across every graded page, in the live AI Visibility Index. How our own crawler behaves, and how to opt out, is on the bot page.

Read the method, then check your page.

The formula is only useful once you have a number to put through it. The scan is free, needs no signup, and shows its working.