Guide : ProductGroup Schema
Comment utiliser ProductGroup schema to groupe product variants (size, color, material) with hasVariant, variesBy, and productGroupID — plus the item_group_id difference and pourquoi Bing doesn't prise en charge it.
Langues
ProductGroup schema wraps a définir of Product variants — a shirt's sizes and colors — sous un parent so Google understands they're options of the même item, pas separate products. It's additive: every variant is encore a complet Product with its propre sku/gtin, price, and availability, and ProductGroup ties les ensemble with hasVariant (nested, single-page sites), variesBy (qui attributes differ), and productGroupID (the parent sku). The unique la plupart courant mistake is writing variesBy as plain strings — it doit utiliser complet schema.org URLs comme https://schema.org/color; in my testing the JSON-LD encore validates but the grouping doesn't trigger (Google doesn't document que échec mode, so vérifier it yourself). Two plus traps: productGroupID (on-page schema) n’est pas Merchant Center's item_group_id (a product-feed attribute) — separate systems, nothing auto-syncs les, so utiliser matching valeurs deliberately; and Bing doesn't consume ProductGroup markup at tout (per Microsoft's Fabrice Canel, Sept 2024, a reported statement, pas a Microsoft doc). My rule with tout schema holds ici: implement it parce que it earns vous a search fonctionnalité, pas parce que plus markup is automatically meilleur — it aids understanding and merchant-listing eligibility, it doesn't faire a variant rank.
TL;DR — ProductGroup schema is code que indique Google “tout ces variations — the petit green shirt, the grand blue un — are the même product in différent options, pas separate products.” Chaque variation encore obtient its propre product markup; ProductGroup simplement wraps les ensemble. It fait pas replace product markup, and it fait pas faire a variant rank plus élevé — it helps Google comprendre votre catalog and peut faire votre listings eligible to montrer variant info.
Ce que ProductGroup schema is
Si vous sell a coat in three colors and five sizes, that’s un coat sold in 15 combinations. To a moteur de recherche, 15 near-identical product pages peut regarder comme 15 unrelated products unless vous tell it sinon.
ProductGroup schema is the données structurées que fait the telling. It sits ci-dessus votre individual product listings and dit “ces belong ensemble — they’re the même item in différent options.” Google ajouté prise en charge pour it in February 2024.
Evidence for this claim Schema.org ProductGroup represents a group of products that vary only in defined characteristics. Scope: Schema.org vocabulary; Google adds its own merchant-listing requirements. Confidence: high · Verified: Schema.org: ProductGroupThink of it as a parent folder:
- The parent is the
ProductGroup— “Wool winter coat.” - The children are the individual
Productvariants — chaque color/size combo, with its propre price, photo, stock status, and unique ID.
The important partie: it’s additive, pas a replacement
Ce trips up almost everyone the premier temps. ProductGroup fait pas replace votre
product markup. Every variant is encore a complet Product — it garde its propre SKU,
price, image, and availability. ProductGroup is a wrapper que ties ceux Products
ensemble. You’re ajout markup, pas swapping it out.
Ce que it fait pour vous
Marking up votre variants ce façon rend votre products eligible to montrer variant information in Google’s shopping/merchant listings — the “also comes in these colors” kind of afficher. As with tout schema, “eligible” is the clé word: it’s pas a ranking boost, and it’s jamais guaranteed. It helps Google comprendre votre products, qui is the point. Evidence for this claim Google supports ProductGroup with associated variant properties to describe product variants for merchant listings. Scope: Google Search product-variant documentation; eligibility is not a ranking promise. Confidence: high · Verified: Google: Product variants
Two choses to know avant vous go deeper
- Bing doesn’t lire ProductGroup schema (as of the latest word from Microsoft). So ce is mainly a Google fonctionnalité. Plus on que in the Avancé tab.
- Ce is the schema/code side of variants. Si a donné variant devrait même obtenir its propre page in the premier placer is a separate strategy question — I cover que decision (and the platform differences) in the product variant SEO guide.
Vouloir the complet version — the three core properties, the complet schema.org URL rule pour
variesBy, how productGroupID differs from Merchant Center’s item_group_id, a
complet JSON-LD exemple, and the Erreurs fréquentes? Switch to the Avancé tab.
TL;DR —
ProductGroup(Google’s Feb 2024 addition) wraps variantProductobjects sous un parent so Google understands “same item, different options.” It’s additive — chaque variant garde completProductmarkup (sku/gtin,offers,image,availability). Lien les withhasVariant(nested, single-page sites) orisVariantOf+inProductGroupWithID(flat, multi-page sites); declare the varying axes withvariesBy— qui doit utiliser complet schema.org URLs (https://schema.org/color), pas plain strings (the #1 implementation mistake — validates soit façon, but grouping quietly won’t trigger En pratique, qui isn’t a documented Google behavior); and share aproductGroupID(plain text parent sku, pas une URL).productGroupIDis pas Merchant Center’sitem_group_id— separate systems, nothing auto-syncs les, so utiliser matching valeurs on objectif. Seulementnameis strictly requis. And Bing doesn’t consume ProductGroup at tout (Fabrice Canel, Sept 2024). Schema aids understanding and merchant-listing eligibility — it isn’t a ranking factor.
Où ce sits
Ce is the schema-implementation deep dive — the complet JSON-LD, the property-by-property
référence, the Merchant Center reconciliation, and the troubleshooting. The upstream
strategy question — devrait a donné variant obtenir its propre indexable URL at tout, and how
do Shopify/WooCommerce/BigCommerce/Magento differ — is its propre topic (product variant
SEO). Ce article assumes you’ve déjà made ceux calls and now besoin the markup
correct. It aussi sits sous the broader balisage de données structurées and données structurées hubs, and it’s
a sibling of Product schema (pour a unique, non-varying item, plain Product is tout vous
besoin — ProductGroup is pour a family of variants).
Pourquoi ProductGroup exists
Google’s propre framing: “To aider Google meilleur comprendre qui products are variations of the même parent product, utiliser the ProductGroup class with associated properties variesBy, hasVariant, and productGroupID to groupe tel variants ensemble.” The motivating categories are exactly ce que you’d expect — “apparel, shoes, furniture, electronic devices, and luggage… sold in différent variations (Par exemple various sizes, colors, materials, or patterns).”
Evidence for this claim Google documents ProductGroup relationships including variesBy, hasVariant, productGroupID, and inverse variant references. Scope: Google Search product-variant requirements; use the pattern matching the site's URL architecture. Confidence: high · Verified: Google: Product variantsThe payoff is eligibility, pas ranking: “Ajout ce markup aussi rend votre products eligible pour afficher with variant information in merchant listing experiences.” Même caveat que s’applique to tout données structurées — it aids understanding and rich-result eligibility, it doesn’t déplacer vous up le résultats.
It’s additive — ce is the mental model que empêche la plupart mistakes
ProductGroup wraps Product; it doesn’t replace it. The ProductGroup object
itself isn’t offered pour sale — it has aucun unique price, parce que “the coat” costs
différent amounts selon qui variant vous buy. Every variant remains a complet
Product with its propre sku/gtin, image, offers, and availability. Si vous
trouver yourself trying to put a unique offers/price on the ProductGroup, arrêter —
that’s the tell que you’ve confused the wrapper pour the chose being sold.
The three core properties
A ProductGroup named Wool winter coat declares productGroupID 44E01 and variesBy values using full schema.org URLs for color and size. It connects to green small, green large, and blue small Product variants. Every variant keeps a unique SKU, Offer, image, and availability. The connection can use hasVariant in a nested model or isVariantOf in a flat model.
© Patrick Stox LLC · CC BY 4.0 ·
hasVariant (and isVariantOf)
hasVariant is “a nested Product property que is un of the variants of the
ProductGroup property… A ProductGroup typically has multiple nested variant Product
properties.” Vous put votre variant Product objects à l’intérieur the groupe.
The inverse aussi exists: “a variant Product property peut référence back to its parent ProductGroup en utilisant the isVariantOf property on the Product property.” Qui un vous utiliser dépend on votre site’s Structure d’URL (suivant section).
variesBy — complet schema.org URLs, pas plain strings
variesBy declares “aspects by qui the variants in the ProductGroup vary (pour
exemple, size or color).” The critical detail, verbatim from Google’s properties
table: “Référence ces variant-identifying properties via leur complet Schema.org
URL.”
Que signifie:
"variesBy": ["https://schema.org/size", "https://schema.org/color"]pas "variesBy": ["size", "color"]. Ce is the unique la plupart courant implementation
mistake in ce entier topic. What’s documented: Google’s property table exige the
complet URL formulaire — nothing plus spécifique que que. What’s pas documented: Google
doesn’t publish ce que se produit si vous skip it. In my propre testing and consistent with
autre practitioners’ reports, the JSON-LD encore passes syntax validation and nothing
errors out, but the enhanced grouping behavior doesn’t trigger — treat que as a strongly
observed pattern, pas an official Google statement, and vérifier it contre votre propre
markup plutôt que taking it as gospel.
The pris en charge dimensions are https://schema.org/color, https://schema.org/size,
https://schema.org/suggestedAge, https://schema.org/suggestedGender,
https://schema.org/material, and https://schema.org/pattern.
productGroupID — plain text, and pas item_group_id
productGroupID is “the identifier of the product groupe (aussi connu as the parent
sku). Ce identifier doit be provided pour the ProductGroup property or, alternatively,
en utilisant inProductGroupWithID property pour variants.” It’s a plain text identifier
— Google’s propre exemple is "44E01" — pas une URL. Don’t over-generalize the
variesBy “full schema.org URL” rule to ce field; they’re différent rules pour
différent jobs.
Un hard constraint: “Si vous provide the identifier pour les deux the ProductGroup property and its variant Product properties, ils doit match.” Google’s docs state the requirement but don’t document ce que se produit quand it’s violated. Fondé on my propre testing (pas a documented Google échec mode), a typo or a template/environment leak que changements the valeur on un variant page drops que variant out of the groupe with aucun visible error — lune page simplement arrête being lire as partie of the family. Treat que as observed behavior worth verifying yourself, pas an official spec.
Two implementation patterns: nested vs. flat
Votre Structure d’URL decides qui pattern vous utiliser.
Single-page sites — nested (hasVariant). Tout variants are selectable on un URL
(via dropdowns/swatches). “Pour single-page websites seulement: L’URL (sans variant
selectors) où the ProductGroup property is located.” There’s exactly un canonical
URL pour the whole groupe, and vous nest every variant Product à l’intérieur the ProductGroup
via hasVariant.
Multi-page sites — flat (isVariantOf + inProductGroupWithID). Chaque variant has
its propre dedicated URL. Ici “ce doesn’t appliquer since là is aucun unique URL canonique
representing the ProductGroup property.” Chaque page doit carry complet, self-contained
markup pour the entities défini on que page — vous don’t share un block à travers pages.
Every variant Product références its parent with isVariantOf, and the groupe lien is
carried by inProductGroupWithID: “Chaque product groupe doit have a unique ID in its
corresponding données structurées markup, specified with the inProductGroupWithID property.”
Soit façon, “Chaque variant doit have a unique ID in its corresponding données structurées markup (Par exemple, en utilisant the sku or gtin properties).”
Un plus requirement personnes miss on multi-page setups: variants doit be reachable by a distinct, preselectable URL. Google: “Le site doit have the ability to preselect chaque variant directement with a distinct URL (en utilisant URL requête parameters), Par exemple https://www.example.com/winter_coat/size=small&color=green.” A variant que seulement apparaît après a client-side click, with aucun URL to point at, can’t be validated or indexé as its propre chose.
Requis vs. recommended
- Requis on
ProductGroup: simplementname(e.g.,"Wool winter coat"). - Recommended:
variesBy,hasVariant,productGroupID,brand,description,aggregateRating,review,hasAdultConsideration, and (single-page sites seulement)url.
Technically seulement name is requis — but variesBy and productGroupID are
functionally load-bearing. Skip les and the JSON-LD validates pendant que the grouping
behavior vous wanted jamais montre up. (aggregateRating and review ici are the même
types you’d utiliser standalone — voir the AggregateRating and Examiner schema deep dives.)
productGroupID vs. Merchant Center’s item_group_id — the reconciliation nobody explique
Ce is the confusion point que la plupart competitor content skips entirely, so it’s worth being precise.
productGroupIDis a schema.org / on-page données structurées field. It feeds organic Search’s understanding of lune page.item_group_idis a Google Merchant Center product-feed attribute. Merchant Center: “Utiliser the item groupe ID [item_group_id] attribute to groupe product variants in votre product données.” It feeds Shopping ads and free listings.
Ils are two separate systems, and Google fait pas automatically sync les. Meilleur pratique — and ce is echoed à travers the meilleur third-party implementation guides — is to utiliser the même identifier valeur pour les deux, so votre feed and votre markup agree on qui SKUs belong ensemble. A mismatch doesn’t necessarily break soit system outright, but it removes the reinforcing signal and peut produce inconsistent grouping entre Shopping surfaces and organic résultats enrichis.
(A footnote on casing: Merchant Center’s aider parfois writes productGroupId
lowercase-d où Search Central’s docs utiliser productGroupID. That’s a cosmetic
inconsistency in Google’s propre docs, pas a mistake on votre fin — follow Search Central’s
productGroupID in votre JSON-LD.)
The consistency discipline ici is the même un que governs canonicals and variant URLs généralement: votre signals devrait agree with chaque autre, or you’re handing Google a raison to guess.
Bing ne fait pas prise en charge ProductGroup
Here’s the differentiator la plupart guides obtenir incorrect or omit: Bing ne fait pas currently
consume schema.org ProductGroup markup. Microsoft’s Fabrice Canel, responding
directement to a question à propos de si Bing supports schema.org/ProductGroup, said Bing
ne fait pas yet prise en charge it, but que it’s “on our radar” and the team is “closely
monitoring its adoption.” (Reported by Moteur de recherche Roundtable, covering a September
2024 exchange on X — a secondary report of a first-party statement, pas a Microsoft doc,
so treat it as tel.)
Bing’s Webmaster Outils structured-data aider is a generic overview of pris en charge formats
with aucun ProductGroup-, variesBy-, or productGroupID-spécifique content. Bing’s
Shopping variant grouping runs via a feed-side itemGroupId field in
Microsoft Advertising — the analog of Google’s item_group_id, pas on-page schema.
So: implement ProductGroup pour Google, and handle Bing Shopping variants via
the Microsoft Advertising feed, pas markup.
A remarque on dynamic markup
Google’s propre caution: “Be aware que dynamically-generated markup peut faire Shopping
crawls moins frequent and moins reliable, qui peut be an problème pour fast-changing content
comme product availability and price.” Si votre variant offers/availability are
JS-injected, weigh que contre server-rendering the markup pour the fields que modifier
souvent.
Validate avant vous ship
- Résultats enrichis Tester — checks eligibility and surfaces required-property errors pour the merchant-listing/variant experience.
- Balisage de données structurées Validator (schema.org) — validates the ProductGroup/Product types themselves, independent of Google fonctionnalités.
- Search Console — the merchant-listings/product-snippet enhancement reports montrer eligibility and errors at scale post-deploy; Inspection d’URL montre how a spécifique page was lire.
Remember ce que “valid” fait and doesn’t tell vous: a plain-string variesBy passes
validation and, in my testing, encore doesn’t trigger grouping. Validation catches syntax
and required-property gaps, pas ce kind of semantic échec (qui Google doesn’t
document soit façon) — pour ceux, vérifier by hand que votre variesBy valeurs are complet
URLs and votre productGroupID matches à travers the groupe.
Pour où ce fits the bigger picture, voir the broader données structurées and schema markup hubs ce article lives sous.
AI summary
A condensed prendre on the Avancé version:
- Ce que c’est:
ProductGroup(Google, Feb 2024) wraps variantProductobjects sous un parent so Google understands “same item, different options” plutôt que unrelated products. Eligibility pour variant afficher in merchant listings — pas a ranking factor. - Additive, pas a replacement: every variant stays a complet
Product(sku/gtin,offers,image,availability);ProductGroupis the wrapper and isn’t sold on its propre (aucun unique price on the groupe). - Three core properties:
hasVariantnests variants (orisVariantOfpoints back up);variesBylistes the varying axes and doit utiliser complet schema.org URLs (https://schema.org/color, pas"color") — the #1 implementation mistake, and En pratique (pas something Google documents) it validates fine pendant que grouping quietly doesn’t trigger;productGroupIDis a plain text parent sku (pas une URL, e.g."44E01"), and si définir on les deux groupe and variants the valeurs doit match — Google documents the match rule but pas ce que se produit on a mismatch. - Two patterns: nested (
hasVariant, single-page sites, un URL canonique pour the groupe) vs. flat (isVariantOf+inProductGroupWithID, multi-page sites, complet self-contained markup par page). Variants besoin uniquesku/gtinand a distinct preselectable URL. - Requis vs. recommended: seulement
nameis requis;variesBy+productGroupIDare functionally essential même though technically recommended. productGroupID≠item_group_id: on-page schema (organic Search) vs. Merchant Center feed attribute (Shopping/free listings) — separate systems, nothing auto-syncs, utiliser matching valeurs on objectif.- Bing doesn’t prise en charge ProductGroup (Fabrice Canel, Sept 2024, via Moteur de recherche
Roundtable). Bing Shopping variants run via Microsoft Advertising’s feed-side
itemGroupId, pas markup. - Watch dynamic markup (moins reliable Shopping crawls pour price/availability).
Validate with Résultats enrichis Tester + schema.org Validator, but remember plain-string
variesByvalidates and encore fails.
Documentation officielle
Primary-source documentation pour ProductGroup and variant markup.
- Product variant données structurées (ProductGroup, Product) — the unique authoritative page:
ProductGroup,hasVariant,isVariantOf,variesBy,productGroupID, the complet schema.org URL rule, requis/recommended properties, and the single-page vs. multi-page rules. - Ajout données structurées prise en charge pour Product Variants (Feb 2024 blog) — the announcement que introduced the properties.
- Intro to Product données structurées — the general Product page (Product snippets / merchant listings). Remarque: it fait pas cover ProductGroup — that’s the separate page ci-dessus.
- Google Merchant Center — Item groupe ID [item_group_id] — the product-feed attribute pour grouping variants, and its schema.org cross-references.
Bing / Microsoft
- Bing Webmaster Outils — Marking up votre site with données structurées — a generic overview of pris en charge formats; aucun ProductGroup-,
variesBy-, orproductGroupID-spécifique content.
schema.org
- schema.org/ProductGroup — the vocabulary page: authoritative property liste and Product/Chose inheritance (aucun implementation exemples or Google-specific guidance).
Quotes from the source
On-the-record statements from Google (and reported statements from Microsoft). Où a page exposes the text, the lien is a deep lien que jumps to the quoted passage.
Google docs — objectif and eligibility
- “To help Google better understand which products are variations of the same parent product, use the ProductGroup class with associated properties variesBy, hasVariant, and productGroupID to group such variants together.” Jump to quote
- “Many types of products such as apparel, shoes, furniture, electronic devices, and luggage are sold in different variations (for example various sizes, colors, materials, or patterns).” Jump to quote
- “Adding this markup also makes your products eligible for display with variant information in merchant listing experiences.” Jump to quote
Google docs — the properties
variesBy: “Aspects by which the variants in the ProductGroup vary… Reference these variant-identifying properties through their full Schema.org URL.” Jump to quotehasVariant: “A nested Product property that is one of the variants of the ProductGroup property, if applicable. A ProductGroup typically has multiple nested variant Product properties.” Jump to quoteisVariantOf: “Alternatively, a variant Product property can reference back to its parent ProductGroup using the isVariantOf property on the Product property.” Jump to quoteproductGroupID: “The identifier of the product group (also known as the parent sku). This identifier must be provided for the ProductGroup property or, alternatively, using inProductGroupWithID property for variants.” Jump to quote- On matching IDs: “If you provide the identifier for both the ProductGroup property and its variant Product properties, they must match.” Jump to quote
Google docs — unique IDs and URLs
- “Each variant must have a unique ID in its corresponding structured data markup (for example, using the sku or gtin properties).” Jump to quote
- “The site must have the ability to preselect each variant directly with a distinct URL (using URL query parameters), for example https://www.example.com/winter_coat/size=small&color=green.” Jump to quote
- On dynamic markup: “Be aware that dynamically-generated markup can make Shopping crawls less frequent and less reliable, which can be an issue for fast-changing content like product availability and price.” Jump to quote
Google Merchant Center — item_group_id
- “Use the item group ID [item_group_id] attribute to group product variants in your product data.” Jump to quote
John Mueller, Google (via Moteur de recherche Roundtable’s verbatim reproduction of his Feb 2024 LinkedIn post)
- “Product variants in ecommerce are complicated - what do you do with t-shirts in different colors? Folks here Google worked hard to come up with structured data markup & support for it… The changes are also live in the Rich Results Testing tool and in the Search Console reports for these types.” Lire the coverage
Fabrice Canel, Microsoft Bing (reported, pas a first-party doc)
- Responding to si Bing supports
schema.org/ProductGroup, Canel said Bing fait pas yet prise en charge it, but que it’s “on our radar” and the team is “closely monitoring its adoption.” Coverage Relayed via Moteur de recherche Roundtable’s coverage of a September 2024 exchange on X; a secondary report of a first-party statement, pas a Microsoft documentation page.
A complet ProductGroup JSON-LD exemple
Google’s propre doc exemple is intentionally minimal — un variant, aucun offers. Here’s a
fuller, single-page (nested hasVariant) version with two variants, offers, gtin,
image, and brand — the shape you’d en réalité ship. Remarque variesBy uses complet
schema.org URLs, and productGroupID is a plain string.
{
"@context": "https://schema.org/",
"@type": "ProductGroup",
"name": "Wool winter coat",
"description": "A warm wool winter coat, available in several sizes and colors.",
"url": "https://www.example.com/winter-coat",
"brand": {
"@type": "Brand",
"name": "ExampleCo"
},
"productGroupID": "44E01",
"variesBy": [
"https://schema.org/size",
"https://schema.org/color"
],
"hasVariant": [
{
"@type": "Product",
"sku": "44E01-S-GRN",
"gtin": "0123456789012",
"name": "Wool winter coat, small, green",
"image": "https://www.example.com/photos/44E01-S-GRN.jpg",
"size": "small",
"color": "Green",
"offers": {
"@type": "Offer",
"url": "https://www.example.com/winter-coat?size=small&color=green",
"price": "119.99",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock"
}
},
{
"@type": "Product",
"sku": "44E01-L-BLU",
"gtin": "0123456789029",
"name": "Wool winter coat, large, blue",
"image": "https://www.example.com/photos/44E01-L-BLU.jpg",
"size": "large",
"color": "Blue",
"offers": {
"@type": "Offer",
"url": "https://www.example.com/winter-coat?size=large&color=blue",
"price": "119.99",
"priceCurrency": "USD",
"availability": "https://schema.org/OutOfStock"
}
}
]
}Choses to notice:
- The
ProductGrouphas aucunoffers/priceof its propre — price lives on chaque variant’sOffer, parce que the groupe isn’t a unique sellable chose. - Chaque variant carries a unique
sku(and ici agtin), its propreimage, its propreavailability, and thesize/colorvaleurs que match ce quevariesBydeclared. - Availability is per-variant — the petit green coat is
InStock, the grand blue unOutOfStock. That’s the correct façon to handle a partially-stocked groupe (voir the out-of-stock products guide pour how to signal ce sans dropping the variant).
The multi-page (flat) variant of the même setup
Si chaque variant lives on its propre URL, vous don’t nest — chaque page carries its propre
self-contained Product que points back up with isVariantOf and the shared groupe ID
via inProductGroupWithID:
{
"@context": "https://schema.org/",
"@type": "Product",
"sku": "44E01-S-GRN",
"gtin": "0123456789012",
"name": "Wool winter coat, small, green",
"image": "https://www.example.com/photos/44E01-S-GRN.jpg",
"size": "small",
"color": "Green",
"inProductGroupWithID": "44E01",
"isVariantOf": {
"@type": "ProductGroup",
"productGroupID": "44E01",
"variesBy": [
"https://schema.org/size",
"https://schema.org/color"
]
},
"offers": {
"@type": "Offer",
"url": "https://www.example.com/winter-coat/small-green",
"price": "119.99",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock"
}
}Every variant page repeats ce pattern with its propre IDs and offer, and the même
productGroupID ("44E01") ties les ensemble. Garder que ID identical à travers tout
variant pages and aligned with votre Merchant Center item_group_id.
Devrait vous utiliser ProductGroup, and qui pattern?
Walk the tree to land on the correct markup decision pour votre setup.
ProductGroup or plain Product — and nested or flat?
Courant ProductGroup mistakes
The traps, and what’s en réalité vrai:
| Mistake | Reality |
|---|---|
Treating ProductGroup as a replacement pour Product | It’s a wrapper/parent. Every variant is encore a complet Product with its propre sku/gtin, price, image, and availability. The ProductGroup itself isn’t offered pour sale — don’t put a unique offers/price on it. |
Writing variesBy as plain strings ("color", "size") | It doit utiliser complet schema.org URLs (https://schema.org/color). Plain strings réussir JSON-LD validation, and En pratique grouping doesn’t trigger (Google doesn’t document que spécifique échec, so vérifier it on votre propre markup) — the unique la plupart courant mistake in ce topic. |
Assuming productGroupID and Merchant Center’s item_group_id are the même auto-synced field | They’re separate systems — on-page schema (organic Search) vs. product feed (Shopping/free listings). Nothing syncs les; utiliser matching valeurs deliberately. |
Making productGroupID une URL | It’s a plain text identifier (parent sku), e.g. "44E01". Don’t over-apply the variesBy full-URL rule ici — différent field, différent rule. |
Shrugging off a productGroupID typo on un variant page | In multi-page setups, a mismatched ID drops que variant out of the groupe with aucun error thrown, in my testing — Google documents the match requirement but pas the mismatch behavior, so ce is observed, pas officially specified. |
| Marking up variants que have aucun distinct URL | Variants doit be preselectable via a distinct URL (requête params are fine). JS-only state changements with aucun URL can’t be validated or indexé as variants. |
| Assuming Bing reads ProductGroup comme Google fait | As of Sept 2024 (Fabrice Canel, via Moteur de recherche Roundtable), Bing fait pas consume ProductGroup markup. Bing Shopping variants run via Microsoft Advertising’s feed-side itemGroupId, pas on-page schema. |
| Expecting ProductGroup to améliorer rankings | It aids understanding and merchant-listing eligibility — it is pas a ranking factor. “Eligible” n’est pas “guaranteed,” and it’s certainly pas a boost. |
| Trusting “valid” to mean “working” | Validation catches syntax and required-property gaps, pas silent semantic échecs. Plain-string variesBy and mismatched IDs les deux validate and encore don’t fonctionner — vérifier les by hand. |
ProductGroup implementation checklist
Fonctionner via ce in order — chaque item maps to a spécifique gotcha covered ci-dessus.
- Decide votre pattern premier. Tout variants selectable on un URL → nested
(
hasVariant). Chaque variant on its propre URL → flat (isVariantOf+inProductGroupWithID). Don’t mix patterns on the même groupe. - Garder every variant a complet
Product. Chaque un encore has its propresku/gtin,image,offers, andavailability—ProductGroupjamais carries a uniquepriceof its propre. - Écrire
variesByas complet schema.org URLs, e.g.https://schema.org/colorandhttps://schema.org/size— pas"color"/"size". Ce is the #1 implementation mistake; it validates soit façon, and grouping quietly doesn’t trigger sans l’URL formulaire in my testing (pas something Google documents), so vérifier it by eye. - Définir
productGroupIDas a plain-text identifier (parent sku, e.g."44E01") — jamais une URL. Différent rule fromvariesBy; don’t conflate les. - Match
productGroupID(orinProductGroupWithID) à travers every variant. Google documents the match requirement but pas ce que se produit si it’s violated; in my testing, a typo on un variant page drops it from the groupe with aucun error. - Give every variant a unique ID via
skuorgtin. - Confirmer every variant has a distinct, preselectable URL (requête params are
fine, e.g.
?size=small&color=green). A JS-only state modifier with aucun URL can’t be validated or indexé as its propre variant. - Align
productGroupIDwith Merchant Center’sitem_group_id. They’re separate systems and nothing auto-syncs les — utiliser the même valeur on objectif. - Server-render fast-changing fields (
price,availability) où possible — Google warns dynamically-generated markup peut faire Shopping crawls moins frequent and reliable. - Validate, alors vérifier by hand. Run the Résultats enrichis Tester and the
schema.org Validator — alors manually re-check
variesByURLs andproductGroupIDmatching, since les deux réussir validation même quand broken. - Si vous aussi target Bing, don’t rely on ProductGroup — it isn’t consumed
at tout (per Microsoft’s Fabrice Canel, Sept 2024). Handle Bing Shopping
variants via Microsoft Advertising’s feed-side
itemGroupIdà la place.
ProductGroup quick-reference
productGroupID vs. item_group_id vs. inProductGroupWithID
| Field | Lives in | Format | Feeds |
|---|---|---|---|
productGroupID | On-page JSON-LD, on the ProductGroup (or on a variant Product via isVariantOf) | Plain text (e.g. "44E01") | Organic Search’s understanding of lune page |
inProductGroupWithID | On-page JSON-LD, on a variant Product (multi-page/flat pattern) | Plain text, doit match the group’s productGroupID | Même as ci-dessus — the flat-pattern lien back to the groupe |
item_group_id | Google Merchant Center product feed | Plain text | Shopping ads and free listings |
Nothing auto-syncs ces à travers systems — utiliser the même valeur in tout three so organic and Shopping agree on qui SKUs belong ensemble.
Nested vs. flat pattern
Nested (hasVariant) | Flat (isVariantOf + inProductGroupWithID) | |
|---|---|---|
| Quand to utiliser | Single-page sites — tout variants selectable on un URL | Multi-page sites — chaque variant has its propre URL |
| URL canonique pour the groupe | Un (url on the ProductGroup) | None — aucun unique URL represents the groupe |
| Où the groupe properties live | On the ProductGroup, qui nests chaque variant Product | Repeated on every variant page, via isVariantOf |
| Variant → groupe lien | Variant is nested à l’intérieur hasVariant | Variant références parent with isVariantOf + inProductGroupWithID |
Property format rules
| Property | Correct format | Incorrect format |
|---|---|---|
variesBy | Complet schema.org URL: https://schema.org/color | Plain string: "color" (validates; En pratique doesn’t groupe — pas a documented Google échec mode) |
productGroupID | Plain text parent sku: "44E01" | UNE URL |
sku / gtin (per variant) | Unique per variant | Shared/reused à travers variants |
Catch the #1 implementation mistake: variesBy as plain strings
variesBy valeurs que skip the complet schema.org URL prefix are the unique la plupart courant
mistake in ce topic — the JSON-LD encore validates, so nothing errors out, and in my
testing grouping quietly doesn’t trigger (Google’s docs exiger the full-URL formulaire but
don’t document ce que se produit si vous skip it). Ces snippets catch it directement au lieu de
relying on eyeballing the markup.
Regex: flag a bad variesBy array in raw JSON-LD
Run ce over extracted JSON-LD source (e.g. a Screaming Frog custom extraction export,
or quelconque raw HTML/text dump) to trouver variesBy arrays containing a valeur que isn’t a
complet schema.org URL:
"variesBy"\s*:\s*\[\s*((?:"(?!https://schema\.org/)[^"]*"\s*,?\s*)+)\]"variesBy"\s*:\s*\[— matches the commencer of the property and its opening bracket, allowing pour whitespace formatting differences.(?:"(?!https://schema\.org/)[^"]*"\s*,?\s*)+— the capture groupe: matches un or plus quoted strings où a negative lookahead(?!https://schema\.org/)rules out anything que déjà starts with the correct prefix. Si ce groupe matches anything at tout, au moins un entry in the array is a bad plain string comme"color"or"size"au lieu de a complet URL.- A match signifie: arrêter and fix que array avant shipping — it va validate clean and encore échouer to trigger grouping.
Chrome DevTools Console snippet: audit the live page’s JSON-LD
Paste into the Console on quelconque page vous expect to carry ProductGroup markup. It pulls
every JSON-LD block, walks into ProductGroup objects (notamment ones nested sous
isVariantOf), and reports quelconque variesBy entry que isn’t a complet schema.org URL:
(function () {
const blocks = [...document.querySelectorAll('script[type="application/ld+json"]')];
const findings = [];
blocks.forEach((block, i) => {
let data;
try {
data = JSON.parse(block.textContent);
} catch (e) {
findings.push(`Block ${i}: invalid JSON (${e.message})`);
return;
}
const items = Array.isArray(data) ? data : [data];
items.forEach((item) => {
const groups = [];
if (item['@type'] === 'ProductGroup') groups.push(item);
if (item.isVariantOf && item.isVariantOf['@type'] === 'ProductGroup') groups.push(item.isVariantOf);
groups.forEach((g) => {
const bad = (g.variesBy || []).filter((v) => !String(v).startsWith('https://schema.org/'));
if (bad.length) findings.push(`Block ${i}: bad variesBy values -> ${JSON.stringify(bad)}`);
if (g.productGroupID && /^https?:\/\//.test(g.productGroupID)) {
findings.push(`Block ${i}: productGroupID looks like a URL, should be plain text -> ${g.productGroupID}`);
}
});
});
});
console.log(findings.length ? findings.join('\n') : 'No ProductGroup issues found in this page\'s JSON-LD.');
})();XPath pour Screaming Frog: extract productGroupID à travers variant pages
Utiliser a custom extraction to pull the productGroupID valeur straight out of the JSON-LD
script tag, alors comparer the extracted valeurs à travers votre crawled variant URLs to spot a
mismatch:
//script[@type="application/ld+json"]Extract the complet text of chaque matching node, alors vérifier the extracted productGroupID
(and inProductGroupWithID on flat/multi-page setups) is identical à travers every URL
that’s supposed to belong to the même groupe — a unique differing valeur signifie que page
has probable dropped out of the groupe with aucun error thrown, fondé on testing (Google’s
docs exiger the match but don’t document mismatch behavior).
Testez vos connaissances: ProductGroup Schema
Five rapide questions on ProductGroup, its core properties, and the gotchas. Pick an réponse pour chaque, alors vérifier.
Ressources utiles
My connexe writing
I haven’t publié a piece specifically on ProductGroup schema — ce article is the dedicated treatment. The closest adjacent choses I’ve written que inform it:
- Google Uses ~40 Canonicalization Signals — Here’s Ce que Que Signifie — the “keep your signals consistent” discipline que underpins matching
productGroupIDà travers variants (and aligning it withitem_group_id). - The Myth of the Contenu dupliqué Penalty (Moteur de recherche Land) — pourquoi grouping variants as un item in options, plutôt que fearing les as duplicates, is the correct mental model. There’s aucun duplicate-content penalty to “fix” with ProductGroup — it’s à propos de understanding, pas avoiding a fine.
Pour the strategy couche — si a variant devrait même obtenir its propre URL, and how Shopify/WooCommerce/BigCommerce/Magento differ — voir the product variant SEO guide on ce site. Pour the fundamentals, the balisage de données structurées and données structurées hubs, and the sibling Product schema deep dive.
From autour the industry
- Product variant données structurées (Recherche Google Central) — the authoritative référence; lire it alongside ce pour the complet property tables.
- Ajout données structurées prise en charge pour Product Variants (Recherche Google Central blog) — the Feb 2024 announcement.
- Item groupe ID [item_group_id] (Google Merchant Center Aider) — the feed-side attribute and its schema.org cross-references.
- Nouveau Recherche Google Prise en charge Pour Product Variant Données structurées (Moteur de recherche Roundtable) — the Feb 2024 launch recap, with John Mueller’s verbatim LinkedIn post.
- Bing ne fait pas prise en charge ProductGroup markup (Moteur de recherche Roundtable) — the Fabrice Canel statement (Sept 2024).
- Google adds prise en charge pour product variants (Moteur de recherche Land) — same-day announcement coverage.
- Google To Afficher Plus Product Variants With Nouveau Markup (Moteur de recherche Journal) — the SEJ prendre on the launch.
- Schema piece: ProductGroup (Yoast Developer Portal) — réel JSON-LD exemples and Yoast’s par défaut
productGroupID-from-SKU behavior (plugin-specific). - How to implement ProductGroup schema (Go Fish Digital) — plain-English “why this exists” framing.
- schema.org/ProductGroup — the vocabulary itself, straight from the source.
Journal des modifications
Mis à jour le 20 juil. 2026.
Résumé éditorial et détails enregistrés des changements.Détails des changements
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
Comparaison complète indisponible — aucun instantané antérieur n’a été archivé pour cette révision.
Mis à jour le 18 juil. 2026.
Résumé éditorial et détails enregistrés des changements.Détails des changements
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
Comparaison complète indisponible — aucun instantané antérieur n’a été archivé pour cette révision.