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, FAQ accordions, sitelinks) and feeds knowledge-graph entity resolution. Done wrong, it earns manual penalties.

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.

  • WebSite once, on the homepage, with SearchAction if the site has internal search.
  • Organization once, on the homepage or /about, with logo, sameAs, and contact points.
  • BreadcrumbList on every page that lives below the homepage.
  • Article or BlogPosting on every editorial page, with headline, author, datePublished, dateModified, image.
  • FAQPage only when the page is genuinely Q&A. Google revoked FAQ rich results for most sites; ship it anyway for AI agents and future eligibility.
  • Product, Recipe, Event, HowTo, JobPosting when the page is that thing.

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.

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.
  • datePublished matches the published date on the page.
  • Aggregate ratings come from real reviews on the same page, not from an external source.
  • Prices in Product schema 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.