Adsentry
IT EN
Sign in Sign up free
Italiano English
Sign in Sign up free
SCHEMA.ORG • JSON-LD • MERCHANT CENTER • SHOPPING

schema.org Product structured data:
common errors and practical fixes

Structured data is the "contract" between your product page and Google. When Product schema is incomplete, duplicated or inconsistent with the product feed, Merchant Center generates warnings, disapprovals or simply ignores your markup. This guide covers plugin conflicts, duplicated Offer blocks, wrong price/availability, missing brand/GTIN and a validation workflow that actually works.

Reading ~12 min Updated March 2026 Technical level: intermediate
In this guide you'll learn:
🔍 How Merchant Center uses structured data to validate your feed and when it becomes authoritative
⚠️ Most common Product schema errors: duplicated Offers, missing brand/GTIN, wrong availability
🧩 Plugin conflicts and how to resolve them without breaking your theme or SEO stack
A practical validation workflow with tools, tests and a pre-deployment checklist
Key terms (glossary)

Why Product structured data matters for Merchant Center

Product structured data is not just for rich snippets. Google Merchant Center uses it as a secondary validation source to verify that your product feed matches what users see on the landing page.

When feed, page and structured data are aligned, you get:

  • Faster approval cycles and fewer manual reviews
  • Lower risk of price/availability mismatch disapprovals
  • Better rich results eligibility (product snippets, reviews, ratings)
  • More accurate product matching across merchants (via GTIN/brand)
Rule of thumb: if your feed says price: 299.00 but your JSON-LD declares price: 349.00, Merchant Center will likely flag a mismatch — even if the visible page shows 299.00.

Common errors overview (and how to spot them)

Most Product schema issues fall into a few recurring patterns. Spotting the pattern early saves hours of debugging.

🔄
Duplicated Product/Offer blocks
Theme + SEO plugin + ecommerce plugin each inject their own JSON-LD. Google reads the first valid one — which may not be yours.
💰
Price/availability mismatch
JSON-LD shows static values while the page updates dynamically via JavaScript or caching layers.
🏷️
Missing brand/GTIN/MPN
Required identifiers omitted or placed in the wrong property path, reducing product matching quality.
🎨
Images array malformed
Using a string instead of an array, or including non-HTTPS URLs, causing validation failures.
🧩
Variants not grouped correctly
Each variant has its own Product object without proper isVariantOf or shared productGroupID.
🌍
Currency/locale inconsistencies
priceCurrency differs from page context or feed, especially with multi-currency setups.
Pro tip: always view the raw page source (Ctrl+U) to inspect JSON-LD. Browser dev tools may show dynamically injected markup that Googlebot never sees.

Plugin conflicts and duplicated markup

On platforms like WordPress/WooCommerce or Shopify, multiple layers can inject structured data: theme, ecommerce core, SEO plugins, schema-specific apps. The result is often multiple @type: "Product" blocks with conflicting values.

How to detect duplicates
View page source → search for application/ld+json. Count occurrences of "@type": "Product". If >1, check which one contains your actual product data.
Resolution strategies
Disable schema output in all but one source (preferably your ecommerce plugin). Use filters/hooks to suppress theme-generated markup. For Shopify, review app settings and theme.liquid injections.
🛠️ Quick fix workflow for duplicates
  1. Identify all sources injecting JSON-LD (theme, plugins, apps).
  2. Temporarily disable all but the most reliable source.
  3. Validate with Rich Results Test and Merchant Center diagnostics.
  4. Re-enable sources one by one, testing after each change.
  5. Document the final configuration to prevent regression.

Offer structure: price, availability, currency

The Offer nested object is where most validation failures occur. Merchant Center compares these values against your feed and visible page.

Property Required format Common mistake Fix
price Number (no currency symbol) String with symbol: "€29.99" Use numeric: 29.99
priceCurrency ISO 4217 code (e.g., EUR) Using symbol or locale name Always use 3-letter code
availability Schema.org URL enum Custom strings like "In Stock" Use https://schema.org/InStock
url Canonical product URL Variant URL with tracking params Strip UTM, use clean canonical
priceValidUntil ISO 8601 date (optional) Missing on time-limited offers Add when using sale_price logic
If you use dynamic pricing (geo, membership, coupons), ensure JSON-LD reflects the default public price — not a personalized value. Merchant Center expects a stable, non-personalized baseline.

Product identity: brand, GTIN, MPN, condition

These properties enable Google to match your product across merchants, improve Shopping ad relevance and reduce disapprovals for "missing identifiers".

🏷️ Required when applicable
  • brand.name: Official brand name (not your store name)
  • gtin, gtin8, gtin12, gtin13, gtin14: Use the correct format for your barcode
  • mpn: Manufacturer Part Number when GTIN unavailable
  • condition: NewCondition, UsedCondition, RefurbishedCondition
⚠️ Common pitfalls
  • Using store name as brand for manufacturer products
  • Inventing GTIN values instead of omitting the field
  • Placing identifiers at Product level instead of Offer level (or vice versa)
  • Missing condition on used/refurbished items
For variants, each variant should have its own GTIN/MPN if they differ. Don't reuse the parent product's identifier for all children unless they truly share it.

Variants and item_group_id in structured data

Structured data for variants is more complex than the feed. Google supports two approaches: separate Product objects per variant, or a single Product with variant properties. Consistency with your feed is key.

01
Separate Product per variant (recommended for Shopping)
Each variant URL has its own JSON-LD with unique @id, matching the feed item_id. Use isVariantOf or shared productGroupID to signal grouping.
02
Single Product with hasVariant array
One Product object containing a hasVariant array of child Products. Useful for configurators, but harder to keep synchronized with feed.
03
Avoid mixing strategies
Don't use separate Products on some pages and hasVariant on others. Pick one pattern per catalog and apply consistently.
04
Sync variant identifiers
Ensure each variant's GTIN/MPN/brand in JSON-LD matches the feed exactly. Mismatches here cause product matching failures.
Minimal valid variant JSON-LD example
{
  "@context": "https://schema.org",
  "@type": "Product",
  "@id": "https://example.com/product/123?variant=blue",
  "name": "Wireless Headphones Pro",
  "brand": { "@type": "Brand", "name": "AudioTech" },
  "gtin13": "0123456789012",
  "color": "Blue",
  "offers": {
    "@type": "Offer",
    "price": "149.99",
    "priceCurrency": "EUR",
    "availability": "https://schema.org/InStock",
    "url": "https://example.com/product/123?variant=blue"
  },
  "isVariantOf": {
    "@type": "ProductGroup",
    "productGroupID": "HEADPHONES-PRO-2024"
  }
}

Images in structured data: requirements and pitfalls

The image property in Product schema must follow the same requirements as your Merchant Center feed. Inconsistencies here can trigger image-related disapprovals.

  • Format: Use an array of strings (even for a single image): "image": ["https://…"]
  • URLs: Must be absolute, HTTPS, and publicly accessible (no auth, no hotlink protection)
  • Variant alignment: The image in JSON-LD should match the variant shown on the page and in the feed
  • No promotional overlays: Watermarks, "sale" badges or text overlays violate Google policies
If your page uses a gallery with multiple images, include the primary product image first in the image array. Additional images can follow, but the first one is the one Google typically uses for validation.

Testing and validation workflow (step-by-step)

Don't rely on a single tool. Use a layered approach to catch issues before they reach production.

01
Raw source inspection
View page source (Ctrl+U) and search for application/ld+json. Confirm only one valid Product block exists and values match expectations.
02
Rich Results Test
Use Google's Rich Results Test to validate syntax and eligible rich result types. Note warnings vs errors.
03
Merchant Center diagnostics
In Merchant Center, check the product's "Diagnostics" tab for structured data warnings. Compare feed values vs page vs JSON-LD.
04
Cross-browser/network test
Test from incognito mode and a different network (e.g., mobile hotspot) to rule out cache/CDN or geo-personalization issues.
05
Variant sampling
Test at least 3 representative variants (different price, stock, color) to ensure JSON-LD updates correctly with variant selection.
06
Automated regression check
Add a simple script or CI check that parses JSON-LD and asserts critical fields (price, availability, brand) match expected values.
Never skip step 1. Browser dev tools may show dynamically injected JSON-LD that Googlebot never receives. Always validate the raw HTML source.

Pre-deployment checklist (fast pass)

Run this checklist before pushing schema changes to production — especially after theme updates, plugin installations or feed modifications.

Syntax & Structure
  • Only one @type: "Product" block per page
  • Valid JSON (no trailing commas, proper escaping)
  • @context and @type present
  • offers is an object or array of objects
  • All URLs are absolute and HTTPS
🎯 Content Alignment
  • Price/availability match visible page and feed
  • Brand/GTIN/MPN match feed identifiers exactly
  • Condition explicitly declared (new/used/refurbished)
  • Variant URLs and identifiers are unique and consistent
  • Images array contains valid, policy-compliant URLs

Want to detect structured data issues automatically before they impact Merchant Center?

Generate a report: duplicated markup, price/availability mismatches, missing identifiers, and variant consistency — all in one pre-deployment check.