Schema.org structured data rules for JSON-LD markup in Next.js. Use when adding or modifying structured data, product schemas, breadcrumbs, or FAQ markup.
Follow these rules when implementing schema.org structured data.
@graph to combine multiple schemas. Multiple tags are valid but harder to maintain.export function JsonLd({ data }: { data: Record<string, unknown> }) {
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}
/>
);
}
{
"@type": "Product",
name: product.name,
description: product.description,
sku: product.sku,
brand: { "@type": "Brand", name: siteConfig.brandName },
image: product.images,
offers: {
"@type": "Offer",
price: product.price,
priceCurrency: getCurrencyForLocale(locale),
availability: "https://schema.org/InStock", // or OutOfStock, PreOrder
seller: { "@type": "Organization", name: siteConfig.brandName },
}
}
Required for rich results: name, image, offers.price, offers.priceCurrency, offers.availability.
{
"@type": "BreadcrumbList",
itemListElement: [
{ "@type": "ListItem", position: 1, name: "Home", item: `${siteConfig.url}/` },
{ "@type": "ListItem", position: 2, name: "Category", item: `${siteConfig.url}/category` },
{ "@type": "ListItem", position: 3, name: "Current Page" }, // No item URL for current page
]
}
Note: Since August 2023, Google has progressively restricted FAQ rich results to a small number of well-known, authoritative government and health websites. For e-commerce sites, FAQ schema provides essentially zero value from Google. Other search engines (Bing) may still use it, but the ROI is minimal. Skip FAQ schema on e-commerce sites unless you have a specific non-Google reason.
{
"@type": "FAQPage",
mainEntity: [
{ "@type": "Question", name: "Q text", acceptedAnswer: { "@type": "Answer", text: "A text" } },
]
}
Only add FAQ schema on pages with visible Q&A content. Min 2 questions. Implementation is optional given the restricted eligibility above.
{
"@type": "WebSite",
name: siteConfig.brandName,
url: siteConfig.url,
potentialAction: {
"@type": "SearchAction",
target: { "@type": "EntryPoint", urlTemplate: `${siteConfig.url}/search?q={query}` },
"query-input": "required name=query"
}
}
Use @graph when a page has multiple schema types:
<JsonLd data={{
"@context": "https://schema.org",
"@graph": [productSchema, breadcrumbSchema]
}} />
@graph to keep structured data organized (multiple tags are valid but harder to maintain)