WooCommerce SEO guide
WooCommerce Variable-Product Schema: Check Every Represented Variation
Map a variable product's sizes and colors to ProductGroup, variants, and offers, then compare the markup with each purchasable variation and note what it leaves out.
On this page
For a WooCommerce variable product, the structured data should describe one product group and the variations a shopper can actually buy, each with its own identifier, price, and availability. Check it in three passes: list the purchasable variations in WooCommerce, compare them with the variants in the markup, and test a few specific combinations against the page. Expect gaps; different plugins represent variations differently, and none should be assumed to cover a whole catalog.
Learn how Google models variants
Google’s product variant documentation, checked September 27, 2026, uses a ProductGroup as the parent and nests each variation as a Product under hasVariant. The key properties:
| Property | Where | What it does |
|---|---|---|
name |
ProductGroup | The only property Google lists as required on the group |
productGroupID |
ProductGroup | A unique ID for the group |
variesBy |
ProductGroup | The attributes variants differ by, as schema.org URLs such as https://schema.org/color |
hasVariant |
ProductGroup | The variant Product nodes |
sku or gtin |
Each variant | “Each variant must have a unique ID” |
offers |
Each variant | The variant’s own price and availability |
Google lists color, size, suggestedAge, suggestedGender, material, and pattern as the supported variesBy values. It says variant names should be more specific than the group, giving “Wool winter coat - green, size small” as an example. Its technical guidelines also say each variant must be selectable at a distinct URL: “The site must have the ability to preselect each variant directly with a distinct URL (using URL query parameters).” Preselecting a variant, it adds, “includes showing the right image, price, and availability, as well as allowing the user to add the variant to the cart.” Google’s merchant listing documentation, checked the same day, describes offers.url as a URL that “may be the preferred URL for the current page with all variant options appropriately selected.”
Inventory the parent and purchasable variants
Start in WooCommerce, because the markup should follow the store and not the reverse. WooCommerce’s variable product documentation, checked September 27, 2026, notes that each variation can have its own SKU, price, sale price, stock, image, weight, dimensions, and description, and that a variation with a blank SKU falls back to the parent’s SKU.
For one product, write down:
- The attributes used for variations (for example, color and size).
- Every variation, with its SKU, barcode, regular and sale price, stock status, and whether it has its own image.
- Variations using “Any” for an attribute. WooCommerce “highly recommend[s]” defining all attributes of all variations, and warns that “Any” choices can make variations effective duplicates of each other, which “can lead to confusing behaviors.”
- Variations with no price. WooCommerce says they “don’t show in your store,” and markup may skip them.
- Duplicate SKUs. A variation that inherits the parent SKU does not have a unique identifier of its own.
For a larger catalog, WooCommerce’s product CSV export (the Export button on Products > All Products, with variations included; checked September 27, 2026) gives you one row per variation, with a Parent column naming its product. Filter it to one parent product at a time.
An illustrative example from the fictional garden.example:
| Variation | SKU | Price | Stock | Own image |
|---|---|---|---|---|
| Green, small | GL-G-S | 18.00 | In stock | Yes |
| Green, large | GL-G-L | 20.00 | Out of stock | Yes |
| Blue, small | GL-B-S | 18.00 | In stock | No |
| Blue, large | (inherits GL) | 20.00 | In stock | No |
Two of these rows already flag problems before you open the markup: neither blue variation has an image of its own, and one has no unique SKU.
Compare URLs, attributes, and offers
Capture the product page’s server HTML and extract the ProductGroup, as described in the product schema check. Then compare the markup with your inventory:
| Question | How to check | A problem looks like |
|---|---|---|
| Is there one group? | Count ProductGroup nodes |
Two groups from two plugins, or a plain Product with a price range |
| Are all purchasable variants present? | Count hasVariant entries against your list |
Fewer variants than the store sells, with no stated limit, or disabled variations listed |
| Is each variant uniquely identified? | Read each sku or gtin |
Repeated SKUs, or none |
| Do prices match? | Compare each variant offer with the price shown when that variation is selected | A variant priced from the stored value while the page shows it with tax |
| Does availability match? | Compare each offer’s availability with the stock message |
Out of stock variation marked in stock |
| Can each variant be identified? | Look for color, size, name, image, or url on each variant |
Variants that differ only by SKU and price |
Then test the URL requirement. Open the product and select a variation. Check whether the address bar changes. Then try opening the product with the variation’s attributes in the query string, for example ?attribute_pa_color=green&attribute_pa_size=small (attribute slugs are illustrative; use your own), and see whether the theme preselects that variation. Record whether each variation has a URL that loads it selected. If none does, markup cannot supply one truthfully.
Know what WP Visibility 2.10.3 prints for variations
With WP Visibility’s Schema and WooCommerce modules on (the defaults when WooCommerce is active), checked against the 2.10.3 release, a variable product gets:
- A
ProductGroupwith the product name; the description, image, and brand when available (the brand is read from a globalpa_brandattribute); and aproductGroupIDset to the parent SKU, or the product ID when there is no SKU. variesBybuilt from the variation attributes. Color (or an attribute namedcolour), size, material, and pattern become schema.org URLs. Any other attribute is published as its store label, such as “Length”, which is not one of the values Google lists as supported.- Up to 30
hasVariantentries, drawn from the first 30 variations in the order WooCommerce returns them, disabled variations included. Each carries the variation’sskuwhen WooCommerce returns one (it supplies the parent SKU when the variation’s own is blank) and, when the price is numeric, an offer withprice,priceCurrency, andavailability. A variation with neither a SKU nor a numeric price is left out, but it still counts toward the 30. - No price range or single offer on the group itself, and the aggregate rating on the group when reviews are enabled and present.
It does not add variant names, images, URLs, GTINs, or attribute values such as color: Green to each variant. On a product with more than 30 variations, variations beyond the thirtieth are not represented. Treat these as fixed limits of that release when you compare against Google’s guidance, not as settings you can change. Variant offer prices follow the same stored-price rule as simple products; the price mismatch guide explains how that interacts with tax display.
Validate representative combinations
You do not need to test every variation of every product, but you do need to test the risky ones.
- Pick samples. For each variable product type in your store, pick one variation that is in stock, one out of stock, one on sale, and one without its own SKU or image.
- Check each against the page. Select the variation on the product page and compare the shown price and stock message with that variant’s offer.
- Run the Rich Results Test on the product URL. Note detected items, errors, and warnings. Google’s variant documentation recommends deploying a few pages and using the URL Inspection tool “to test how Google sees the page.”
- Record the limits. Write down any variation that is missing from the markup, any variant without a unique ID, and whether variation URLs exist.
What the results mean:
| Result | Meaning | Next step |
|---|---|---|
| Variant missing, product has more variations than the emitter’s limit (in 2.10.3, disabled variations count) | A known cap | Decide whether that product needs different markup; do not assume coverage |
| Variant missing, below the limit | In 2.10.3, no SKU (own or inherited) and no numeric price; other emitters have their own rules | Fix the variation data in WooCommerce |
| Duplicate SKU | The variation inherits the parent SKU | Give the variation its own SKU |
| Price differs only when tax applies | Stored versus displayed price | Follow the price mismatch guide |
| Validator passes, variants have no names or URLs | Structurally valid, less descriptive than Google’s examples | Note it; validation is not accuracy or eligibility |
Checklist
- Every purchasable variation listed from WooCommerce, with SKU, price, stock, and image.
- No “Any” variations, or each one understood.
- Each variation has its own SKU or barcode.
- Variant count in the markup compared with the store, and any cap noted.
- At least four representative variations checked against the page.
- Whether each variation has its own URL recorded.
