Where to Put JSON-LD in HTML
Should JSON-LD go in the head or body? Learn the best placement practices for structured data, including Google's guidelines and edge cases.
One of the most frequent JSON-LD questions is simple: where exactly should the <script type="application/ld+json"> block go in your HTML document? The answer is more nuanced than you might expect.
Google’s Official Position
Google’s documentation states that JSON-LD scripts can be placed in either the <head> or <body> of your HTML document. Both locations are supported and parsed identically by Google’s crawler.
<!-- Option 1: In the <head> -->
<head>
<script type="application/ld+json">
{ "@context": "https://schema.org", "@type": "Article", ... }
</script>
</head>
<!-- Option 2: In the <body> -->
<body>
<script type="application/ld+json">
{ "@context": "https://schema.org", "@type": "Article", ... }
</script>
<!-- Page content -->
</body>
Best Practice: Place in the <head>
While both locations work, placing JSON-LD in the <head> is the recommended best practice for several reasons:
1. Separation of Concerns
Metadata belongs in the <head>. Open Graph tags, standard meta descriptions, canonical URLs, and favicon links all live in the <head>. Placing JSON-LD alongside them keeps your metadata organized in one location.
2. Early Parsing
Crawlers parse the <head> first. While Google processes both locations, placing JSON-LD early in the document ensures it’s encountered before any potential parsing issues in the body.
3. Framework Compatibility
Most SSR frameworks (Next.js, Nuxt, Astro, SvelteKit) inject head content through dedicated head management APIs. Placing JSON-LD in the head integrates naturally with these systems.
When Body Placement Makes Sense
There are legitimate scenarios for placing JSON-LD in the <body>:
Component-Level Structured Data
In component-based architectures, you might want a product card component to include its own Product schema. Placing the JSON-LD inside the component keeps the data co-located with the UI:
<div class="product-card">
<h2>Premium Headphones</h2>
<p>$149.99</p>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Premium Headphones",
"offers": { "@type": "Offer", "price": "149.99" }
}
</script>
</div>
CMS Injection Points
Some CMS platforms only allow content injection into the body. WordPress plugins, for example, may append JSON-LD at the end of the <body> because they lack access to the <head> template.
Dynamically Injected Content
If your JSON-LD is generated by client-side JavaScript (not recommended, but sometimes necessary), it may only be injectable into the body.
Anti-Patterns to Avoid
1. Placing JSON-LD After the Closing </body> Tag
</body>
<!-- WRONG: Invalid HTML location -->
<script type="application/ld+json">...</script>
</html>
While some parsers may still read this, it’s technically invalid HTML and could be ignored by strict crawlers.
2. Nesting Inside Other Script Tags
<!-- WRONG -->
<script>
<script type="application/ld+json">...</script>
</script>
3. Duplicating the Same Schema
Don’t include the same JSON-LD block in both <head> and <body>. Duplicate schemas can confuse search engines and produce validation warnings.
Multiple Schemas on One Page
You can (and should) include multiple JSON-LD blocks when your page contains different types of structured data:
<head>
<!-- Article schema -->
<script type="application/ld+json">
{ "@context": "https://schema.org", "@type": "Article", ... }
</script>
<!-- Breadcrumb schema -->
<script type="application/ld+json">
{ "@context": "https://schema.org", "@type": "BreadcrumbList", ... }
</script>
</head>
Alternatively, combine them using @graph:
{
"@context": "https://schema.org",
"@graph": [
{ "@type": "Article", ... },
{ "@type": "BreadcrumbList", ... }
]
}
Related Resources
- How to Create JSON-LD — Step-by-step tutorial.
- Application/LD+JSON Explained — Understanding the MIME type.
- Open Graph Protocol: Complete Developer Guide — OG tag placement in the
<head>.