Add structured data markup
Schema.org structured data (JSON-LD) is implemented for rich search results.
- Structured data enables rich snippets in search results
- Use JSON-LD format (Google recommended)
- Common types: Article, Product, FAQ, HowTo, LocalBusiness
- Validate with Google Rich Results Test
Rule Details
Structured data helps search engines understand your content and enables rich results.
Code Example
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Executive Widget",
"description": "Premium quality widget for professionals",
"image": "https://example.com/images/widget.jpg",
"offers": {
"@type": "Offer",
"price": "49.99",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock"
}
}
</script>Why It Matters
Structured data enables rich snippets with stars, prices, images, and FAQ dropdowns in search results—significantly increasing click-through rates.
Common Schema Types
| Type | Use For | Rich Result |
|---|---|---|
| Article | Blog posts, news | Author, date, image |
| Product | E-commerce items | Price, rating, availability |
| FAQ | FAQ pages | Expandable questions |
| HowTo | Tutorials, guides | Step-by-step instructions |
| LocalBusiness | Physical locations | Map, hours, reviews |
| Organization | Company info | Logo, social profiles |
| BreadcrumbList | Navigation path | Breadcrumb trail |
Article Schema
// components/ArticleSchema.tsx
interface ArticleSchemaProps {
title: string
description: string
image: string
datePublished: string
dateModified: string
author: string
url: string
}
export function ArticleSchema({
title,
description,
image,
datePublished,
dateModified,
author,
url,
}: ArticleSchemaProps) {
const schema = {
'@context': 'https://schema.org',
'@type': 'Article',
headline: title,
description,
image,
datePublished,
dateModified,
author: {
'@type': 'Person',
name: author,
},
publisher: {
'@type': 'Organization',
name: 'Example Company',
logo: {
'@type': 'ImageObject',
url: 'https://example.com/logo.png',
},
},
mainEntityOfPage: {
'@type': 'WebPage',
'@id': url,
},
}
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
)
}Product Schema
interface ProductSchemaProps {
name: string
description: string
image: string
price: number
currency: string
availability: 'InStock' | 'OutOfStock' | 'PreOrder'
rating?: number
reviewCount?: number
brand?: string
sku?: string
}
export function ProductSchema({
name,
description,
image,
price,
currency,
availability,
rating,
reviewCount,
brand,
sku,
}: ProductSchemaProps) {
const schema: any = {
'@context': 'https://schema.org',
'@type': 'Product',
name,
description,
image,
sku,
brand: brand ? { '@type': 'Brand', name: brand } : undefined,
offers: {
'@type': 'Offer',
price: price.toFixed(2),
priceCurrency: currency,
availability: `https://schema.org/${availability}`,
},
}
if (rating && reviewCount) {
schema.aggregateRating = {
'@type': 'AggregateRating',
ratingValue: rating,
reviewCount,
}
}
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
)
}FAQ Schema
interface FAQItem {
question: string
answer: string
}
export function FAQSchema({ items }: { items: FAQItem[] }) {
const schema = {
'@context': 'https://schema.org',
'@type': 'FAQPage',
mainEntity: items.map(item => ({
'@type': 'Question',
name: item.question,
acceptedAnswer: {
'@type': 'Answer',
text: item.answer,
},
})),
}
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
)
}Breadcrumb Schema
interface BreadcrumbItem {
name: string
url: string
}
export function BreadcrumbSchema({ items }: { items: BreadcrumbItem[] }) {
const schema = {
'@context': 'https://schema.org',
'@type': 'BreadcrumbList',
itemListElement: items.map((item, index) => ({
'@type': 'ListItem',
position: index + 1,
name: item.name,
item: item.url,
})),
}
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
)
}Organization Schema
export function OrganizationSchema() {
const schema = {
'@context': 'https://schema.org',
'@type': 'Organization',
name: 'Example Company',
url: 'https://example.com',
logo: 'https://example.com/logo.png',
contactPoint: {
'@type': 'ContactPoint',
telephone: '+1-555-555-5555',
contactType: 'customer service',
},
sameAs: [
'https://twitter.com/example',
'https://www.linkedin.com/company/example',
'https://github.com/example',
],
}
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
)
}Next.js App Router Integration
// app/blog/[slug]/page.tsx
import { ArticleSchema } from '@/components/ArticleSchema'
export default async function BlogPost({ params }) {
const post = await getPost(params.slug)
return (
<>
<ArticleSchema
title={post.title}
description={post.excerpt}
image={post.image}
datePublished={post.createdAt}
dateModified={post.updatedAt}
author={post.author.name}
url={`https://example.com/blog/${params.slug}`}
/>
<article>{/* Content */}</article>
</>
)
}Exceptions
- Necessary utility or compliance pages can be intentionally brief and should not be judged by the same editorial-depth expectations as ranking-focused content.
- AI-assisted drafting is not a failure by itself; flag unsupported claims, missing editorial review, or low-originality output instead.
- When a page has both trust-signal issues and crawl/index problems, make the page eligible to rank first and then improve the content quality signals.
Standards
- Use these references as the standard for the final search-facing HTML, metadata, and crawl behavior.
- Check the implementation against Google Search Central: Search Essentials before treating the rule as satisfied.
- Check the implementation against Google Search Central documentation before treating the rule as satisfied.
Verification
Automated Checks
- Use Google Rich Results Test (opens in new tab)
- Validate with Schema Markup Validator
- Check Google Search Console for errors
- Test in multiple browsers
Manual Checks
- Verify JSON syntax is valid
Use with AI
Copy these prompts to use with your AI assistant, or install the MCP server to use directly from Claude, Cursor, or Windsurf.
Check
Verify implementation
Analyze if this webpage implements structured data using Schema.org vocabulary. Check for JSON-LD, Microdata, or RDFa markup.
Fix
Auto-fix issues
Add appropriate Schema.org structured data to this webpage based on its content type (Article, Product, LocalBusiness, etc.).
Explain
Learn more
Explain how structured data helps search engines understand page content and enables rich snippets in search results.
Review
Code review
Review metadata generation, rendered HTML, structured data, and response headers related to Add structured data markup. Flag exact routes or templates where search-facing output violates the rule, and describe how to verify the final page output.