Structured Data That Earns Trust: JSON-LD Beyond Rich Results
Open a handful of competitor pages in a schema validator and you will almost always find one of three failure modes: no structured data at all, a thin WebPage block dropped in by a plugin and left unmodified for three years, or a Product type with every required property present but every value wrong. Rich results are the visible payoff, but the real function of structured data is to tell machines — Googlebot, Bing, GPTBot, and LLM answer engines — what a page means, who authored it, what entity it represents, and how to connect it to the broader graph of web knowledge. Getting that right requires thinking past the Rich Results Test.
Why JSON-LD Became the Default Format
The structured-data format wars are over. JSON-LD won, and the reasons are practical rather than political.
Microdata embeds schema properties directly into HTML attributes (itemprop, itemscope, itemtype). Every change to the visible HTML potentially breaks the markup, and template engineers have to hold schema semantics in their heads while writing HTML. At scale, this produces drift — a class name gets refactored, the itemprop gets dropped, and no test catches it.
RDFa has similar coupling problems and adds its own namespace complexity. It sees heavy use in Drupal ecosystems but is essentially absent from modern JS-rendered stacks.
JSON-LD is a <script type="application/ld+json"> block that lives outside the content markup. You can update your H1 without touching schema. You can generate schema from your CMS data model in a separate template. You can validate the block in isolation. Google, Bing, and Schema.org tooling all give JSON-LD first-class support. For any site that isn’t locked into a CMS that outputs only microdata, JSON-LD should be the default choice.
The @graph Pattern: Building a Connected Entity
Single-entity blocks are fine for simple pages. The problem is that most pages represent several connected entities — an article has an author, that author belongs to an organization, the page sits in a breadcrumb trail, the site has a global identity. When you drop those as separate disconnected JSON-LD blocks, parsers handle the linking by heuristic. When you use @graph, you make the relationships explicit.
A well-structured @graph for a blog post on a media site looks roughly like this:
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Organization",
"@id": "https://example.com/#organization",
"name": "Example Media",
"url": "https://example.com",
"logo": {
"@type": "ImageObject",
"url": "https://example.com/logo.png"
},
"sameAs": [
"https://twitter.com/examplemedia",
"https://linkedin.com/company/examplemedia"
]
},
{
"@type": "WebSite",
"@id": "https://example.com/#website",
"url": "https://example.com",
"name": "Example Media",
"publisher": { "@id": "https://example.com/#organization" }
},
{
"@type": "Person",
"@id": "https://example.com/authors/jane-doe/#person",
"name": "Jane Doe",
"url": "https://example.com/authors/jane-doe/",
"worksFor": { "@id": "https://example.com/#organization" },
"sameAs": ["https://linkedin.com/in/janedoe"]
},
{
"@type": "Article",
"@id": "https://example.com/blog/post/#article",
"headline": "...",
"author": { "@id": "https://example.com/authors/jane-doe/#person" },
"publisher": { "@id": "https://example.com/#organization" },
"isPartOf": { "@id": "https://example.com/#website" },
"datePublished": "2026-04-08",
"dateModified": "2026-04-08"
},
{
"@type": "BreadcrumbList",
"@id": "https://example.com/blog/post/#breadcrumb",
"itemListElement": [
{ "@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com" },
{ "@type": "ListItem", "position": 2, "name": "Blog", "item": "https://example.com/blog/" },
{ "@type": "ListItem", "position": 3, "name": "Post Title" }
]
}
]
}
The @id references are the key mechanism. The Article’s author property doesn’t repeat Jane Doe’s details — it points to her @id, and the parser follows the reference. This is how knowledge graph connections are built, and it’s why getting @id values right matters: they should be stable, canonical URLs that uniquely identify the entity, not random strings or fragment IDs that change across page versions.
Which Types Actually Earn Rich Results
Not all schema types produce visible SERP features, and confusing “entity graph markup” with “rich result markup” leads to wasted effort. The types that reliably produce rich results as of 2026 are: Product (price, availability, ratings), Recipe (ingredients, time, calories), FAQPage (accordion-style answer expansions, though currently in limited rollout), HowTo (step expansions), Event (date, location, ticket availability), JobPosting, Article/NewsArticle/BlogPosting (Top Stories, article dates), VideoObject (video carousels), LocalBusiness (local panel details), and Review/AggregateRating when attached to an eligible parent type.
Types that are valuable for entity disambiguation but do not themselves produce visible SERP features: Organization, Person, WebSite, BreadcrumbList (breadcrumbs appear but they’re derived from URL structure in most cases), SiteLinksSearchBox, and most Action subtypes. These types still matter — they feed the knowledge graph, power entity recognition, and influence how AI systems identify and describe your site — but you should not measure their success by rich-result appearance.
E-E-A-T Types: Person Credentials and Organization Identity
Google’s quality rater guidelines stress Experience, Expertise, Authoritativeness, and Trustworthiness. Structured data is one of the few signals you control directly that influences these assessments.
Person markup is underused. A Person node with name, url, sameAs links to LinkedIn and professional profiles, hasCredential with a EducationalOccupationalCredential, and knowsAbout properties connecting to topic entities gives parsers a richer signal than a byline with a name and headshot. For YMYL content especially — health, finance, legal — the credential signals matter.
Organization markup with verified sameAs entries (Wikipedia, Wikidata, Crunchbase, relevant industry directories) helps reconcile your site identity across the web. The contactPoint property with contactType values (customer support, editorial, sales) adds operational transparency that trust assessors note.
Author page canonicalization is a common failure. If Jane Doe has an author page at /authors/jane-doe/, that page should have a Person block with the same @id used everywhere else on the site. When the article’s author @id matches the author page’s Person @id, graph consumers can confidently resolve the entity. When they differ, or when the author page has no schema at all, the connection breaks.
How LLMs and AI Answer Engines Use Schema
The landscape changed significantly when LLMs began using structured data not just for rich results but as a disambiguation layer. When GPT-4, Claude, Gemini, and Perplexity encounter your site, they are reading both the visible content and the schema to understand what claims the page is making and who is making them.
A Product block with accurate name, description, brand, and offers gives a shopping assistant the structured signals to surface your product in a comparison. An Article with a credible author node — one that resolves to a real person with verifiable credentials — gives an AI answer engine reason to prefer it as a citation source over an undifferentiated blog post. The llms.txt protocol works at the site level to guide AI crawlers; JSON-LD works at the page level to tell those crawlers what the page means.
AI answer engines are also sensitive to entity disambiguation. If your Organization has sameAs links to Wikidata and your industry association directory, the knowledge graph connection is tighter and the likelihood of accurate citation — rather than hallucinated description — goes up. This is a detail that AI visibility tracking surfaces: you can see whether AI systems are correctly attributing content to your organization or producing confused entity merges.
Validation: Schema.org vs Google’s Rich Results Test
These are two different tools measuring two different things.
The Schema.org validator (validator.schema.org) checks syntactic and structural correctness against the full Schema.org specification. It flags invalid property usage, type mismatches, and malformed JSON. Use it for structural validation.
The Google Rich Results Test checks a narrower question: does this page qualify for rich results in Google Search? It applies Google’s own property requirements, which are stricter and differ from Schema.org’s full spec. A Product type that validates on Schema.org can still fail the Rich Results Test for missing offers or missing aggregateRating when Google considers them required for the feature.
The correct workflow is: validate structure with Schema.org, then verify rich-result eligibility with Google’s tool, then check Bing’s markup validator if Bing traffic matters. The critical thing to check in each case is the distinction between required and recommended properties — treating “recommended” as optional is fine until you wonder why the rich result isn’t appearing.
The Rendering Caveat
Schema injected only after JavaScript executes is at real risk of being missed. Googlebot renders pages, but there is a crawl-then-render pipeline with unpredictable delay. More practically: AI crawlers and bot user-agents that do not execute JavaScript will see only the raw HTML snapshot. If your Product schema is injected by a client-side framework after hydration, that schema is invisible to any bot that doesn’t render.
This connects directly to render parity — the gap between what the raw HTML delivers and what the rendered DOM contains. VisibilityIQ crawls both snapshots and parses JSON-LD from each independently. When a schema block appears in the rendered DOM but is absent from the raw HTML, it flags the finding with severity scaled by schema type: a Product block that requires rendering is a high-severity finding; a BreadcrumbList is lower. The principle is simple: deploy JSON-LD in the server-rendered HTML. If your stack makes that difficult, that’s an architecture problem worth solving, not a rendering behavior worth accepting.
Property-Level Completeness
The most common failure mode in deployed schema isn’t wrong types — it’s correct types with incomplete properties. A Product block with name and description but no offers, sku, or aggregateRating tells a parser less than the product page’s visible text does. A Person block with only name and no sameAs, url, or credential data adds nothing to entity recognition.
Each schema type has a clear hierarchy of required, recommended, and optional properties. For a Product targeting rich results: name is required; image, description, brand, sku, and offers (with price, priceCurrency, availability) are required for rich results; aggregateRating, review, gtin, mpn are recommended and affect feature eligibility. For an Article: headline, image, datePublished, author are required for Top Stories eligibility; dateModified, publisher are strongly recommended.
VisibilityIQ validates required properties per type and reports missing recommended properties as lower-severity findings. The gap report by template is more useful than the gap report by page — when fifty product pages are all missing offers.availability, the fix is one template change, not fifty individual patches.
The measure of a well-deployed structured-data program is not “does the Rich Results Test pass?” — it’s “does every page in this type cluster have the right schema, with accurate values, in the raw HTML, wired to a coherent entity graph?” Getting there is a technical discipline, and it pays off across search, AI answer engines, and the knowledge graph connections that AI visibility work depends on.