seo-schema-structured-data
Schema.org Structured Data & JSON-LD
JSON-LD Fundamentals
JSON-LD (JavaScript Object Notation for Linked Data) is Google's recommended format for structured data. It is injected via a <script> tag in the <head> or <body> of an HTML page.
Basic Syntax
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "How to Implement Structured Data",
"author": {
"@type": "Person",
"name": "Jane Smith"
}
}
</script>
Core Keywords
| Keyword | Purpose | Example |
|---|---|---|
@context |
Declares the vocabulary (always https://schema.org) |
"@context": "https://schema.org" |
@type |
Specifies the entity type | "@type": "Article" |
@id |
Unique identifier for an entity (enables cross-referencing) | "@id": "https://example.com/#organization" |
@graph |
Contains multiple entities in a single JSON-LD block | "@graph": [{ ... }, { ... }] |
Nesting Entities
Entities can be nested directly or referenced by @id:
{
"@context": "https://schema.org",
"@type": "Article",
"author": {
"@type": "Person",
"name": "Jane Smith",
"@id": "https://example.com/#jane"
},
"publisher": {
"@id": "https://example.com/#organization"
}
}
Arrays
Use arrays when a property has multiple values:
{
"@type": "Article",
"author": [
{ "@type": "Person", "name": "Jane Smith" },
{ "@type": "Person", "name": "John Doe" }
]
}
The @graph Pattern (Multi-Entity Pages)
Use @graph to describe multiple entities on a single page (e.g., Organization + WebPage + BreadcrumbList):
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Organization",
"@id": "https://example.com/#organization",
"name": "Example Corp",
"url": "https://example.com"
},
{
"@type": "WebPage",
"@id": "https://example.com/about/#webpage",
"url": "https://example.com/about/",
"name": "About Us",
"isPartOf": { "@id": "https://example.com/#website" }
},
{
"@type": "BreadcrumbList",
"itemListElement": [
{ "@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com/" },
{ "@type": "ListItem", "position": 2, "name": "About" }
]
}
]
}
Google-Supported Schema Types
The following types are recognized by Google and can trigger rich results. Each section lists required (R) and recommended (Rec) properties.
Article (NewsArticle, BlogPosting)
Triggers: article rich result with headline, image, date in search.
| Property | Status | Notes |
|---|---|---|
headline |
R | Max 110 characters |
image |
R | At least 696px wide; multiple images recommended |
datePublished |
R | ISO 8601 format |
dateModified |
Rec | ISO 8601 format |
author |
R | Person or Organization with name and url |
publisher |
Rec | Organization with name and logo |
description |
Rec | Short summary of the article |
mainEntityOfPage |
Rec | URL of the page |
MCP Tool: Use extract_schema on any article URL to see its current structured data, then generate_schema with type Article to produce compliant markup.
Product (with Offer, AggregateRating)
Triggers: product rich result with price, availability, rating stars.
| Property | Status | Notes |
|---|---|---|
name |
R | Product name |
image |
R | At least one image |
description |
Rec | Product description |
sku |
Rec | Stock-keeping unit |
brand |
Rec | Brand name |
offers |
R | Offer or AggregateOffer |
offers.price |
R | Numeric price |
offers.priceCurrency |
R | ISO 4217 currency code |
offers.availability |
R | ItemAvailability enum (e.g., https://schema.org/InStock) |
offers.url |
Rec | URL to buy |
aggregateRating |
Rec | AggregateRating with ratingValue and reviewCount |
review |
Rec | Individual Review objects |
Nesting pattern: AggregateRating and Offer nest inside Product:
{
"@type": "Product",
"name": "Widget",
"offers": {
"@type": "Offer",
"price": "29.99",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.5",
"reviewCount": "120"
}
}
FAQPage (with Question / Answer)
Triggers: expandable FAQ accordion in search results.
| Property | Status | Notes |
|---|---|---|
mainEntity |
R | Array of Question objects |
Question.name |
R | The question text |
Question.acceptedAnswer |
R | Answer object |
Answer.text |
R | The answer text (HTML allowed) |
Rules:
- Only use FAQPage for pages where the primary content is a list of questions and answers.
- Each question and answer must be visible on the page.
- Do not use for forums or single-question pages (use QAPage instead).
HowTo (with HowToStep)
Triggers: step-by-step rich result or carousel.
| Property | Status | Notes |
|---|---|---|
name |
R | Title of the how-to |
step |
R | Array of HowToStep objects |
step.name |
R | Step title |
step.text |
R | Step instructions |
step.image |
Rec | Image for each step |
step.url |
Rec | URL anchor to step on page |
totalTime |
Rec | ISO 8601 duration (e.g., PT30M) |
estimatedCost |
Rec | MonetaryAmount object |
supply |
Rec | HowToSupply items needed |
tool |
Rec | HowToTool items needed |
LocalBusiness (and Subtypes)
Triggers: local knowledge panel, map pack eligibility data.
Subtypes: Restaurant, Dentist, LegalService, RealEstateAgent, MedicalBusiness, etc.
| Property | Status | Notes |
|---|---|---|
name |
R | Business name |
address |
R | PostalAddress object |
telephone |
Rec | Phone number |
openingHoursSpecification |
Rec | Array of hours |
geo |
Rec | GeoCoordinates (lat/long) |
url |
Rec | Website URL |
image |
Rec | Business photo |
priceRange |
Rec | e.g., $$ or $10-50 |
servesCuisine |
Rec | For Restaurant subtype |
aggregateRating |
Rec | AggregateRating |
review |
Rec | Review objects |
Organization
Triggers: knowledge panel data, logo in search results.
| Property | Status | Notes |
|---|---|---|
name |
R | Organization name |
url |
R | Website URL |
logo |
R | ImageObject or URL (min 112x112px, square preferred) |
sameAs |
Rec | Array of social profile URLs |
contactPoint |
Rec | ContactPoint object |
address |
Rec | PostalAddress |
description |
Rec | Short description |
foundingDate |
Rec | ISO 8601 date |
BreadcrumbList
Triggers: breadcrumb trail in search results replacing the URL.
| Property | Status | Notes |
|---|---|---|
itemListElement |
R | Array of ListItem objects |
ListItem.position |
R | Integer (1-indexed) |
ListItem.name |
R | Breadcrumb label |
ListItem.item |
R* | URL (*omit on last item) |
WebSite (with SearchAction for Sitelinks Search Box)
Triggers: sitelinks search box on branded queries.
| Property | Status | Notes |
|---|---|---|
url |
R | Homepage URL |
name |
Rec | Site name |
potentialAction |
R | SearchAction object |
SearchAction.target |
R | URL template with {search_term_string} |
SearchAction.query-input |
R | "required name=search_term_string" |
{
"@type": "WebSite",
"url": "https://example.com/",
"potentialAction": {
"@type": "SearchAction",
"target": "https://example.com/search?q={search_term_string}",
"query-input": "required name=search_term_string"
}
}
Event
Triggers: event rich result with date, location, ticket info.
| Property | Status | Notes |
|---|---|---|
name |
R | Event name |
startDate |
R | ISO 8601 datetime |
location |
R | Place or VirtualLocation |
location.name |
R | Venue name |
location.address |
R | PostalAddress |
endDate |
Rec | ISO 8601 datetime |
description |
Rec | Event description |
image |
Rec | Event image |
offers |
Rec | Offer with price/url/availability |
performer |
Rec | Person or Organization |
organizer |
Rec | Person or Organization |
eventStatus |
Rec | EventScheduled, EventCancelled, EventPostponed, etc. |
eventAttendanceMode |
Rec | OfflineEventAttendanceMode, OnlineEventAttendanceMode, MixedEventAttendanceMode |
Recipe
Triggers: recipe rich result with image, rating, cook time.
| Property | Status | Notes |
|---|---|---|
name |
R | Recipe name |
image |
R | Multiple images at different aspect ratios |
author |
R | Person or Organization |
datePublished |
Rec | ISO 8601 |
description |
Rec | Short description |
prepTime |
Rec | ISO 8601 duration |
cookTime |
Rec | ISO 8601 duration |
totalTime |
Rec | ISO 8601 duration |
recipeYield |
Rec | e.g., "4 servings" |
recipeIngredient |
Rec | Array of strings |
recipeInstructions |
R | Array of HowToStep objects |
nutrition |
Rec | NutritionInformation (calories) |
aggregateRating |
Rec | AggregateRating |
video |
Rec | VideoObject |
VideoObject
Triggers: video rich result with thumbnail, duration, upload date.
| Property | Status | Notes |
|---|---|---|
name |
R | Video title |
description |
R | Video description |
thumbnailUrl |
R | Thumbnail image URL |
uploadDate |
R | ISO 8601 date |
contentUrl |
Rec | Direct URL to video file |
embedUrl |
Rec | Embed URL |
duration |
Rec | ISO 8601 duration |
interactionStatistic |
Rec | View count |
Course
Triggers: course rich result in search and Google for Education.
| Property | Status | Notes |
|---|---|---|
name |
R | Course title |
description |
R | Course description |
provider |
R | Organization offering the course |
offers |
Rec | Offer with price |
courseCode |
Rec | Identifier |
hasCourseInstance |
Rec | CourseInstance with schedule |
SoftwareApplication
Triggers: software rich result with rating, price, OS.
| Property | Status | Notes |
|---|---|---|
name |
R | App name |
operatingSystem |
Rec | e.g., "Windows 10", "Android" |
applicationCategory |
Rec | e.g., "GameApplication", "BusinessApplication" |
offers |
R | Offer with price (use "0" for free) |
aggregateRating |
Rec | AggregateRating |
review |
Rec | Review objects |
Review
Triggers: review snippet with star rating.
| Property | Status | Notes |
|---|---|---|
itemReviewed |
R | The entity being reviewed (Product, LocalBusiness, etc.) |
author |
R | Person who wrote the review |
reviewRating |
R | Rating object with ratingValue |
reviewRating.bestRating |
Rec | Maximum rating value |
reviewRating.worstRating |
Rec | Minimum rating value |
datePublished |
Rec | ISO 8601 date |
reviewBody |
Rec | Full text of the review |
Dynamic Schema Generation Patterns
When building pages programmatically, generate schema from your data models:
Server-Side Rendering (Next.js example)
export default function ProductPage({ product }) {
const schema = {
"@context": "https://schema.org",
"@type": "Product",
"name": product.title,
"image": product.images,
"description": product.description,
"sku": product.sku,
"brand": { "@type": "Brand", "name": product.brand },
"offers": {
"@type": "Offer",
"price": product.price,
"priceCurrency": "USD",
"availability": product.inStock
? "https://schema.org/InStock"
: "https://schema.org/OutOfStock"
}
};
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
{/* Page content */}
</>
);
}
CMS Integration Pattern
For WordPress, Shopify, or headless CMS:
- Map CMS fields to schema properties in a template or plugin.
- Ensure price, availability, and rating data are pulled from the live data source.
- Use conditional logic to only output properties that have values.
Validation Approach
Step 1: Rich Results Test (Google)
- URL: https://search.google.com/test/rich-results
- Tests if your markup qualifies for rich results.
- Reports errors and warnings per schema type.
Step 2: Schema Markup Validator (Schema.org)
- URL: https://validator.schema.org/
- Validates against the full Schema.org vocabulary (broader than Google).
Step 3: Google Search Console
- Check Enhancements section for structured data reports.
- Monitor errors, warnings, and valid item counts.
- Review indexing of pages with structured data.
MCP Tool: Use extract_schema on any URL to pull all JSON-LD, Microdata, and RDFa. Use generate_schema with a target type to produce valid markup from page content.
Common Pitfalls
| Pitfall | Problem | Fix |
|---|---|---|
| Invisible content | Schema describes content not visible to users | Ensure every structured data property matches visible page content |
| Missing required fields | Google ignores incomplete markup | Always include all required properties per type |
Wrong @type |
Using a type Google does not support for rich results | Use only Google-documented types |
| Fake reviews | Schema includes fabricated ratings or reviews | Only mark up genuine, real user reviews |
| Outdated prices | Product schema shows old price | Dynamically generate schema from live data |
| Multiple conflicting types | Two Product schemas on one page with different data | Use one canonical schema per entity |
| Self-referencing issues | @id references that point nowhere |
Ensure every @id reference has a matching definition |
| Incorrect date format | Using MM/DD/YYYY instead of ISO 8601 |
Always use YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS+00:00 |
| HTTP image URLs | Images referenced over HTTP not HTTPS | Use HTTPS URLs for all images |
| Spam policy violations | Marking up content solely for SEO manipulation | Follow Google's structured data spam policies |
Related Skills
- seo-on-page-optimization -- for content and meta tag optimization
- seo-technical-audit -- for crawlability and indexing issues
- seo-mcp-tools-expert -- for detailed MCP tool usage
Key MCP Tools for Structured Data
| Tool | Use For |
|---|---|
extract_schema |
Extract existing structured data from any URL |
generate_schema |
Generate valid JSON-LD markup for a given page and type |
See SCHEMA_TEMPLATES.md for ready-to-use JSON-LD templates. See VALIDATION_RULES.md for Google's validation requirements. See RICH_RESULTS_GUIDE.md for which types trigger which rich results.
More from autom8minds/seo-skills
seo-technical-audit
Expert guide for technical SEO auditing. Use when checking crawlability, indexing issues, page speed, Core Web Vitals, mobile-friendliness, HTTPS configuration, robots.txt, XML sitemaps, canonical tags, hreflang, redirect chains, HTTP status codes, or diagnosing technical SEO problems.
22seo-off-page-backlinks
Expert guide for off-page SEO and backlink analysis. Use when analyzing backlink profiles, assessing domain authority, planning link building strategies, evaluating link quality, identifying toxic backlinks, understanding anchor text distribution, or performing competitor backlink analysis.
22seo-content-strategy
Expert guide for content-driven SEO strategy. Use when doing keyword research, planning content clusters, analyzing search intent, building topic authority, evaluating E-E-A-T signals, creating content briefs, or planning content calendars for SEO.
20seo-on-page-optimization
Expert guide for on-page SEO optimization. Use when analyzing meta tags, title tags, headings (H1-H6), content optimization, image alt text, internal linking, URL structure, or improving on-page SEO signals for any web page.
19seo-local-seo
Expert guide for local SEO optimization. Use when optimizing Google Business Profile, managing local citations, NAP consistency, local keyword targeting, review management, local pack ranking, local landing page optimization, or multi-location SEO strategy.
18seo-mcp-tools-expert
Expert guide for using seo-mcp MCP tools effectively. Use when analyzing web pages, running SEO audits, checking Core Web Vitals, generating schema markup, analyzing backlinks, researching keywords, or using any seo-mcp tool. Provides tool selection guidance, parameter formats, and recommended workflows.
18