Skip to content
WP Visibility

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.

Published

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.”

From variations to variant markup. ProductGroup: Name, group ID, and the attributes that vary. Variant Product: Unique SKU or GTIN for one combination. Variant offer: That combination's price and availability.
Google's model nests one Product per variation under a ProductGroup. Which variations a plugin actually prints, and with which properties, has to be checked product by product.

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:

  1. The attributes used for variations (for example, color and size).
  2. Every variation, with its SKU, barcode, regular and sale price, stock status, and whether it has its own image.
  3. 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.”
  4. Variations with no price. WooCommerce says they “don’t show in your store,” and markup may skip them.
  5. 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 ProductGroup with the product name; the description, image, and brand when available (the brand is read from a global pa_brand attribute); and a productGroupID set to the parent SKU, or the product ID when there is no SKU.
  • variesBy built from the variation attributes. Color (or an attribute named colour), 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 hasVariant entries, drawn from the first 30 variations in the order WooCommerce returns them, disabled variations included. Each carries the variation’s sku when WooCommerce returns one (it supplies the parent SKU when the variation’s own is blank) and, when the price is numeric, an offer with price, priceCurrency, and availability. 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.

  1. 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.
  2. 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.
  3. 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.”
  4. 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.

Read next

WordPress SEO with your own assistant.

WP Visibility is $99 a year for unlimited sites, client sites included, with a 30-day refund. Use its SEO tools in WordPress or connect a supported assistant. Read how proposal review and permissions work.