In short. Use productGroupID on the ProductGroup, then connect variants with hasVariant or isVariantOf according to the markup shape.
Definition: A
ProductGroupdescribes a set ofProductentities that vary along defined dimensions such as size or color. A variant can belong to that group through the group'shasVariantproperty, point to it withisVariantOf, or identify its group withinProductGroupWithIDwhen the group'sproductGroupIDis used.
Key facts
- Google's product variant documentation uses
ProductGroupwithvariesBy,hasVariant, andproductGroupID, alongsideProductstructured data, to group variants. - Schema.org defines
ProductGroupas a group of products that vary in well-described ways, including size, color, or material. - Schema.org defines
inProductGroupWithIDas theproductGroupIDfor theProductGroupthat a productisVariantOf. - Schema.org describes
isVariantOfas the kind of product that a product is a variant of and listshasVariantas its inverse property.
What goes on the parent product group?
Put the group identifier on the ProductGroup with productGroupID. Schema.org describes this property as a textual identifier for a ProductGroup. Google calls the value in its example the parent SKU and places it on the group entity. The group also declares the dimensions that distinguish variants through variesBy, such as the Schema.org size and color properties.
The group is a place for shared information. Google documents common properties such as brand and review information at ProductGroup level, while variant-specific titles and descriptions belong at Product level. Schema.org describes the group as a prototype or template for products that have an isVariantOf relationship to it.
Which relationship should connect a variant?
There are two useful shapes.
For nested markup, put each variant in the parent's hasVariant array. Google says that this structure places the variants under the top-level ProductGroup; in this pattern, productGroupID does not need to be repeated on each Product with inProductGroupWithID.
For separate entities, give the ProductGroup an @id and set each Product's isVariantOf to that identifier. Google's separate-entity example uses "isVariantOf": { "@id": "#coat_parent" }. Schema.org lists hasVariant as the inverse of isVariantOf, so the two properties describe the same membership from opposite directions.
{
"@type": "ProductGroup",
"@id": "#coat_parent",
"productGroupID": "coat-parent",
"variesBy": ["https://schema.org/size", "https://schema.org/color"],
"hasVariant": [{"@type": "Product", "sku": "coat-small"}]
}
{
"@type": "Product",
"isVariantOf": {"@id": "#coat_parent"},
"sku": "coat-small"
}
inProductGroupWithID expresses the same parent association by value: its value identifies the group's productGroupID. It is useful when the implementation connects a product to its group through the textual identifier. The nested pattern already carries the association through hasVariant, which is why Google says the identifier need not be repeated there.
How does the page layout affect the markup?
Google documents both single-page and multi-page product variant layouts. On a single page, selectable variants can be nested under one ProductGroup or kept as separate entities. For separate entities, Google notes that the approach can be easier for some content management systems to generate.
On a multi-page site, Google says the ProductGroup definition is repeated on each variant page when the group contains shared attributes. A page can carry full details for its local variants and a variant entry with only a URL for a variant on another page. The ProductGroup has no canonical URL in this example because no single URL represents the group.
What should be checked before release?
Google's documentation says to validate the markup with the Rich Results Test, inspect how Google sees a deployed page with URL Inspection, and ensure that the page is accessible rather than blocked by robots.txt, noindex, or login requirements. The markup should also match the page's product information, including the variant's own properties and offer URL where those are present.
Related terms
FAQ
Should a nested variant include inProductGroupWithID?
Google's nested hasVariant example puts the membership on the parent and says the productGroupID does not need to be repeated under each Product. The product can therefore remain nested under hasVariant without that second identifier property.
Should a separate variant use isVariantOf or inProductGroupWithID?
Use isVariantOf when the product points to a ProductGroup entity by @id, as in Google's separate-entity example. inProductGroupWithID supplies the textual productGroupID of the group described by Schema.org.
Where does the variant SKU go?
The parent group's identifier goes in productGroupID. A variant's own SKU is a property of its Product; Google's example shows a separate SKU on each variant.
Sources
- Google Search Central, "Product Variant Structured Data (ProductGroup, Product)", 8 September 2026
- Schema.org, "ProductGroup", 16 September 2026
- Schema.org, "inProductGroupWithID", 16 September 2026
- Schema.org, "isVariantOf", 16 September 2026
Check how a page reads to answer engines. Open the GEO score analyzer