JSON-LD
How to implement JSON-LD structured data in your HTML for AI agents and search engines.
2025-02-15
JSON-LD (JavaScript Object Notation for Linked Data) is the recommended format for adding structured data to your web pages. It embeds Schema.org data in a <script> tag, keeping it separate from your page's visual content.
Why JSON-LD?
- Decoupled from HTML — No need to add attributes to every element. One script block handles all structured data.
- Easy to update — Change the data in one place without touching the layout.
- Preferred by Google and AI systems — JSON-LD is the format recommended by Google and supported by AI retrieval systems.
- Framework-friendly — Easy to generate dynamically in Next.js, Nuxt, Django, etc.
Basic structure
<head>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "My Page Title",
"description": "A description of my page."
}
</script>
</head>
The @context is always "https://schema.org". The @type defines the Schema.org type.
Multiple JSON-LD blocks
You can have multiple <script type="application/ld+json"> blocks on the same page:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Acme Corp",
"url": "https://example.com"
}
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebSite",
"name": "Acme Corp",
"url": "https://example.com"
}
</script>
Or combine them with @graph:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Organization",
"name": "Acme Corp",
"url": "https://example.com"
},
{
"@type": "WebSite",
"name": "Acme Corp",
"url": "https://example.com"
}
]
}
</script>
Implementation in Next.js
In the App Router, add JSON-LD directly in a Server Component:
export default function Page() {
const jsonLd = {
"@context": "https://schema.org",
"@type": "Article",
"headline": "My article title",
"datePublished": "2025-01-15"
};
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
{/* page content */}
</>
);
}
Dynamic generation
For blog posts, products, or other dynamic content, generate JSON-LD from your data:
function articleJsonLd(post: Post) {
return {
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": post.title,
"description": post.description,
"datePublished": post.publishedAt,
"dateModified": post.updatedAt ?? post.publishedAt,
"author": {
"@type": "Person",
"name": post.author
}
};
}
Common types
See the Schema.org guide for the most useful types and their full property sets.
Validation
After adding JSON-LD to your pages:
- Open Google Rich Results Test.
- Enter your URL or paste your HTML.
- Fix any errors or warnings reported.
Always validate after adding or changing JSON-LD — malformed JSON breaks silently and won't be read by agents.