← Back to Structured Data Drift Check

Why Google requires structured data to match visible text

Google's Search Central documentation for the FAQPage and HowTo structured-data types both say the same thing in substance: the markup has to reflect content that is actually on the page and visible to a visitor, not text that exists only inside a <script type="application/ld+json"> block. A page that markets up a question and answer nobody can read is, per that guidance, not eligible for the rich result the markup is meant to earn — and Google's own spam policies treat structured data describing hidden or absent content as a form of misleading markup, not a harmless inaccuracy. This page describes the rule rather than quoting Google's current wording verbatim, because that wording can change without notice; read the current guidance on developers.google.com for the authoritative text.

Why it happens: two authored strings, one source of truth for neither

Nothing about how a page is normally built keeps its visible copy and its JSON-LD in sync. A marketer edits an FAQ answer on the page and never touches the schema. A developer writes the schema once at launch, off the copy as it existed that day, and the copy keeps evolving underneath it. A templating system interpolates the same variable into both places today and a refactor six months later interpolates it into only one. In every case the drift is invisible to a human reader, because nobody reads raw JSON-LD next to rendered copy side by side — which is exactly the comparison this tool automates.

Why this extends past FAQPage and HowTo

Google's written policy names two structured-data types. The underlying reason it exists — markup should describe what is actually on the page — is not specific to either one. An AI system that reads a page's JSON-LD to summarize it, answer a question about it, or decide what to tell a user about a product, business, or review has no equivalent published rule requiring the markup to match what a human visitor sees; it can simply treat the JSON-LD as a structured, pre-parsed statement of fact and repeat it. A Product description, a LocalBusiness address claim in prose, a fabricated-sounding Review body, or an Article headline that no longer matches the page's own <h1> can mislead exactly the same way a stale FAQ answer can — this tool checks all six because the risk is not limited to the two types Google has written a rule about.

What this tool checks, and what it deliberately doesn't

TypeFields checked
FAQPagemainEntity[].name (question), mainEntity[].acceptedAnswer.text (answer)
HowToname, description, step[].name, step[].text
Article / BlogPosting / NewsArticleheadline, description
Productname, description
LocalBusiness / Organization (and common subtypes)name, description
ReviewreviewBody, author.name

Deliberately excluded: numeric and URL fields (ratingValue, priceCurrency, image, url, dates, and so on). Those aren't prose a visitor reads and confirms by eye the way an FAQ answer or a headline is, and a false-positive divergence report on a formatting difference in a number would train a reader to ignore real findings — the same failure mode this portfolio's other checkers avoid by staying narrow.

Wiring it into CI as a gate

Run it against a static build's output directory after every deploy that touches copy or schema:

- name: Check structured data against visible page text
  run: |
    npm run build
    find dist -name '*.html' | xargs node ventures/structured-data-drift-check/cli.mjs check

The command exits non-zero if any claim on any page diverges from that page's own visible text. Add --strict to also fail on a malformed application/ld+json block, which is a different bug this tool notices but does not fail on by default.

Common questions

Where does Google actually say this?

Google's Search Central documentation for both the FAQPage and HowTo structured data types states that the markup must reflect the main content of the page, and that content used only in structured data and not shown to users is not eligible for the rich result. This tool does not quote the live page text verbatim since that text can change without notice; read the current FAQPage and HowTo structured data guidelines on developers.google.com for the exact current wording, and treat this as the sourced, dated pointer to go read it rather than a substitute for doing so.

Why do AI answer engines make this matter beyond FAQPage and HowTo?

A search engine's rich-result eligibility check is one consumer of JSON-LD. An AI system summarizing or answering questions about a page is another, and it has no equivalent published policy requiring the markup to match what a human sees -- it can simply read the JSON-LD as a structured, pre-parsed statement of what the page says and repeat it. A Product, Review, or Organization block that drifted from the page's actual copy is exactly as capable of misleading a reader that way as a FAQPage block is, even though Google's written rule names only two of the six types this tool checks.

How does the two-lockfile-style diff this tool's siblings use apply to a single page?

It doesn't, directly -- this tool checks one page's JSON-LD against that same page's own visible text, not two point-in-time snapshots against each other. The shared idea with this portfolio's other checkers is the same deterministic, no-network, no-verdict shape: read exactly what is already present, compare two specific things character by character, and report precisely where they part ways rather than issuing an opinion.