We covered schema at a strategic level in on-page. Here's the technical implementation: where to put it, how to generate it dynamically, how to validate, how to avoid penalties.
JSON-LD goes in the <head> in a <script type="application/ld+json"> tag. Can also go in <body>, but head is convention.
You can have multiple JSON-LD blocks on one page OR nest multiple types inside one block via @graph:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "WebSite",
"@id": "https://example.com/#website",
"url": "https://example.com/",
"name": "Example Site"
},
{
"@type": "Article",
"headline": "...",
"isPartOf": { "@id": "https://example.com/#website" }
}
]
}
</script>
@graph is cleaner for complex pages. IDs let entities reference each other.
For CMS-generated content, produce JSON-LD dynamically from content metadata. Most modern CMS plugins (Yoast, RankMath, Schema Pro) handle this. For custom builds:
next/head or metadata APIAvoid client-side schema generation. Googlebot may not always render JS-injected schema.
{
"@type": "Organization",
"name": "Your Company",
"url": "https://yourcompany.com",
"logo": "https://yourcompany.com/logo.png",
"sameAs": [
"https://twitter.com/yourcompany",
"https://linkedin.com/company/yourcompany"
]
}
{
"@type": "Article",
"headline": "...",
"author": { "@type": "Person", "name": "Samuel Ochoa" },
"datePublished": "2026-04-18",
"dateModified": "2026-04-18",
"image": "https://example.com/hero.jpg",
"publisher": { "@type": "Organization", "name": "Example" }
}
{
"@type": "Product",
"name": "Product Name",
"image": "...",
"description": "...",
"offers": {
"@type": "Offer",
"priceCurrency": "USD",
"price": "99.00",
"availability": "https://schema.org/InStock"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.5",
"reviewCount": "127"
}
}
{
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "What is...?",
"acceptedAnswer": {
"@type": "Answer",
"text": "..."
}
}
]
}
Note: Google has restricted FAQ rich results heavily since 2023. Still fine to implement, just don't expect the rich result everywhere.
{
"@type": "BreadcrumbList",
"itemListElement": [
{ "@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com" },
{ "@type": "ListItem", "position": 2, "name": "Blog", "item": "https://example.com/blog" },
{ "@type": "ListItem", "position": 3, "name": "Post", "item": "https://example.com/blog/post" }
]
}
Schema in JSON-LD adds HTML weight. Not usually significant, but for very large sites with many entities per page (thousands of products on a category page), be mindful. Consider serving minimal schema on listing pages and full schema on detail pages.