ChangeGamer

← All guides · The agent-ready web

Structured Data for AI Agents: Which Schema.org Types Earn Their Keep

Part 8 of The agent-ready web · 1,148 words · published 2026-07-26 · updated 2026-07-26 · Markdown variant

Most schema.org markup is invisible to machine readers. The types that are worth the effort for AI agents, how to emit them without drift, and what to build instead of more markup.

In short

  • Structured data helps machine readers most where it states facts the prose leaves implicit: dates, prices, authorship, identity, licence.
  • A short, correct graph beats a long, aspirational one. Four accurate types are worth more than twenty types with placeholder values.
  • Emit JSON-LD from the same source that renders the page. Hand-written markup drifts from the visible content, and contradiction is worse than absence.
  • Never mark up something that is not visible on the page. It is a policy violation for search rich results and it makes the whole graph untrustworthy to any consumer.
  • If the thing you are marking up is really data — a catalogue, prices, availability — publish a JSON endpoint. Structured data is a description of a page; an API is the data itself.

Part of the The Agent-Ready Website: A Complete Guide to AI Visibility, Access Control and Monetization guide.


Structured data is the oldest machine-readable layer on the web and the one where effort is most often misspent. This page is about the subset that is worth doing for machine consumers, as part of the agent-ready website.

What structured data is actually good at

A model reading your prose can usually work out what a page is about. What it cannot reliably work out is the metadata: when this was last revised, who published it, what the price is, which currency, whether it is free, what it is part of, and what licence applies. Those are exactly the facts a JSON-LD block states unambiguously.

So the useful mental model is not "markup for rich results". It is: a machine-readable fact sheet attached to a human-readable page. Judge every type you consider adding by whether it states a fact the prose leaves implicit.

The types that earn their keep

Type Use for Facts it pins down
Article / TechArticle Any content page headline, description, dateModified, language, keywords, isAccessibleForFree
BreadcrumbList Pages inside a hierarchy where this page sits; extra crawl paths into hubs
Organization Site-wide identity who publishes this, canonical URL, sameAs identities
WebSite + SearchAction Homepage the site as an entity; how to search it
Product + Offer Anything with a price price, currency, availability, SKU, seller, subscription vs one-time
FAQPage Real question/answer sections Q/A pairs as discrete, quotable units
HowTo Genuinely sequential procedures ordered steps with names and text
Dataset Downloadable data distribution URLs, formats, licence
CollectionPage + hasPart Index and hub pages the set of things this page indexes

Two of these are underused and disproportionately valuable to machine buyers:

The types that usually are not worth it

Emit it from one source, or it will lie

The failure mode is always the same: markup written once by hand, content edited later, and now the graph says the price is €19 while the page says €29. A machine consumer that catches a contradiction has no way to resolve it and every reason to distrust the rest.

Derive the graph from the same data that renders the page:

// One source of truth → visible page AND graph
const jsonld = {
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "TechArticle",
      headline: page.title,               // same field the <h1> renders
      description: page.description,      // same field the meta tag renders
      dateModified: page.updated,         // same field the byline renders
      inLanguage: "en",
      isAccessibleForFree: !page.premium,
      keywords: page.tags.join(", "),
      isPartOf: { "@type": "WebSite", name: SITE.name, url: SITE.url },
      publisher: { "@type": "Organization", name: SITE.name, url: SITE.url },
    },
    {
      "@type": "BreadcrumbList",
      itemListElement: trail.map((t, i) => ({
        "@type": "ListItem", position: i + 1, name: t.name, item: t.url,
      })),
    },
  ],
};

Then add a CI assertion that the graph's headline equals the page's <h1> and its dateModified equals the rendered date. Two assertions catch nearly every drift bug this layer produces.

Practical rules

  1. JSON-LD, in <head>. Microdata and RDFa still work but are harder to keep consistent and harder to diff in review.
  2. One @graph per page, not five script tags. Consumers that only read the first block will otherwise miss most of what you said.
  3. Stable @ids for anything referenced twice (offers, organisations), scoped to the page URL.
  4. Absolute URLs everywhere. A relative url in a graph consumed out of context resolves to nothing.
  5. Only mark up what is on the page. This is both a search-engine policy requirement and the difference between a fact sheet and a claim sheet.
  6. Validate on every build, not once at launch. A schema error introduced by a template change is otherwise invisible for months.

Where structured data stops and APIs start

The boundary is worth stating plainly, because a lot of effort goes into forcing data through markup that would be better published directly.

You have Publish as Why
A page about a thing JSON-LD on that page It describes the page a client already fetched
A list of things that changes JSON endpoint An index in markup means fetching HTML to get data
Prices and tiers Both Markup for the crawler on the page, endpoint for the machine buyer
A corpus NDJSON / one-file export Per-page markup cannot express a dataset
A changelog Atom/JSON Feed Feeds exist for "what changed", and pollers already understand them

The API side of this is JSON API design for agents, and the format decision — Markdown for prose, JSON for records, NDJSON for corpora — is worked through in data formats and schema.

Adjacent: provenance markup

Schema.org states facts; it does not prove them. Where authenticity matters — images, documents, anything that could be fabricated — C2PA Content Credentials cryptographically bind assertions about origin and edit history to the asset itself. That is a different guarantee from a JSON-LD author field, and the two are complementary: see C2PA content credentials.

A 45-minute pass on an existing site

  1. Pick your highest-value template. Check whether it emits any graph at all.
  2. Add or fix Article/TechArticle with a real dateModified sourced from your content, not the build clock.
  3. Add BreadcrumbList matching the visible breadcrumb.
  4. Add Organization and WebSite once, site-wide.
  5. On priced pages, add Product + Offer generated from your price data.
  6. Delete every type that describes something you do not have.
  7. Add two CI assertions: graph headline matches <h1>, graph date matches rendered date.

That sequence takes under an hour on most codebases and leaves you with a graph that is small, correct and — because it is generated — still correct next quarter.

Frequently asked questions

Do LLMs read JSON-LD?
When a model or its retrieval pipeline processes raw HTML, the JSON-LD block is part of what it sees, and it is the cleanest statement of facts on the page. Vendors do not publish how much weight it carries, so treat it as a cheap way to make facts unambiguous rather than as a ranking lever.
Which types should I add first?
The ones that describe what your page actually is: `Article`/`TechArticle` for content, `Product`/`Offer` for anything priced, `BreadcrumbList` for hierarchy, `Organization` for identity, and `FAQPage` where you genuinely have questions and answers. Then stop and check they are correct before adding more.
Is FAQPage markup still worth adding?
For rich results, treatment has varied by search engine and changed over time, so do not count on visual gains. As a machine-readable statement of question-answer pairs it is still useful, provided the questions and answers are visible on the page and are real questions rather than keyword shims.
Should structured data duplicate the page content?
It should describe it, not restate it. Titles, dates, identifiers, prices, authorship and relationships belong in the graph; the body does not. Duplicating whole articles into JSON-LD bloats every fetch for no gain.

#structured-data #schema.org #json-ld #ai-visibility #seo

Agents: this guide is available as Markdown and JSON; the whole cluster is indexed at /api/articles.json. The reference corpus behind it is at /llms.txt, with licensing at pricing.