TL;DR: JSON-LD is the format Google recommends and nearly everyone uses today, because it lives in one isolated <script> block instead of being woven through your markup like Microdata or RDFa. Place it once per page (or as sibling blocks for multiple types), validate it with Google's own tools before you ship, and don't expect it to buy you an AI citation by itself — it just makes your facts easier to extract cleanly. And teams doing standards-compliant web development at YuSMP treat JSON-LD the same way: a contract with the crawler, not an afterthought bolted on after launch.
Microdata and RDFa both require you to sprinkle itemscope, itemprop, or property attributes directly onto the HTML elements that already hold your visible content. JSON-LD sidesteps that entirely: it's a self-contained block of JSON, dropped in once, that describes the page without touching a single existing tag. That isolation is the whole reason Google has recommended JSON-LD as the preferred format for years, and it's why this guide spends most of its length on the practitioner details — placement, multiplicity, validation, and the mistakes that slip through — rather than re-explaining what a schema type is.
If you already know roughly what JSON-LD looks like, skip ahead to placement or the validation checklist. If you don't, the next section gets you there in one short comparison and one code block.
All three formats express the same underlying vocabulary — schema.org's types and properties — they just encode it differently. Microdata and RDFa embed that vocabulary as attributes on your visible HTML, which means every template change risks breaking the markup silently. JSON-LD keeps it separate:
| Format | Where it lives | Readability | Current recommendation |
|---|---|---|---|
| Microdata | Attributes on existing HTML elements | Mixed with content, easy to break on refactor | Legacy, still supported |
| RDFa | Attributes on existing HTML elements | Same coupling as Microdata, RDF-based vocabulary | Legacy, still supported |
| JSON-LD | Isolated <script> block | Self-contained, independent of markup changes | Preferred by Google and most tooling |
A minimal, valid example for an organization:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Acme Corp",
"url": "https://example.com",
"logo": "https://example.com/logo.png"
}
</script>Because the block is independent of your template's HTML, a frontend rewrite, a CMS migration, or a redesign doesn't automatically break it — but that independence cuts both ways, which is exactly the mistake covered later: nothing forces the JSON-LD to stay in sync with the content around it. You have to maintain that link yourself.
Google has explicitly said it has no preference between <head> and the end of <body> — both are crawled and parsed identically. What actually decides placement in practice is convention and CMS constraints, not a ranking rule:
<head>, next to other metadata, so anyone editing the page sees all the "data about the page" in one place.<body> because that's where their plugin architecture hooks in, and rewriting that isn't worth the effort.@type's full description in a single block.On the inline-vs-external question, keep it inline. An external JSON-LD file (referenced some other way) adds an extra network request and an extra point of staleness for close to no benefit — the data is small, specific to the page, and belongs with it. Inline <script type="application/ld+json"> is the format every major platform and validator expects.
Yes. A blog post can legitimately carry an Article (or BlogPosting) type, a BreadcrumbList for its navigation path, and a FAQPage for an on-page Q&A section — all on the same URL, because all three statements are true about that one page. You have two correct ways to combine them:
<script type="application/ld+json">
{ "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [ ... ] }
</script>
<script type="application/ld+json">
{ "@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [ ... ] }
</script>...as sibling <script> blocks, or combined under a single @graph:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{ "@type": "BreadcrumbList", "itemListElement": [ ... ] },
{ "@type": "FAQPage", "mainEntity": [ ... ] }
]
}
</script>Both parse identically to Google. The line to watch is when multiple schema types start describing the same claim about the page in contradictory ways — two different Article blocks with different headlines, or a Product and a Service type both claiming to be the primary entity. That's not completeness, it's a sign the page itself is trying to be two things at once.
Structured data fails quietly — a broken block doesn't throw a visible error, it just stops showing up in rich results, or shows up with the wrong fields. Run through this before any deploy that touches JSON-LD:
@type is present (check the type's schema.org page for which properties are required vs. recommended).@id and url values are consistent with the page's actual canonical URL — not a staging domain, not a redirect target.Manual spot-checks catch most of this for a small site. At any scale beyond a handful of templates, script the JSON syntax check and a basic required-property check into your build or CI step — catching a missing datePublished at merge time costs nothing; catching it three weeks later in Search Console costs a re-crawl cycle.
Partially, and it's worth being precise about which part. Structured data makes facts easier for a machine — including the retrieval and parsing pipelines behind AI Overviews, ChatGPT, and Perplexity — to extract cleanly without guessing at ambiguous prose. An Organization block that explicitly states a founding date, or a Product block that states a price, removes the inference step a model would otherwise have to make from running text.
What it is not is a ranking lever or a citation guarantee. Adding JSON-LD to a thin or poorly-written page does not make that page more likely to be cited; the underlying content quality, clarity, and crawlability still dominate whether anything cites you at all. Treat structured data as a clarity aid layered on top of good content, not a substitute for it.
datePublished frozen at the original publish date is fine; dateModified that never updates after a real content revision misrepresents freshness to anyone reading the schema.@type ("Artical" instead of "Article") is syntactically valid JSON but semantically meaningless to any parser — it will simply be ignored.All three express the same schema.org vocabulary. Microdata and RDFa embed it as attributes directly on your existing HTML elements, which couples the schema to your markup. JSON-LD keeps it in one isolated <script> block, independent of the surrounding HTML — which is why it's now the preferred format.
<head> vs. <body> affect how Google reads it?No. Google has stated it has no preference and parses both locations identically. Placement is a convention and tooling decision, not an SEO one.
As many as are genuinely true about the page — a single post commonly carries Article, BreadcrumbList, and FAQPage together, either as sibling script blocks or combined under one @graph. The limit isn't a count; it's whether the types still describe one coherent page.
Paste the live or staging URL into Google's Rich Results Test, then cross-check with schema.org's own Schema Markup Validator for anything the first tool doesn't flag. Both take under a minute per page.
No. It makes your facts easier for machines, including AI retrieval pipelines, to extract cleanly — it does not directly improve rankings or guarantee a citation. Content quality and crawlability remain the dominant factors.
Not for a handful of pages — hand-written blocks are fine. Past a few dozen templates, generating JSON-LD from the same data source that renders the visible content (rather than maintaining it by hand in two places) is what actually prevents drift.
Google can detect the mismatch and may disregard the structured data, or in clear cases of misleading markup, apply a manual action. Treat every JSON-LD claim as something that must stay provably true of the rendered page.