Overview
Structured data tells search engines what a page is, not just what it says. Ship JSON-LD with schema.org vocabulary on every public page. Done right, it earns rich results (article cards, breadcrumbs, product and review annotations, sitelinks) and feeds knowledge-graph entity resolution. Done wrong, it earns manual penalties. Note that not every schema type still maps to a rich result: Google retired FAQ and HowTo rich results (2023 to 2026), so ship those types for page understanding and AI-agent consumption, not for a SERP feature. See schema-markup-deep.
Ship JSON-LD, not Microdata or RDFa
Google, Bing, and Yandex all read JSON-LD, and it is the only format the major engines actively recommend.
- JSON-LD lives in a
<script>tag, separate from the rendered DOM. - Microdata and RDFa interleave attributes with HTML and break under SSR diffing.
- One
<script type="application/ld+json">block per entity. Keep entities atomic; do not chain unrelated types into one blob.
Pick the right schemas for the page type
Most sites need a small fixed set. Add specialized schemas only when the page genuinely matches. For the deeper menu of types (HowTo, Course, VideoObject, DefinedTerm), see schema-markup-deep.
WebSiteonce, on the homepage, withSearchActionif the site has internal search.Organizationonce, on the homepage or/about, with logo, sameAs, and contact points.BreadcrumbListon every page that lives below the homepage.ArticleorBlogPostingon every editorial page, withheadline,author,datePublished,dateModified,image.FAQPageonly when the page is genuinely Q&A. Google fully removed FAQ rich results in May 2026; ship it for page understanding and AI agents, not for a SERP feature.Product,Recipe,Event,JobPostingwhen the page is that thing; these still earn rich results.HowToonly for AI-agent consumption. Google retired HowTo rich results in 2023, so it earns no SERP feature.
Embed JSON-LD in <head> on the server-rendered HTML
Inline the script in the document <head>, rendered server-side so crawlers see it on first byte.
<head>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "Technical SEO",
"author": { "@type": "Person", "name": "Jane Doe" },
"datePublished": "2026-05-14",
"dateModified": "2026-05-14",
"image": "https://example.com/og/seo-technical.png",
"mainEntityOfPage": "https://example.com/seo/technical"
}
</script>
</head>Generate the block from the page’s frontmatter at build time so the structured data and the rendered content cannot drift. Pair it with the og:image from og-images so social and search share the same asset. See add-jsonld-to-static-site for the end-to-end walkthrough on a static site, and schema-org-types for the type-by-type required-field reference.
Fill required fields, then recommended, then stop
Each schema type has a required field set and a recommended field set. Google’s docs list both per type.
- Required fields must be present and non-empty. Missing a required field disqualifies the page from rich results.
- Recommended fields earn the richer treatment. Ship them when the data exists.
- Optional fields are noise unless they enable a specific feature. Do not pad the markup.
Never lie in structured data
The cardinal rule. Markup must match what a human sees on the page.
- Author in markup matches the byline rendered on the page. Honest author markup is also the load-bearing signal for e-e-a-t.
datePublishedmatches the published date on the page.- Aggregate ratings come from real reviews on the same page, not from an external source.
- Prices in
Productschema match the price the buyer pays.
Mismatches trigger manual actions in Search Console, and the recovery cycle is weeks.
Validate before every deploy
Run two validators on every change.
- Google Rich Results Test (
https://search.google.com/test/rich-results). Confirms eligibility for specific rich result types. - schema.org validator (
https://validator.schema.org). Confirms the JSON-LD parses and conforms to the vocabulary.
Wire both into a pre-deploy smoke test on the sitemap’s top 20 URLs. Failures block the deploy. Pair this with the URL hygiene rules in technical so canonical and JSON-LD never disagree on the URL.