JSON-LD

JSON-LD is the script-based structured data format Google recommends — easiest to implement, never touches visible HTML, and typically pairs with schema.org for SEO.

First published: Jun 26, 2026 · Last updated: Jul 18, 2026 · Advanced
demand #2 in Structured Data#7 in On-Page#41 in Technical SEO#54 on the site
1 evidence signal on this page

JSON-LD (JavaScript Object Notation for Linked Data) is a structured data format that lives in a <script type="application/ld+json"> tag; on the SEO side it's typically paired with the schema.org vocabulary to describe page content, though JSON-LD itself can carry other vocabularies too. It's a W3C standard (2014), and Google recommends it over Microdata and RDFa for one reason: it's the easiest format to implement and maintain at scale, because it sits in its own block and never touches your visible HTML. All three formats work equally well when implemented correctly. The syntax spine is @context (the vocabulary — schema.org for most SEO markup, but not the only valid value), @type (the entity), and @id (a useful but optional stable URI for linking entities — the basis of the @graph pattern, itself one valid way to organize multiple entities, not a requirement). The catch most guides miss: Googlebot renders JavaScript so dynamically injected JSON-LD works for Google, but several AI crawlers — GPTBot and ClaudeBot included, as tested — don't execute JavaScript; that's provider- and date-specific, not a universal rule, so verify directly if a particular crawler matters to you and server-render markup you can't confirm otherwise. Structured data is not a ranking signal; it governs rich-result eligibility and entity understanding, and it must describe content actually visible on the page.

TL;DR — JSON-LD (JavaScript Object Notation for Linked Data) is a W3C Recommendation from 2014 — built on JSON, but @context is what makes it linked data, not just JSON. It’s the structured data format Google recommends because it’s the easiest to implement and maintain at scale and never touches visible HTML; Microdata and RDFa are equally valid when correct. The syntax spine is @context (vocabulary — schema.org for most SEO markup, though the spec allows other contexts), @type (entity), @id (a useful but optional stable URI for cross-referencing entities — the basis of @graph, itself one valid pattern among others, not a requirement). Place it in <head> or <body> — Google accepts either. Googlebot renders JS so dynamically injected JSON-LD works for Google; several AI crawlers (GPTBot, ClaudeBot included, as tested) don’t execute JS, but that’s provider- and date-specific — verify directly rather than assuming it for every AI crawler, and server-render what you can’t confirm. Structured data is not a ranking signal — it drives rich-result eligibility and entity understanding, and it must describe content visible on the page.

JSON-LD is a format, not a vocabulary

First, a distinction that clears up a lot of confusion: JSON-LD is the format; schema.org is the vocabulary. JSON-LD is how you write the markup; schema.org’s Article, Product, Organization types are what you say. Rich results are the feature layer on top of both. This page is about the format. (The vocabulary-for-AI angle lives in Schema Markup for AI.)

JSON-LD is a W3C Recommendation, first published in 2014 — it predates its SEO adoption and was designed for general linked-data interoperability across the web, not specifically for search. That history is why a property like @id exists at all, and it’s the spec-level point most SEO guides skip: JSON-LD is not just JSON. It’s built on JSON syntax, but the @context declaration is what makes the data linked — identifiable and connectable across the web. Strip @context and you’ve got data a parser can’t interpret.

JSON-LD also isn’t married to schema.org. The spec lets @context reference any published vocabulary — its own examples link to non-schema.org contexts — so JSON-LD is the right answer to “what format” while schema.org is one answer, the common one for search and AI-search markup, to “what vocabulary.” A page could validly use JSON-LD with a different vocabulary; it just wouldn’t be schema.org markup anymore.

JSON-LD vs. Microdata vs. RDFa

There are three ways to express structured data, and Google supports all of them:

JSON-LDMicrodataRDFa
Where it livesA separate <script> blockInline itemprop attributes on your HTMLInline property attributes on your HTML
Touches visible HTML?NoYesYes
Can be injected by JS / tag manager?Yes (cleanly)AwkwardAwkward
Google’s stanceRecommendedSupportedSupported
Error-pronenessLowestHigher (tangled with markup)Higher (tangled with markup)

Google’s recommendation is explicit but narrowly scoped: “In general, Google recommends using JSON-LD for structured data if your site’s setup allows it, as it’s the easiest solution for website owners to implement and maintain at scale (in other words, less prone to user errors).”

The nuance competitors usually drop — and the one worth keeping — comes from the same Google page: “All 3 formats are equally fine for Google, as long as the markup is valid and properly implemented per the feature’s documentation.” So the recommendation is about implementation ease and error rate, not parsing speed or ranking advantage. Using Microdata is not a penalty. JSON-LD just wins in practice because it doesn’t entangle structured data with the markup a designer might edit tomorrow.

The syntax: @context, @type, @id, properties, nesting

Here’s an annotated Article block:

<script type="application/ld+json">
{
  "@context": "https://schema.org",          // the vocabulary — the common value for SEO
  "@type": "Article",                          // the entity type
  "@id": "https://example.com/post#article",   // a stable URI for this entity
  "headline": "How JSON-LD Works",            // a property (key/value)
  "datePublished": "2026-06-26",
  "author": {                                  // a nested entity
    "@type": "Person",
    "name": "Patrick Stox",
    "url": "https://patrickstox.com/"
  }
}
</script>
  • @context — establishes the semantic framework (the vocabulary). For schema.org SEO markup it’s typically "https://schema.org", but that’s a convention, not a rule: @context maps terms to identifiers, and the spec lets it point to other vocabularies. It tells the parser how to interpret every property name that follows. This is the part that makes it linked data.
  • @type — declares the entity: Article, Product, Organization, BreadcrumbList, etc. It maps to a schema.org type. Use the most specific applicable typeNewsArticle over Article if it fits.
  • @id — a unique URI identifying the resource. It’s the mechanism that lets you reference one entity from another (see @graph below), and it’s worth setting on anything you’ll cross-reference — but it’s not universally required. The JSON-LD spec permits unidentified blank nodes, so valid JSON-LD can omit @id on entities you never need to reference elsewhere.
  • Properties — ordinary JSON key/value pairs, using vocabulary terms from the @context.
  • Nesting — child entities are expressed as nested JSON objects (the author object above) or arrays of objects.

The @graph pattern (the scalable approach)

Most pages need more than one entity: an Organization, a WebSite, a BreadcrumbList, and the Article or WebPage itself. The naive approach is four separate <script> blocks that repeat data. A scalable alternative is a single block with @graph — an array of entities, cross-referenced by @id. Neither the JSON-LD spec nor Google mandates @graph as the pattern — it’s syntax for expressing a graph, and other valid layouts exist (separate typed blocks, nested objects without a top-level @graph, blank nodes with no @id at all) — but on a site with several cross-referenced entities, it’s the pattern that avoids repeating the same Organization or WebSite data on every page:

Declare each entity once and connect the graph with stable `@id` references instead of repeating full objects. Source: Nested Schema

One Organization is referenced as publisher by the WebSite and Article. The WebPage belongs to the WebSite and is connected to the Article. Each entity is declared once, and the same stable ID string is reused for every reference.

© Patrick Stox LLC · CC BY 4.0 ·

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "Organization",
      "@id": "https://example.com/#org",
      "name": "Example Co",
      "url": "https://example.com/"
    },
    {
      "@type": "WebSite",
      "@id": "https://example.com/#website",
      "url": "https://example.com/",
      "publisher": { "@id": "https://example.com/#org" }   // reference, not a copy
    },
    {
      "@type": "WebPage",
      "@id": "https://example.com/post#webpage",
      "isPartOf": { "@id": "https://example.com/#website" },
      "breadcrumb": { "@id": "https://example.com/post#breadcrumb" }
    }
  ]
}
</script>

Define Organization once, then point at it with { "@id": "...#org" } everywhere else instead of repeating the name, logo, and URL. This is how the major CMS schema plugins build their output, and it’s why @id exists. Bing makes the same case for JSON-LD’s nesting: it “makes defining links and relationships between data and entities… easy because it supports nested data.”

Where to place it: <head> or <body>

Google confirms both work“You can put the JSON-LD data in the <head> or the <body> of the page.” <head> is conventional, but plenty of CMS plugins inject it near the end of <body>, and that’s fine. Bing agrees it can sit “in the header, body or foot of the page.” Don’t burn time relocating a valid block from body to head; it changes nothing. Evidence for this claim Google permits JSON-LD in either the head or body of an HTML document for supported structured-data features. Scope: Google Search JSON-LD guidance; markup must still match visible page content. Confidence: high · Verified: Google: Structured data introduction

Generating JSON-LD dynamically — and the AI crawler catch

You can build JSON-LD on the fly with JavaScript, and Google documents two ways to do it:

Evidence for this claim Dynamically generated structured data is acceptable to Google when it is rendered and complies with content and quality guidelines. Scope: Google Search JavaScript and structured-data guidance; crawlability and rendering remain prerequisites. Confidence: high · Verified: Google: Generate structured data with JavaScript
  1. Google Tag Manager — a Custom HTML tag containing the JSON-LD, pulling values from GTM variables. (Avoid duplicating data between the page and the tag.)
  2. Custom JavaScript — create the script element programmatically:
    const script = document.createElement('script');
    script.setAttribute('type', 'application/ld+json');
    script.textContent = structuredDataText;
    document.head.appendChild(script);

This works for Googlebot, because Google renders the page: “Google Search can understand and process structured data that’s available in the DOM when it renders the page.” So far, so good.

Here’s the catch most guides miss, stated carefully. Several AI crawlers — including GPTBot and ClaudeBot, as commonly tested — have not executed JavaScript. If your JSON-LD only exists after a client-side script runs, a JS-skipping crawler never sees it — it’s invisible to that bot even though Googlebot reads it fine, because Google documents rendering the DOM before it looks for structured data.

Two honest caveats on that AI-crawler behavior: it’s Google’s own documentation that establishes the Googlebot side; the AI-crawler side comes from testing and reporting on individual providers, not a spec any of them publish, so it’s provider- and date-specific — a crawler’s JavaScript support can change, and I haven’t verified every provider directly. Don’t treat “AI crawlers skip JS” as a universal rule to build on; treat it as a reason to check the crawler you actually care about (or default to server rendering when you can’t check). If it isn’t in the server-rendered HTML and you haven’t confirmed the crawler executes JS, assume it can’t see it. For AI-search visibility, render JSON-LD server-side into the static HTML unless you’ve verified otherwise. (This is the JavaScript-rendering problem from a structured-data angle — see JavaScript SEO.)

There’s a second caveat for ecommerce: Google warns that dynamically generated Product markup “can make Shopping crawls less frequent and less reliable,” which is a real problem for fast-changing price and availability. For products, prefer server-side rendering regardless of AI.

The policies (these have teeth now)

Google’s structured data guidelines are short and load-bearing:

  • “Don’t mark up content that is not visible to readers of the page.”
  • “Don’t mark up irrelevant or misleading content, such as fake reviews.”
  • “Put the structured data on the page that it describes.”
  • “Use the most specific applicable type and property names defined by schema.org.”
  • Don’t block your structured-data pages from Googlebot via robots.txt or noindex.

The visible-content rule is the one to internalize. Schema that describes content not shown on the page has always been a violation; enforcement of “invisible” schema has tightened. Bing puts the warning bluntly: “even though the markup is not visible on your page, it is still read by the search engines, and putting spam data in the markup can hamper your presence.”

Common JSON-LD mistakes

  • Markup that doesn’t match the visible page — the #1 policy problem (a rating in the JSON-LD that no visitor sees).
  • Malformed JSON — a trailing comma, an unescaped quote, or Word smart quotes (" instead of ") that silently break the whole block. JSON-LD is strict.
  • Wrong property names — inventing properties that aren’t in schema.org, or misspelling real ones, so the parser ignores them.
  • A generic type where a specific one existsThing or Article where Recipe or NewsArticle was warranted.
  • Duplicate, inconsistent Organization blocks across pages with conflicting names/logos.
  • Missing required properties for the rich result you’re targeting (each feature lists its own required fields).
  • JS-injected markup assumed to be visible to every crawler — Google renders it, but some AI crawlers have not, and that’s worth verifying per crawler (the catch above).

Validating JSON-LD

Four different questions get asked under “is my JSON-LD valid,” and they’re not the same question — passing one doesn’t pass the others:

TestProvesDoes not prove
JSON parses (any JSON linter, or the Rich Results Test’s parse step)The syntax is legal JSON — no trailing commas, unescaped quotes, or smart-quote breakageThat any property name is real schema.org vocabulary, or that Google will show anything
Schema.org ValidatorThe properties and types exist in the schema.org vocabularyThat Google supports the type as a rich result, or that required fields for a specific feature are present
Rich Results TestThe markup meets Google’s requirements for a specific supported rich-result type, on the rendered page you testedThat Google will actually display the rich result — eligibility isn’t a guarantee — or that other search/AI systems parse it the same way
Google Search Console — Enhancements / rich result reportsWhat Google actually parsed on live, crawled pages, at scale, with real errorsReal-time state — reports lag behind a recrawl
  • Test by URL, not pasted code, for JS-rendered pages. The Rich Results Test’s code-input mode doesn’t run your scripts or resolve relative references the way live-URL testing does — it can’t tell you what a client-side-injected block looks like after rendering.
  • Bing Webmaster Tools — Markup Validator — Bing has validated JSON-LD since August 2018.
  • None of these tests speak for crawlers that don’t render JavaScript (see the AI-crawler caveat above) — testing the rendered URL confirms what Google sees, not what a JS-skipping bot receives.

Does JSON-LD help SEO?

Set expectations honestly:

  • Not a ranking signal. John Mueller has said structured data won’t make a site rank better. Full stop.
  • Rich-result eligibility. It’s what makes you eligible for enhanced SERP features (stars, prices, FAQs, breadcrumbs) — eligibility, not a guarantee.
  • CTR, indirectly. Richer-looking results can earn more clicks, which is the real payoff for most sites.
  • Entity understanding. It helps engines connect your page to known entities and the Knowledge Graph.
  • AI search. Fabrice Canel (Bing) confirmed in 2025 that schema markup helps Microsoft’s LLMs understand content — but note the controlled-study caveat from Schema Markup for AI: it’s infrastructure for disambiguation, not a direct citation lever.

So: implement JSON-LD for rich-result eligibility, entity clarity, and AI/LLM comprehension — not as a ranking hack.

This article sits in the structured data hub. For the AI-specific take on the schema.org vocabulary, see Schema Markup for AI; for the rendering mechanics behind dynamic injection, see JavaScript SEO.

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin an expert quote first.