Guides ยท Structured data
JSON-LD vs Microdata vs RDFa: Which Format Google Reads
A JSON-LD block is small enough to paste and easy enough to get subtly wrong. This guide goes through the four keys that define a block, then the structural choices that decide whether a consumer can read the result.
What JSON-LD is
JSON-LD is a JSON script block that describes the entities on a page using the schema.org vocabulary.
It is a syntax, not a vocabulary: JSON-LD says how to write the data, schema.org says which types and properties exist. Google documents JSON-LD as its recommended format for structured data, and it is the only format that can be added without touching the HTML that renders the page.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Example Ltd",
"url": "https://example.com/"
}
</script>
@context, @type and @graph, field by field
@context names the vocabulary, @type names the entity, @graph holds several entities, and every other key is a property.
| Key | Value | Per block | What it does |
|---|---|---|---|
@context | https://schema.org | 1 | Declares which vocabulary the property names come from |
@type | A schema.org type such as Article | 1 per entity | States what the entity is; properties are interpreted against it |
@graph | An array of objects | 2 or more entities | Describes several entities in one block under one context |
@id | An absolute URL, often with a fragment | 1 per node | Gives an entity a stable identity so other nodes can point at it |
Only @context and @type are needed for a single simple entity. @graph becomes useful when a page genuinely describes more than one thing: an article, the person who wrote it, the publisher, and the breadcrumb trail. @id is what turns those into a graph rather than a pile of unrelated objects.
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Article",
"@id": "https://example.com/guide#article",
"headline": "A title that appears on the page",
"author": { "@id": "https://example.com/#author" },
"publisher": { "@id": "https://example.com/#org" }
},
{
"@type": "Person",
"@id": "https://example.com/#author",
"name": "Martin Cao",
"url": "https://example.com/about"
},
{
"@type": "Organization",
"@id": "https://example.com/#org",
"name": "Pingory",
"url": "https://example.com/"
}
]
}
The article references the author and publisher by @id instead of repeating them. That is the whole benefit of a graph: one definition, several references, and no chance of two copies drifting apart.
Value shapes are the other thing worth learning early. A property accepts a string, a number, an object or an array of those, depending on its definition: headline takes text, author takes a Person or Organization, and multiple authors are an array. A property that expects an object will not accept a plain name string, even though the name is the only part you cared about.
One recurring @context question: several script blocks on a page may each carry their own, because Google processes each block as an independent document. What you cannot do is put two @context keys in one object โ JSON permits only one member with a given name, and the second one is silently lost.
Nesting vs separate blocks
Nest when the child has no independent identity; use a graph node when several parents need to reference it.
A nested object is the simpler choice for a value that belongs to one parent, such as an author on a single article. It keeps the block readable and survives being moved as a unit. A graph node is better when the same entity appears more than once, or when describing it separately makes the block easier to generate: an organization referenced by an article, a logo and a breadcrumb list, for example.
Several script blocks are also valid, and common when different components own different entities. The trade-off is that separate blocks cannot share an @id graph unless the ids are written carefully, and duplicate descriptions of the same entity are easy to introduce. Pick one approach per template and keep it consistent.
Where to put the script
Anywhere in the document works; what matters is that the block is in the server response, not injected after load.
Google reads application/ld+json in the head or the body. The head is conventional because it keeps structured data out of the rendered layout and easy to find in an audit. Placement matters far less than delivery: if a tag manager or client-side effect injects the block after the page loads, any consumer that does not execute JavaScript sees nothing.
That distinction is worth testing directly. View source on the live URL and search for application/ld+json. If the block is there, it ships. If it only exists in the inspector, it does not.
JSON-LD vs microdata vs RDFa
All three express schema.org; JSON-LD separates the data from the markup, which is why it is easier to maintain.
| Format | Lives in | Main advantage | Main cost |
|---|---|---|---|
| JSON-LD | A script block | Independent of the rendered HTML; one block can describe several entities | Can drift from the visible page if generated carelessly |
| Microdata | Attributes on existing tags | The markup sits on the content it describes | Template changes can silently remove it |
| RDFa | Attributes on existing tags | Fine-grained annotation of existing markup | Verbose, and harder to audit at scale |
Mixing formats is allowed but rarely wise. Two descriptions of the same entity in different formats can disagree, and a consumer has no reason to prefer one. Pick a format per entity type and keep the source of truth in one place.
What Google actually consumes
Google reads a subset of schema.org and uses it for specific features; a valid type with no feature attached produces no visible result.
Article markup, for example, has no required properties in Google's current documentation: headline, image, datePublished, dateModified and author are recommended, and they influence how a result can be presented rather than whether it ranks. Breadcrumb markup has a documented structure and can change how a URL is displayed. Product, Event and Recipe markup each have their own requirements, and those requirements are Google's, not schema.org's.
Two consequences follow. First, the same block can be perfectly valid and produce nothing, because Google does not build a feature for that type. Second, a feature can be withdrawn: since August 2023, FAQ rich results are shown only for well-known, authoritative government and health sites, so FAQPage markup elsewhere is read but not displayed as an expandable result.
Breadcrumbs are a useful contrast: the type has a documented shape, it appears in results as the path rather than as a separate block, and it is one of the few places where structured data changes something a searcher sees every day.
How to validate JSON-LD
Check syntax and vocabulary in one tool, then eligibility in Google's, because they answer different questions.
Run the block through the Schema Markup Validator at validator.schema.org for syntax and the full vocabulary, then the live URL through Google's Rich Results Test for feature eligibility โ and keep the third check that neither tool performs: every marked-up value should be visible to a reader. When a message is unclear, the mapping from each one to its cause is in the validation errors guide. It is a separate page because the failure modes are a different problem from the format itself.
What valid JSON-LD cannot prove: that a rich result will appear, that rankings will move, or that an AI product will cite the page. Markup describes what is already there; it does not create demand, authority or a display decision.
Sources checked
- Google Search Central, structured data introduction and Article documentation โ recommended properties, JSON-LD as the recommended format. Checked 2026-10-25.
- schema.org โ type and property definitions for Article, Person and Organization. Checked 2026-10-25.
- Google Search Central blog, 2023-08-08 โ FAQ rich results limited to government and health sites. Checked 2026-10-25.
Frequently asked questions
Four questions cover placement, graph structure, format choice and the effect on rankings.
Does JSON-LD have to be in the head?
No. Google reads the script anywhere in the document, head or body. The head is conventional because it keeps markup out of the visible layout, but the requirement that matters is that the block is present in the server response.
Should I use one graph or several script blocks?
Either works. One block with an @graph array keeps a single @context and lets nodes reference each other by @id. Several blocks are easier to generate from different components, but they cannot share an @id graph as cleanly.
Is JSON-LD better than microdata?
Usually yes, particularly on a template-driven site. JSON-LD lives outside the markup that renders the page, so a template change does not break it and one block can describe several entities. Google documents JSON-LD as its recommended format, and both formats describe the same vocabulary.
Does JSON-LD improve rankings?
Not directly. It makes a page eligible for certain search features and gives other consumers a machine-readable description. Eligibility is not display, and neither is a ranking factor you can isolate and measure.
Check any site free
See whether every JSON-LD block parses, carries @context and declares at least one @type.