Schema.org Structured Data Reference
Complete reference for Schema.org structured data markup: JSON-LD examples for every major schema type, rich results eligibility, testing tools, and implementation patterns for static sites, Next.js, React, and WordPress.
What Structured Data Does
Structured data is machine-readable markup that tells search engines, voice assistants, and AI systems exactly what your page content means. Instead of relying on algorithms to infer meaning from raw HTML, you declare it explicitly using a shared vocabulary defined at schema.org.
Search engine benefits:
- Rich results — star ratings, prices, FAQ accordions, recipe cards, how-to steps, and event listings displayed directly in Google Search results
- Knowledge panels — branded panels on the right side of search results for organizations, people, and products
- Voice search / Google Assistant — structured data powers direct answers in voice queries (e.g., "What are the hours for [business]?")
- AI citations — large language models and AI search engines (Google AI Overviews, Bing Copilot, Perplexity) use structured data to surface and attribute information
Measurable impact:
- Pages with rich results earn significantly higher click-through rates than plain blue links
- FAQ rich results can double your SERP real estate
- Product rich results with price and availability reduce bounce rates from unqualified clicks
- BreadcrumbList markup replaces raw URLs in search results with readable navigation paths
Formats: JSON-LD, Microdata, RDFa
Three formats exist for embedding structured data in HTML. Google explicitly recommends JSON-LD.
JSON-LD (Recommended)
JavaScript Object Notation for Linked Data. Placed in a <script> tag in the document <head> or <body>. Completely decoupled from the visual HTML — you never mix markup with display code.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Example Corp"
}
</script>
Why Google prefers JSON-LD:
- No coupling between markup and presentation — easier to maintain
- Can be injected dynamically by JavaScript frameworks
- Simpler to validate and debug
- No risk of breaking page layout when modifying structured data
- Supports nesting and complex graphs cleanly
Microdata
Inline HTML attributes (itemscope, itemtype, itemprop) mixed directly into page elements.
<div itemscope itemtype="https://schema.org/Organization">
<span itemprop="name">Example Corp</span>
</div>
When to use: Legacy systems where you cannot add <script> tags, or when structured data must mirror visible content exactly (rare).
RDFa
Similar to Microdata — uses vocab, typeof, and property attributes inline.
<div vocab="https://schema.org/" typeof="Organization">
<span property="name">Example Corp</span>
</div>
When to use: Rarely. RDFa is more common in non-HTML contexts (XML, SVG). For web pages, JSON-LD covers every use case.
Bottom line: Use JSON-LD for all new implementations. It is the only format that cleanly separates data from presentation.
Schema Types and JSON-LD Examples
Organization
Defines a company or organization. Powers knowledge panels and branded search features.
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Cogny AI",
"url": "https://cogny.com",
"logo": "https://cogny.com/images/logo.png",
"sameAs": [
"https://twitter.com/cognyai",
"https://linkedin.com/company/cogny",
"https://github.com/cognyai"
],
"contactPoint": {
"@type": "ContactPoint",
"telephone": "+46-8-123-4567",
"contactType": "customer service",
"availableLanguage": ["English", "Swedish"]
},
"foundingDate": "2023",
"numberOfEmployees": {
"@type": "QuantitativeValue",
"value": 15
}
}
Required: name
Recommended: url, logo, sameAs, contactPoint
Rich result: Knowledge panel (right sidebar in Google Search)
LocalBusiness
Extends Organization for businesses with a physical location. Powers local pack results and Google Maps.
{
"@context": "https://schema.org",
"@type": "LocalBusiness",
"name": "Nordic Coffee Roasters",
"image": "https://example.com/photos/storefront.jpg",
"url": "https://nordiccoffee.se",
"telephone": "+46-8-765-4321",
"priceRange": "$$",
"address": {
"@type": "PostalAddress",
"streetAddress": "Drottninggatan 45",
"addressLocality": "Stockholm",
"addressRegion": "Stockholm",
"postalCode": "111 21",
"addressCountry": "SE"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 59.3293,
"longitude": 18.0686
},
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"opens": "07:00",
"closes": "18:00"
},
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Saturday", "Sunday"],
"opens": "09:00",
"closes": "16:00"
}
],
"sameAs": [
"https://instagram.com/nordiccoffee",
"https://facebook.com/nordiccoffee"
]
}
Required: name, address
Recommended: geo, openingHoursSpecification, telephone, priceRange, image
Rich result: Local pack, knowledge panel with map, hours, and phone
Product
Defines a product with pricing and availability. Powers product rich results in Google Search and Shopping.
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Wireless Noise-Cancelling Headphones",
"image": [
"https://example.com/photos/headphones-front.jpg",
"https://example.com/photos/headphones-side.jpg"
],
"description": "Premium wireless headphones with active noise cancellation, 30-hour battery life, and multipoint Bluetooth connectivity.",
"sku": "WH-1000XM5",
"brand": {
"@type": "Brand",
"name": "AudioTech"
},
"offers": {
"@type": "Offer",
"url": "https://example.com/headphones-wh1000xm5",
"priceCurrency": "USD",
"price": "349.99",
"priceValidUntil": "2025-12-31",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition",
"seller": {
"@type": "Organization",
"name": "AudioTech Store"
}
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.7",
"bestRating": "5",
"reviewCount": "2847"
}
}
Required for rich results: name, image, offers (with price, priceCurrency, availability)
Recommended: sku, brand, aggregateRating, description
Rich result: Product snippet with price, availability, and star rating
FAQPage
Defines a page containing frequently asked questions. Powers FAQ accordion rich results.
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "What is structured data?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Structured data is machine-readable markup added to HTML pages that helps search engines understand your content. It uses the Schema.org vocabulary and is typically implemented in JSON-LD format."
}
},
{
"@type": "Question",
"name": "Does structured data improve SEO rankings?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Structured data does not directly affect rankings. However, it enables rich results that significantly improve click-through rates, which can indirectly improve performance through higher engagement signals."
}
},
{
"@type": "Question",
"name": "How many FAQs should I include per page?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Google will display up to 10 FAQ results per page. Focus on quality over quantity — include the most relevant questions that match real user search intent."
}
}
]
}
Required: mainEntity array with Question items, each containing acceptedAnswer
Rich result: Expandable FAQ accordion directly in search results (up to 10 questions)
HowTo
Defines step-by-step instructions. Powers how-to rich results with numbered steps and images.
{
"@context": "https://schema.org",
"@type": "HowTo",
"name": "How to Implement JSON-LD Structured Data",
"description": "A step-by-step guide to adding Schema.org JSON-LD structured data to your website.",
"totalTime": "PT15M",
"estimatedCost": {
"@type": "MonetaryAmount",
"currency": "USD",
"value": "0"
},
"tool": [
{
"@type": "HowToTool",
"name": "Text editor or CMS"
},
{
"@type": "HowToTool",
"name": "Google Rich Results Test"
}
],
"step": [
{
"@type": "HowToStep",
"name": "Choose your schema type",
"text": "Identify the primary content type of your page (Product, Article, FAQPage, etc.) and look up the required and recommended properties at schema.org.",
"url": "https://example.com/guide#step1",
"image": "https://example.com/images/step1-choose-type.png"
},
{
"@type": "HowToStep",
"name": "Write the JSON-LD block",
"text": "Create a JSON-LD script block with @context set to https://schema.org, @type set to your chosen type, and all required properties filled in with accurate data from your page.",
"url": "https://example.com/guide#step2",
"image": "https://example.com/images/step2-write-jsonld.png"
},
{
"@type": "HowToStep",
"name": "Insert into your page",
"text": "Place the script tag in the head or body of your HTML document. For JavaScript frameworks, use the appropriate head management library.",
"url": "https://example.com/guide#step3",
"image": "https://example.com/images/step3-insert.png"
},
{
"@type": "HowToStep",
"name": "Validate with testing tools",
"text": "Run your page through the Google Rich Results Test and the Schema Markup Validator to confirm the markup is error-free and eligible for rich results.",
"url": "https://example.com/guide#step4",
"image": "https://example.com/images/step4-validate.png"
}
]
}
Required: name, step (with text for each step)
Recommended: image per step, totalTime, tool, supply
Rich result: Numbered step-by-step instructions with optional images
Article / BlogPosting
Defines news articles, blog posts, and other editorial content. Powers article rich results with headline, author, and thumbnail.
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "Complete Guide to Schema.org Structured Data",
"description": "Learn how to implement structured data markup to earn rich results in Google Search.",
"image": [
"https://example.com/images/structured-data-guide-16x9.jpg",
"https://example.com/images/structured-data-guide-4x3.jpg",
"https://example.com/images/structured-data-guide-1x1.jpg"
],
"author": {
"@type": "Person",
"name": "Anna Lindqvist",
"url": "https://example.com/authors/anna-lindqvist"
},
"publisher": {
"@type": "Organization",
"name": "Example Publishing",
"logo": {
"@type": "ImageObject",
"url": "https://example.com/logo.png"
}
},
"datePublished": "2025-01-15",
"dateModified": "2025-02-10",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://example.com/guides/structured-data"
}
}
Use @type: "Article" for news, "BlogPosting" for blog content, "NewsArticle" for news publishers in Google News.
Required for rich results: headline, image, datePublished, author
Recommended: dateModified, publisher, description, mainEntityOfPage
Rich result: Article carousel, Top Stories (NewsArticle), author and date in search results
BreadcrumbList
Defines the navigation path to a page. Replaces raw URLs in search results with readable breadcrumb trails.
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://example.com/"
},
{
"@type": "ListItem",
"position": 2,
"name": "Documentation",
"item": "https://example.com/docs"
},
{
"@type": "ListItem",
"position": 3,
"name": "Structured Data Reference",
"item": "https://example.com/docs/structured-data-reference"
}
]
}
Required: itemListElement with position, name, and item (URL) for each level
Rich result: Breadcrumb trail replaces the URL in search results (e.g., "Example > Documentation > Structured Data")
Review / AggregateRating
Defines individual reviews or aggregated ratings for a product, service, or business.
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Cloud Analytics Platform",
"review": [
{
"@type": "Review",
"reviewRating": {
"@type": "Rating",
"ratingValue": "5",
"bestRating": "5"
},
"author": {
"@type": "Person",
"name": "Erik Johansson"
},
"reviewBody": "Transformed our data pipeline. The BigQuery integration is seamless and the AI insights save us hours every week.",
"datePublished": "2025-01-20"
}
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.8",
"bestRating": "5",
"ratingCount": "312",
"reviewCount": "189"
}
}
Reviews must be nested inside the item they review (Product, LocalBusiness, etc.) — standalone Review markup without an itemReviewed context will not generate rich results.
Required: ratingValue, bestRating, author (for Review); ratingValue, ratingCount (for AggregateRating)
Rich result: Star rating snippet in search results
Event
Defines events with dates, location, and ticket information. Powers event rich results and event packs.
{
"@context": "https://schema.org",
"@type": "Event",
"name": "Nordic Growth Marketing Summit 2025",
"description": "Two-day conference on performance marketing, AI-driven analytics, and growth strategies for Nordic businesses.",
"startDate": "2025-09-15T09:00:00+02:00",
"endDate": "2025-09-16T17:00:00+02:00",
"eventStatus": "https://schema.org/EventScheduled",
"eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode",
"location": {
"@type": "Place",
"name": "Stockholm Waterfront Congress Centre",
"address": {
"@type": "PostalAddress",
"streetAddress": "Nils Ericsons Plan 4",
"addressLocality": "Stockholm",
"postalCode": "111 64",
"addressCountry": "SE"
}
},
"performer": {
"@type": "Organization",
"name": "Cogny AI"
},
"offers": {
"@type": "Offer",
"url": "https://example.com/tickets",
"price": "4999",
"priceCurrency": "SEK",
"availability": "https://schema.org/InStock",
"validFrom": "2025-03-01T00:00:00+01:00"
},
"organizer": {
"@type": "Organization",
"name": "Growth Hackers Stockholm",
"url": "https://growthhackers.se"
},
"image": "https://example.com/images/summit-2025.jpg"
}
Required: name, startDate, location
Recommended: endDate, offers, performer, eventStatus, eventAttendanceMode, image
Rich result: Event listing with date, location, and ticket link; event pack in search results
VideoObject
Defines a video with metadata for video rich results and Google Video search.
{
"@context": "https://schema.org",
"@type": "VideoObject",
"name": "How to Set Up GA4 BigQuery Export",
"description": "Step-by-step tutorial for connecting Google Analytics 4 to BigQuery, configuring the export, and verifying data flow.",
"thumbnailUrl": "https://example.com/thumbnails/ga4-bigquery-setup.jpg",
"uploadDate": "2025-01-10",
"duration": "PT12M30S",
"contentUrl": "https://example.com/videos/ga4-bigquery-setup.mp4",
"embedUrl": "https://youtube.com/embed/abc123",
"interactionStatistic": {
"@type": "InteractionCounter",
"interactionType": {
"@type": "WatchAction"
},
"userInteractionCount": 15420
}
}
Required: name, thumbnailUrl, uploadDate
Recommended: description, duration, contentUrl or embedUrl
Rich result: Video carousel, video thumbnail in search results, Google Video search listing
SoftwareApplication
Defines a software product with platform and pricing information.
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "Cogny Analytics Platform",
"operatingSystem": "Web",
"applicationCategory": "BusinessApplication",
"description": "AI-powered analytics platform that connects to BigQuery, Google Ads, and Meta Ads for automated growth insights.",
"offers": {
"@type": "Offer",
"price": "99",
"priceCurrency": "USD"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.8",
"ratingCount": "156"
},
"screenshot": "https://example.com/images/dashboard-screenshot.png"
}
Required: name, offers (with price and priceCurrency)
Recommended: operatingSystem, applicationCategory, aggregateRating
Rich result: Software snippet with rating and price
Course
Defines an educational course with provider information.
{
"@context": "https://schema.org",
"@type": "Course",
"name": "Advanced BigQuery for Marketing Analytics",
"description": "Learn to write efficient BigQuery SQL for GA4 data, build marketing attribution models, and create automated reporting pipelines.",
"provider": {
"@type": "Organization",
"name": "Cogny Academy",
"sameAs": "https://cogny.com/academy"
},
"courseCode": "BQ-301",
"hasCourseInstance": {
"@type": "CourseInstance",
"courseMode": "online",
"courseSchedule": {
"@type": "Schedule",
"repeatFrequency": "P1W",
"startDate": "2025-03-01",
"endDate": "2025-04-15"
}
},
"offers": {
"@type": "Offer",
"price": "499",
"priceCurrency": "USD",
"category": "Paid"
}
}
Required: name, description, provider
Recommended: offers, hasCourseInstance, courseCode
Rich result: Course listing with provider and enrollment information
JobPosting
Defines a job listing with compensation, location, and requirements.
{
"@context": "https://schema.org",
"@type": "JobPosting",
"title": "Senior Growth Engineer",
"description": "We are looking for a senior growth engineer to build and optimize our marketing analytics infrastructure, including BigQuery pipelines, A/B testing frameworks, and automated reporting.",
"datePosted": "2025-02-01",
"validThrough": "2025-04-01T23:59:59+01:00",
"employmentType": "FULL_TIME",
"hiringOrganization": {
"@type": "Organization",
"name": "Cogny AI",
"sameAs": "https://cogny.com",
"logo": "https://cogny.com/images/logo.png"
},
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"addressLocality": "Stockholm",
"addressRegion": "Stockholm",
"addressCountry": "SE"
}
},
"jobLocationType": "TELECOMMUTE",
"baseSalary": {
"@type": "MonetaryAmount",
"currency": "SEK",
"value": {
"@type": "QuantitativeValue",
"minValue": 55000,
"maxValue": 75000,
"unitText": "MONTH"
}
},
"applicantLocationRequirements": {
"@type": "Country",
"name": "Sweden"
}
}
Required: title, description, datePosted, hiringOrganization, jobLocation
Recommended: validThrough, employmentType, baseSalary, jobLocationType
Rich result: Job listing in Google Jobs with salary, location, and apply button
Testing and Validation
Google Rich Results Test
URL: search.google.com/test/rich-results
Test individual pages or code snippets for rich result eligibility. Shows which rich result types are detected, whether they pass validation, and lists any errors or warnings.
Use for: Pre-launch validation, debugging specific pages, testing JSON-LD snippets before deployment.
Schema Markup Validator
URL: validator.schema.org
Validates against the full Schema.org specification (not just Google's subset). Catches structural errors, incorrect types, and missing required properties that the Rich Results Test might not flag.
Use for: Spec compliance, catching edge cases, validating schema types that Google does not currently use for rich results.
Google Search Console Rich Results Report
Location: Search Console > Enhancements > [specific rich result type]
Shows aggregate data across your entire site: how many pages have valid structured data, how many have errors, and which specific errors are most common. Updated daily.
Use for: Ongoing monitoring, catching regressions after deployments, tracking rich result coverage over time.
Common Validation Errors and Fixes
| Error | Cause | Fix |
|---|---|---|
Missing field "image" | Product or Article missing required image | Add image property with a valid URL to a crawlable image |
Invalid URL in field "url" | Relative URL instead of absolute | Use fully qualified URLs (e.g., https://example.com/page) |
Missing field "author" | Article or Review missing author | Add author as a Person or Organization object with name |
Invalid value in field "price" | Price includes currency symbol | Use numeric value only (e.g., "349.99" not "$349.99") |
Invalid enum value for "availability" | Plain text instead of Schema.org URL | Use https://schema.org/InStock, not "In Stock" |
Warning: missing recommended field | Recommended property omitted | Not blocking, but add it for best rich result presentation |
Array expected, single value found | Single image instead of array | Wrap in array: "image": ["https://..."] |
datePublished is in the future | Publish date set ahead of actual publish | Set datePublished to the actual publication date |
Best Practices
One Primary Schema Type per Page
Each page should have one primary schema type that matches its main content purpose. A product page uses Product schema, a blog post uses Article or BlogPosting, a FAQ page uses FAQPage. You can combine complementary types (e.g., BreadcrumbList alongside the primary type), but do not add multiple competing primary types.
Nesting vs. Flat Structures
Nest when there is a clear parent-child relationship:
{
"@type": "Product",
"name": "Widget",
"offers": {
"@type": "Offer",
"price": "29.99"
}
}
Use @graph for multiple independent entities on the same page:
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "BreadcrumbList",
"itemListElement": [...]
},
{
"@type": "Product",
"name": "Widget",
"offers": {...}
}
]
}
Required vs. Recommended Properties
Google documents required and recommended properties for each rich result type. Required properties must be present for the rich result to appear at all. Recommended properties improve the quality and appearance of the rich result. Always include both.
Reference: developers.google.com/search/docs/appearance/structured-data/search-gallery
Avoiding Spammy Markup
Google penalizes structured data that misrepresents page content:
- Fake reviews: Do not fabricate reviews or ratings. AggregateRating must reflect real user reviews
- Misleading content: Schema properties must match visible page content. If your Product schema says the price is $29.99, that price must be visible on the page
- Hidden markup: Do not add structured data for content that is not visible to users
- Schema type mismatch: Do not mark a category page as a Product, or a marketing page as an Article
- Self-serving reviews: Do not add Review markup where the reviewed item is the page owner's own product without genuine third-party reviews
Google's manual actions for structured data spam can remove all rich results from your entire site.
Keeping Schema in Sync with Page Content
Structured data must always reflect the current, visible page content. Stale markup (outdated prices, discontinued products still marked InStock, old dates) triggers validation warnings and can result in manual actions.
Recommendations:
- Generate structured data dynamically from the same data source as the page content
- Include schema updates in your CMS publishing workflow
- Set up Search Console alerts for structured data errors
- Audit structured data quarterly or after major site changes
Rich Results Eligibility
Which schema types trigger which rich results in Google Search:
| Schema Type | Rich Result | SERP Appearance |
|---|---|---|
Product | Product snippet | Price, availability, rating stars below listing |
FAQPage | FAQ accordion | Expandable Q&A directly in results |
HowTo | How-to steps | Numbered steps with optional images |
Article / BlogPosting | Article result | Author, date, thumbnail image |
NewsArticle | Top Stories | Carousel at top of results |
BreadcrumbList | Breadcrumb trail | Replaces URL with navigation path |
Review / AggregateRating | Review snippet | Star rating below listing |
Event | Event listing | Date, location, ticket info in event pack |
VideoObject | Video result | Thumbnail, duration in video carousel |
LocalBusiness | Local pack | Map pin, hours, phone, directions |
JobPosting | Google Jobs | Salary, location, apply button in jobs widget |
SoftwareApplication | Software result | Rating, price |
Course | Course listing | Provider, schedule, enrollment |
Recipe | Recipe card | Cook time, calories, rating, image |
Organization | Knowledge panel | Logo, social links, description (right sidebar) |
Not all schema types generate rich results. Google supports a specific subset — check the Search Gallery for the current list.
Implementation Patterns
Static HTML Injection
Add the JSON-LD <script> tag directly in your HTML <head>:
<!DOCTYPE html>
<html>
<head>
<title>Product Page</title>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Widget Pro",
"offers": {
"@type": "Offer",
"price": "49.99",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock"
}
}
</script>
</head>
<body>...</body>
</html>
Best for simple static sites, landing pages, and server-rendered pages.
Next.js / React Head Management
Use Next.js <Script> component or the metadata API:
// app/products/[slug]/page.tsx (App Router)
export default function ProductPage({ product }) {
const jsonLd = {
"@context": "https://schema.org",
"@type": "Product",
name: product.name,
image: product.images,
description: product.description,
sku: product.sku,
brand: {
"@type": "Brand",
name: product.brand,
},
offers: {
"@type": "Offer",
priceCurrency: product.currency,
price: product.price,
availability: product.inStock
? "https://schema.org/InStock"
: "https://schema.org/OutOfStock",
},
};
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
{/* Page content */}
</>
);
}
For the Pages Router, use next/head:
import Head from "next/head";
export default function ProductPage({ product }) {
const jsonLd = { /* ... same as above ... */ };
return (
<>
<Head>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
</Head>
{/* Page content */}
</>
);
}
WordPress Plugins
For WordPress sites, several plugins handle structured data without manual coding:
- Yoast SEO — Automatically generates Organization, Article, BreadcrumbList, and other schema types. Includes a schema tab for per-page customization
- Rank Math — Built-in schema generator with a visual editor. Supports 20+ schema types with per-post configuration
- Schema Pro — Dedicated structured data plugin with conditional rules (e.g., add Product schema to all pages in the "Shop" category)
Manual approach in WordPress — Add JSON-LD via the wp_head action:
add_action('wp_head', function() {
if (is_singular('product')) {
$product = get_post();
$price = get_post_meta($product->ID, '_price', true);
$schema = [
'@context' => 'https://schema.org',
'@type' => 'Product',
'name' => $product->post_title,
'description' => $product->post_excerpt,
'offers' => [
'@type' => 'Offer',
'price' => $price,
'priceCurrency' => 'USD',
'availability' => 'https://schema.org/InStock',
],
];
echo '<script type="application/ld+json">' . json_encode($schema) . '</script>';
}
});
Dynamic Generation from CMS Data
For headless CMS setups (Contentful, Sanity, Strapi), generate structured data from the API response:
// Generic pattern for any CMS
function generateProductSchema(cmsData: CMSProduct): object {
return {
"@context": "https://schema.org",
"@type": "Product",
name: cmsData.title,
image: cmsData.media.map((m) => m.url),
description: cmsData.shortDescription,
sku: cmsData.sku,
brand: {
"@type": "Brand",
name: cmsData.brand.name,
},
offers: {
"@type": "Offer",
price: cmsData.variants[0].price.toString(),
priceCurrency: cmsData.currency,
availability: cmsData.inStock
? "https://schema.org/InStock"
: "https://schema.org/OutOfStock",
},
};
}
The key principle: structured data should be generated from the same data source that populates the page, never hardcoded separately. This ensures schema stays in sync with visible content.
Claude Code Skill
This structured data reference is also available as a free Claude Code skill — use it directly in your terminal:
# Install
curl -sSL https://raw.githubusercontent.com/cognyai/claude-code-marketing-skills/main/install.sh | bash
# Use
/structured-data # Full reference overview
/structured-data Product # Show Product schema example
/structured-data FAQPage # Show FAQPage example
/structured-data validate # Testing and validation guide
Resources
- Schema.org Full Vocabulary: schema.org/docs/full.html
- Google Rich Results Gallery: developers.google.com/search/docs/appearance/structured-data/search-gallery
- Google Rich Results Test: search.google.com/test/rich-results
- Schema Markup Validator: validator.schema.org
- Google Structured Data Guidelines: developers.google.com/search/docs/appearance/structured-data/sd-policies
- Claude Code Marketing Skills: github.com/cognyai/claude-code-marketing-skills