Structured Data
Structured data is machine-readable metadata describing what your content is - an article, a product, a recipe, an FAQ - using the schema.org vocabulary. It powers rich results (stars, prices, FAQs in the SERP), feeds knowledge panels, and gives answer engines and LLMs unambiguous facts to extract. It is the closest thing SEO has to a free lunch: deterministic, validatable, and directly tied to SERP enhancements.
JSON-LD: the format#
Google recommends JSON-LD - a script block, separate from your markup:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "How to Fix Soft 404s in Next.js",
"datePublished": "2026-03-02",
"dateModified": "2026-05-19",
"author": { "@type": "Person", "name": "Ada Okafor", "url": "https://example.com/authors/ada" },
"image": "https://example.com/og/soft-404s.png"
}
</script>In Next.js, render it from the page component so it ships with the server HTML:
export default async function Page({ params }: PageProps<"/blog/[slug]">) {
const post = await getPost((await params).slug);
const jsonLd = {
"@context": "https://schema.org",
"@type": "Article",
headline: post.title,
datePublished: post.publishedAt,
author: { "@type": "Person", name: post.author.name },
};
return (
<article>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
{/* … */}
</article>
);
}The types that earn rich results#
| Type | Rich result | Use on |
|---|---|---|
Article / BlogPosting | Headline/date/author treatment, Top Stories | Editorial content |
Product + Offer + AggregateRating | Price, stock, stars | Product pages |
FAQPage | Expandable Q&A under your listing | Pages with genuine FAQs |
HowTo | Step-by-step rich result | Instructional content |
BreadcrumbList | Breadcrumb trail instead of raw URL | Everything |
Organization / Person | Knowledge panel inputs, logo | Home/about pages |
LocalBusiness | Map pack data: hours, location | Local SEO |
VideoObject | Video thumbnails and key moments | Pages embedding video |
Two universal rules from Google's policies:
- Markup must describe visible page content. Marking up reviews that aren't on the page is a manual-action offense.
- Eligibility, not entitlement. Valid markup makes you eligible for a rich result; Google decides display per-query.
Entities and the graph#
Beyond rich results, structured data builds your entity graph - connecting your organization, authors and content to known entities. Use @id and sameAs to link identities:
{
"@type": "Organization",
"@id": "https://example.com/#org",
"name": "Example Co",
"url": "https://example.com",
"logo": "https://example.com/logo.png",
"sameAs": [
"https://github.com/example",
"https://www.linkedin.com/company/example",
"https://en.wikipedia.org/wiki/Example_Co"
]
}This disambiguation ("we are this Example, the one with this GitHub and this Wikipedia page") feeds knowledge panels and is increasingly relevant to how generative engines ground brand facts.
Validation and monitoring#
- Rich Results Test - checks eligibility for Google's specific features.
- Schema.org validator - general syntax/vocabulary validation.
- Search Console → Enhancements - ongoing per-type error reports at scale; structured data breaks silently when templates change, so these reports are your alarm.
Next: JavaScript SEO - making sure all of this survives client-side rendering.
