Structured Data Schema Org
Schema.org structured data markup: JSON-LD implementation for rich results, product/article/FAQ/breadcrumb schemas, validation, and Google Search Console integration.
Structured data is the bridge between your page content and search engine understanding. When implemented correctly via JSON-LD, it enables rich results -- star ratings, FAQ accordions, breadcrumb trails, product prices -- that directly increase click-through rates without changing your algorithmic ranking. The ROI of structured data is one of the highest in SEO because the implementation effort is modest and the visibility impact is immediate and measurable. ## Key Points - Always validate structured data with Google's Rich Results Test (https://search.google.com/test/rich-results) before deploying. Invalid markup is silently ignored by search engines. - Keep structured data in sync with visible page content. Google penalizes markup that describes content not visible to users (e.g., fake reviews or prices that differ from what is displayed). - Use the `@id` pattern to cross-reference entities within a `@graph` block, creating a connected entity graph that search engines can traverse. - Marking up content that is not visible on the page. Google's guidelines require structured data to reflect user-visible content; violations can result in manual actions. ## Quick Example ```bash # Test a live URL npx structured-data-testing-tool --url https://example.com/product/widget # Test local HTML file npx structured-data-testing-tool --file ./out/product/widget.html ```
skilldb get seo-content-skills/Structured Data Schema OrgFull skill: 232 linesStructured Data & Schema.org — SEO & Content
Core Philosophy
Structured data is the bridge between your page content and search engine understanding. When implemented correctly via JSON-LD, it enables rich results -- star ratings, FAQ accordions, breadcrumb trails, product prices -- that directly increase click-through rates without changing your algorithmic ranking. The ROI of structured data is one of the highest in SEO because the implementation effort is modest and the visibility impact is immediate and measurable.
JSON-LD is the industry standard for structured data because it separates markup from HTML, making it easier to maintain, debug, and generate dynamically. Google explicitly recommends JSON-LD over Microdata and RDFa. A reusable JsonLd component in your React or Next.js application that accepts typed data objects is the cleanest implementation pattern.
Structured data must always reflect user-visible content. Google penalizes markup that describes content not shown on the page -- fake reviews, prices that differ from displayed values, or FAQ content hidden from users. The structured data is a machine-readable description of what the human sees, not an opportunity to inject additional information for search engines.
You are an expert in Schema.org structured data markup for SEO, specializing in JSON-LD implementation, rich result eligibility, and search engine validation.
Overview
Structured data uses a standardized vocabulary (Schema.org) to annotate web page content so search engines can understand entities, relationships, and attributes. When implemented correctly via JSON-LD, structured data enables rich results in Google Search — star ratings, FAQ accordions, breadcrumb trails, product prices, recipe cards, and more. This directly increases click-through rates and search visibility without changing page rankings algorithmically.
Core Concepts
JSON-LD as the Preferred Format
Google recommends JSON-LD (JavaScript Object Notation for Linked Data) over Microdata or RDFa. JSON-LD is injected as a <script> block, keeping markup separate from HTML structure.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Understanding Structured Data",
"datePublished": "2026-01-15T08:00:00+00:00",
"dateModified": "2026-03-10T12:00:00+00:00",
"author": {
"@type": "Person",
"name": "Jane Smith",
"url": "https://example.com/authors/jane-smith"
}
}
</script>
Schema Types That Trigger Rich Results
| Schema Type | Rich Result | Key Required Fields |
|---|---|---|
Article | Article snippet | headline, datePublished, author |
Product | Product card with price/rating | name, offers, aggregateRating |
FAQPage | Expandable FAQ accordion | mainEntity[].name, mainEntity[].acceptedAnswer |
BreadcrumbList | Breadcrumb trail | itemListElement[].name, itemListElement[].item |
HowTo | Step-by-step instructions | name, step[].text |
LocalBusiness | Business panel | name, address, telephone |
Organization | Knowledge panel | name, url, logo |
Review | Star ratings | reviewRating, author, itemReviewed |
Event | Event listing | name, startDate, location |
VideoObject | Video carousel | name, uploadDate, thumbnailUrl |
The @graph Pattern for Multiple Entities
When a page has multiple schema types, use @graph to bundle them in a single JSON-LD block:
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "WebPage",
"@id": "https://example.com/product/widget#webpage",
"name": "Widget Product Page",
"isPartOf": { "@id": "https://example.com/#website" }
},
{
"@type": "Product",
"name": "Widget Pro",
"offers": {
"@type": "Offer",
"price": "49.99",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock"
}
},
{
"@type": "BreadcrumbList",
"itemListElement": [
{ "@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com/" },
{ "@type": "ListItem", "position": 2, "name": "Products", "item": "https://example.com/products/" },
{ "@type": "ListItem", "position": 3, "name": "Widget Pro" }
]
}
]
}
Implementation Patterns
Reusable JSON-LD Component (React/Next.js)
// components/structured-data.tsx
type JsonLdProps = {
data: Record<string, unknown> | Record<string, unknown>[];
};
export function JsonLd({ data }: JsonLdProps) {
const jsonLd = Array.isArray(data)
? { "@context": "https://schema.org", "@graph": data }
: { "@context": "https://schema.org", ...data };
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
);
}
FAQ Page Schema
interface FaqItem {
question: string;
answer: string;
}
export function faqSchema(items: FaqItem[]) {
return {
"@type": "FAQPage",
mainEntity: items.map((item) => ({
"@type": "Question",
name: item.question,
acceptedAnswer: {
"@type": "Answer",
text: item.answer,
},
})),
};
}
Product Schema with Offers
interface ProductData {
name: string;
description: string;
image: string;
sku: string;
price: number;
currency: string;
availability: "InStock" | "OutOfStock" | "PreOrder";
ratingValue?: number;
reviewCount?: number;
}
export function productSchema(product: ProductData) {
return {
"@type": "Product",
name: product.name,
description: product.description,
image: product.image,
sku: product.sku,
offers: {
"@type": "Offer",
price: product.price.toFixed(2),
priceCurrency: product.currency,
availability: `https://schema.org/${product.availability}`,
url: typeof window !== "undefined" ? window.location.href : undefined,
},
...(product.ratingValue && {
aggregateRating: {
"@type": "AggregateRating",
ratingValue: product.ratingValue,
reviewCount: product.reviewCount,
},
}),
};
}
Breadcrumb Schema from URL Path
export function breadcrumbSchema(
segments: { name: string; url: string }[]
) {
return {
"@type": "BreadcrumbList",
itemListElement: segments.map((segment, index) => ({
"@type": "ListItem",
position: index + 1,
name: segment.name,
...(index < segments.length - 1 ? { item: segment.url } : {}),
})),
};
}
Validation with Google's Rich Results Test API
# Test a live URL
npx structured-data-testing-tool --url https://example.com/product/widget
# Test local HTML file
npx structured-data-testing-tool --file ./out/product/widget.html
Use Google Search Console's "Enhancements" reports to monitor structured data errors across the entire site after deployment.
Best Practices
- Always validate structured data with Google's Rich Results Test (https://search.google.com/test/rich-results) before deploying. Invalid markup is silently ignored by search engines.
- Keep structured data in sync with visible page content. Google penalizes markup that describes content not visible to users (e.g., fake reviews or prices that differ from what is displayed).
- Use the
@idpattern to cross-reference entities within a@graphblock, creating a connected entity graph that search engines can traverse.
Anti-Patterns
- Invisible markup: Adding structured data for content that is not visible on the page. Google's guidelines require structured data to reflect user-visible content, and violations can result in manual actions that remove rich results entirely.
- Using Microdata or RDFa instead of JSON-LD: While technically valid, these formats interleave with HTML and are harder to maintain, debug, and generate dynamically. JSON-LD as a separate script block is cleaner and Google-recommended.
- Skipping validation before deployment: Pushing structured data to production without testing with Google's Rich Results Test. Invalid markup is silently ignored by search engines, providing zero benefit while creating a false sense of implementation.
- Stale structured data: Letting structured data drift out of sync with page content after product updates, price changes, or content edits. Structured data must be generated dynamically from the same data source as the page content.
- Separate JSON-LD blocks per entity: Using multiple
<script type="application/ld+json">blocks on a single page instead of bundling entities into a single@grapharray. The graph pattern creates a connected entity model that search engines can traverse more effectively.
Common Pitfalls
- Marking up content that is not visible on the page. Google's guidelines require structured data to reflect user-visible content; violations can result in manual actions.
- Using Microdata or RDFa instead of JSON-LD. While technically valid, these formats interleave with HTML and are harder to maintain, debug, and generate dynamically. JSON-LD is the industry standard.
Install this skill directly: skilldb add seo-content-skills
Related Skills
Contentlayer
"Contentlayer and Velite for type-safe content management: transforming Markdown/MDX into typed data, schema validation, computed fields, Next.js integration, hot reload, and migration between content tools."
Core Web Vitals
Core Web Vitals optimization: LCP, INP, and CLS measurement, diagnosis, and improvement strategies for better search rankings and user experience.
Fumadocs
"fumadocs documentation framework: Next.js App Router native, MDX content collections, full-text search, OpenAPI integration, TypeScript-first, customizable UI components, and content source adapters."
Mdx
"MDX authoring with Next.js: Markdown + JSX, custom components, frontmatter extraction, @next/mdx, mdx-bundler, contentlayer integration, rehype/remark plugins, and syntax highlighting with Shiki or Prism."
Next SEO
"Next.js SEO and metadata management: meta tags, Open Graph, Twitter cards, JSON-LD structured data, canonical URLs, robots directives, and sitemap generation using the Metadata API and next-seo."
Nextra
"Nextra documentation framework: MDX-powered Next.js docs and blog sites, sidebar navigation, full-text search, i18n, themes (docs and blog), frontmatter configuration, and custom components."