Schema.org Structured Data for Products — Complete Guide with Examples
Detailed guide to Schema.org structured data markup for online stores: JSON-LD, required fields, examples, validation, common mistakes, and recommendations. Everything you need for rich product snippets in search results.
📖 Table of Contents
- What is Schema.org and Why You Need It
- Which Markup Format to Use
- Required Fields for a Product Card
- Full List of Recommended Fields
- Simple JSON-LD Example (Minimum)
- Full Product Markup (GTIN, brand, SKU, rating, reviews)
- Variant Products (size/color)
- BreadcrumbList
- Product Rating (aggregateRating)
- Customer Reviews (review)
- Validation Tools
- Best Practices and Recommendations
- Common Errors and How to Fix Them
- Template for Dynamic Insertion
- Frequently Asked Questions (FAQ)
1. What is Schema.org and Why You Need It
Schema.org is a vocabulary (vendor-neutral schema) for structured data, supported by major search engines (Google, Yandex, Bing, Yahoo). Markup helps search engines correctly understand the content of a product card and can lead to rich snippets (price, availability, rating, reviews, photos), as well as correct display in social networks via Open Graph and Twitter Cards.
Structured data is a standardized format for transmitting information about a page and its content. Search engines use this data to improve search results: product snippets with price and availability, star ratings, breadcrumbs, and much more.
Official links:
2. Which Markup Format to Use
Google recommends JSON-LD (JavaScript Object Notation for Linked Data). This format does not interfere with the DOM, is easy to insert server-side, and can be dynamically generated from database data. JSON-LD is a <script> block with type application/ld+json placed in the <head> or <body> of the page.
Existing markup formats:
- JSON-LD (recommended) — separate script block, does not affect layout
- Microdata — attributes in HTML tags (itemscope, itemtype, itemprop)
- RDFa — extended attributes for data linking
For an online store, choose JSON-LD — it is the most flexible and well-supported format.
3. Required Fields for a Proper Product Card
Minimum set of fields necessary for correct Google processing and rich snippet display:
- name — product name
- image — at least one image (URL)
- description — brief description (1-2 sentences)
- offers.price — price (as a number, without currency symbol)
- offers.priceCurrency — currency (ISO 4217, e.g., UAH, USD, EUR)
- offers.availability — availability (full URL from schema.org, e.g.,
https://schema.org/InStock) - offers.url — product page URL (canonical)
4. Full List of Recommended Fields
- sku — SKU (internal product code)
- mpn — manufacturer part number
- gtin8 / gtin12 / gtin13 / gtin14 — barcode (GTIN-8, GTIN-12, GTIN-13, GTIN-14)
- brand — brand (Brand object with name field)
- category — product category
- color, material, size, weight — physical characteristics
- aggregateRating — aggregate rating (AggregateRating)
- review — reviews (Review array)
- itemCondition — product condition (NewCondition, UsedCondition, etc.)
- additionalProperty — custom properties (PropertyValue)
- shippingDetails / OfferShippingDetails — shipping terms and cost
- seller — seller organization (Organization)
- offers.priceValidUntil — price expiration date
5. Simple Working JSON-LD Example (Minimum)
Basic product markup example with required fields:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Wireless Headphones X100",
"image": "https://site.com/images/headphones-x100.jpg",
"description": "Wireless headphones with noise cancellation.",
"offers": {
"@type": "Offer",
"url": "https://site.com/product/headphones-x100",
"priceCurrency": "UAH",
"price": "2499",
"availability": "https://schema.org/InStock"
}
}
</script>
Important: price should be sent as a number or digit string (without currency symbol). availability should use the full URL from schema.org (e.g., https://schema.org/InStock).
6. Full Product Markup (GTIN, brand, SKU, rating, reviews)
Below is extended markup with many fields: GTIN, brand, SKU, multiple images, aggregateRating, review, additionalProperty, shippingDetails, seller. This is the most complete example that can be adapted for any online store.
<script type="application/ld+json">
{
"@context": "https://schema.org/",
"@type": "Product",
"name": "Xiaomi Mi Band 7",
"image": [
"https://site.com/upload/mi-band-7-1.webp",
"https://site.com/upload/mi-band-7-2.webp"
],
"description": "Fitness tracker with AMOLED display and heart rate monitor.",
"sku": "MI-BAND-7-BLACK",
"mpn": "MB7-2025",
"gtin13": "6954176850021",
"brand": {
"@type": "Brand",
"name": "Xiaomi"
},
"additionalProperty": [
{
"@type": "PropertyValue",
"name": "Color",
"value": "Black"
},
{
"@type": "PropertyValue",
"name": "Material",
"value": "Silicone, metal"
}
],
"offers": {
"@type": "Offer",
"url": "https://site.com/product/mi-band-7/",
"priceCurrency": "UAH",
"price": "1499",
"priceValidUntil": "2026-12-31",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition",
"seller": {
"@type": "Organization",
"name": "BooStore.pro"
},
"shippingDetails": {
"@type": "OfferShippingDetails",
"shippingRate": {
"@type": "MonetaryAmount",
"value": "50"
}
}
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.8",
"reviewCount": "238"
},
"review": [
{
"@type": "Review",
"author": "Olena",
"datePublished": "2025-02-10",
"reviewBody": "Great band, works smoothly!",
"reviewRating": {
"@type": "Rating",
"ratingValue": "5"
}
}
]
}
</script>
This example shows: basic product information, characteristics via additionalProperty, detailed offer information (price, currency, availability, condition, seller, shipping), rating and reviews.
Product type — the main Schema.org type for describing a product. Contains name, description, images, attributes (brand, GTIN, SKU) and nested types Offer, AggregateRating, Review.
Offer type — description of a commercial offer: price, currency, availability, condition, shipping terms, seller.
AggregateRating type — aggregate product rating based on all reviews.
Review type — individual customer review with author, date, text, and rating.
BreadcrumbList type — navigation chain (breadcrumbs) showing the path from the home page to the current product.
7. Variant Products (size/color) — Approaches
There are two common approaches for marking up products with variants (color, size, material):
- One Product + offers array — if all variants are on one page. Each Offer contains its own price, availability, and variant attributes.
- Multiple Products — if each variant has its own page/URL.
Example: Product with two Offers (different colors, same page):
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Classic T-shirt",
"image": ["https://site.com/img/tshirt-red.jpg"],
"description": "Classic cotton t-shirt",
"sku": "TSHIRT-001",
"brand": {"@type": "Brand", "name": "BrandCo"},
"offers": [
{
"@type": "Offer",
"sku": "TSHIRT-001-RED",
"price": "599",
"priceCurrency": "UAH",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition"
},
{
"@type": "Offer",
"sku": "TSHIRT-001-BLUE",
"price": "599",
"priceCurrency": "UAH",
"availability": "https://schema.org/OutOfStock",
"itemCondition": "https://schema.org/NewCondition"
}
]
}
</script>
When using an offers array, each element must contain its own @type ("Offer"), price, currency, and availability status.
8. BreadcrumbList — Navigation
Breadcrumbs help search engines show site structure in snippets and improve user navigation. It is recommended to place BreadcrumbList on every product page together with Product.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://site.com/"
},
{
"@type": "ListItem",
"position": 2,
"name": "Category: Bracelets",
"item": "https://site.com/category/bracelets"
},
{
"@type": "ListItem",
"position": 3,
"name": "Xiaomi Mi Band 7",
"item": "https://site.com/product/mi-band-7/"
}
]
}
</script>
Each element of the itemListElement array is an object of type ListItem with fields position (sequence number), name (title), and item (URL).
9. Product Rating (aggregateRating)
Rating allows displaying the average product rating and review count in rich snippets. This increases user trust and CTR from search results.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Wireless Headphones X100",
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.7",
"reviewCount": "154"
}
}
</script>
Recommendation: ratingValue — number with a decimal point (e.g., 4.7), reviewCount — integer. Do not provide fake ratings — Google may impose penalties.
Additionally, you can specify bestRating (maximum rating, default 5) and worstRating (minimum rating, default 1).
10. Customer Reviews (review)
Reviews allow detailed descriptions of user opinions about a product, including the author, publication date, text, and rating. Each review is a separate Review object in an array.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Wireless Headphones X100",
"review": [
{
"@type": "Review",
"author": "Olena",
"datePublished": "2025-05-10",
"reviewBody": "Very comfortable headphones, great sound!",
"reviewRating": {
"@type": "Rating",
"ratingValue": "5"
}
},
{
"@type": "Review",
"author": "Ihor",
"datePublished": "2025-05-12",
"reviewBody": "Good, but a bit bulky.",
"reviewRating": {
"@type": "Rating",
"ratingValue": "4"
}
}
]
}
</script>
Each review includes the author (author), publication date (datePublished), text (reviewBody), and rating (reviewRating). You can add any number of reviews, but only real ones.
11. Validation and Testing Tools
- Google Rich Results Test — quickly shows errors and warnings for rich snippets. Allows checking a URL or pasting code manually.
- Schema.org Validator — detailed schema validation from the Schema.org consortium.
- Google Search Console — in the "Enhancements" → "Products" section you can track errors after publication.
- Yandex Webmaster — similar tool for checking structured data.
12. Best Practices and Recommendations
- Generate JSON-LD server-side from the database — price, availability, SKU, images should be synchronized with page content.
- Do not use test or fake data in production.
- If showing multiple prices (promotions, discounts), use
priceValidUntiland specify the current price inoffers.price. - Specify
priceCurrencyin ISO 4217 format (UAH, USD, EUR, RUB). - Do not create conflicting markup — the price in JSON-LD must match the visible price on the page.
- For international stores, specify locales, seller address, and shippingDetails.
- Use
BreadcrumbListandProducttogether — this improves navigation in search results. - Add at least one image with a correct URL (accessible for indexing).
- Regularly check markup via Google Rich Results Test and Search Console.
- Learn more about improving website SEO in the article: How to Improve Website SEO — Guide.
- For analytics and eCommerce tracking setup, use the material: GA4 and eCommerce Analytics Setup.
13. Common Errors and How to Fix Them
- Error: price contains currency symbol (
2499 грн) — fix: store and output only digits, specify currency inpriceCurrency. - Error: missing image or broken link — fix: add at least 1 correct accessible image URL.
- Error: mismatched URLs — fix: use the exact current product page URL in
offers.url. - Error: review or aggregateRating array contains fake data — fix: show only real reviews and ratings.
- Error: incorrect availability format — fix: use the full URL format like
https://schema.org/InStock. - Error: duplicate markup (multiple JSON-LD blocks with conflicting data) — fix: merge everything into one block.
- Error: missing breadcrumbs on product pages — fix: add BreadcrumbList to improve navigation in search results.
14. Template for Dynamic Insertion (PHP/Twig/Smarty)
Below is a template where variables are replaced by the server. Substitute your values instead of %VAR%.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "%PRODUCT_NAME%",
"image": [%IMAGE_LIST%],
"description": "%SHORT_DESCRIPTION%",
"sku": "%SKU%",
"brand": {"@type": "Brand", "name": "%BRAND%"},
"offers": {
"@type": "Offer",
"url": "%PRODUCT_URL%",
"priceCurrency": "%CURRENCY%",
"price": "%PRICE%",
"priceValidUntil": "%PRICE_VALID_UNTIL%",
"availability": "%AVAILABILITY%"
}
}
</script>
❓ Frequently Asked Questions (FAQ)
What is Schema.org and how does it benefit an online store?
Schema.org is a structured data vocabulary supported by Google, Yandex, Bing, and Yahoo. Markup helps search engines understand page content and display rich snippets (price, availability, rating, reviews). This increases CTR from search and improves product visibility.
Which markup format is best to use?
Google recommends JSON-LD. It does not affect layout, is easily generated server-side, supports all Schema.org types, and does not conflict with HTML markup. Microdata and RDFa are considered outdated approaches for new projects.
Is it mandatory to add all fields from the guide?
No. For a correct rich snippet, the mandatory minimum is sufficient: name, image, description, offers.price, offers.priceCurrency, offers.availability, offers.url. All other fields are recommendations that expand display capabilities.
Can Schema.org be used for products with variants (color, size)?
Yes. If variants are on one page — use an offers array. If on different pages — create a separate Product for each variant. In both cases, Google processes the markup correctly.
How to check if the markup on my site is working correctly?
Use Google Rich Results Test (search.google.com/test/rich-results) — paste the URL or markup code. After publication, track errors in Google Search Console under "Enhancements" → "Products".
Do I need to add markup manually if the site is on BooStore.pro?
No. BooStore.pro already contains all basic microdata (Product, Offer, Price, Availability, BreadcrumbList, ImageObject, AggregateRating, Review). Additional fields (GTIN, MPN, brand) can be added when needed through the platform settings.