The Variant Matrix Is Not a Sellable Catalog
Fresh Schema.org changes can describe richer product options, but dimensions, valid combinations, offers, and consumer support remain separate contracts.
Schema.org merged a small but consequential product-variant change on 31 August. variesBy can now accept PropertyValue, allowing a ProductGroup to describe not only that a laptop varies by memory and CPU, but also that the known memory values are 16, 32, and 64 GB and the CPU values are eight and sixteen cores.
Six days earlier, another Schema.org product-data change added pending terms for grouped technical specifications, consumer notices, frequently bought-together relationships, marketplace popularity, maximum retail price, shipping providers, and minimum order values.
The additions make a richer catalog graph possible. They do not make every combination in that graph sellable, deploy the vocabulary to every published schema page, add support to every search or commerce consumer, or prove that the visible product page agrees with the markup.
The repeated angle to avoid
The ten most recent posts here covered htmx state provenance, Shopify finance clocks, verified-bot policy joins, AI-catalog conformance, security-dashboard denominators, chat-adapter semantics, agent compute planes, security treatment states, soft-navigation measurement, and API authorization loops. Older overlapping posts covered Shopify checkout experiments, negotiated cache variants, and situation-specific AI-search pages.
The weak version would return to the old X needs Y formula: ecommerce structured data needs validation. It would also repeat the generic advice to keep page content and JSON-LD consistent.
The narrower thesis is that a product option set, a valid variant combination, a purchasable offer, and a consumer-supported structured-data feature are four different facts. The new PropertyValue range makes the first fact more expressive. It does not infer the other three.
That distinction produces the information surplus. A catalog may offer memory values of 16, 32, and 64 GB and CPUs with eight or sixteen cores without selling all six Cartesian combinations. A valid SKU can be temporarily unavailable. A current Schema.org term can be unknown to Google. A merged term can still be in a pending extension or absent from the rendered vocabulary site. Operators need a release contract that preserves those boundaries rather than turning every newly expressible value into a public promise.
Fresh evidence and background serve different jobs
| Source | Freshness | What it contributes |
|---|---|---|
| Enhanced specification of variant dimensions and its merged commit | Merged 31 August 2026 | PropertyValue in the range of variesBy, available values for custom dimensions, and QualitativeValue support needed for structured sizes |
| Common retail and marketplace product data and its merged commit | Merged 25 August 2026 | Pending vocabulary for specifications, notices, relationships, popularity, MRP, shipping providers, and minimum-order thresholds |
Schema.org ProductGroup, variesBy, and hasVariant |
Current development vocabulary | The group, dimension, and member relationships; also evidence that rendered vocabulary deployment can lag merged source |
| Google product-variant structured data | Background consumer documentation, last modified 20 May 2026 | Google's supported ProductGroup pattern, distinct variant URLs, single-page and multi-page designs, and visible variant preselection requirements |
| Google Merchant Center item group ID | Current primary consumer documentation | Separate submitted products per variant, shared group identity, variant attributes, distinct landing URLs, and agreement with the shopping experience |
The two Schema.org merges are the fresh primary evidence. The Google documents are older consumer contracts, not proof that Google already consumes the new ranges or pending properties.
That separation matters immediately. The 31 August commit changed the core source file, but during this review the rendered development page for variesBy still listed only DefinedTerm and Text as expected types. The 25 August retail additions live under Schema.org's pending extension in the repository rather than the core schema. A merged source change, a deployed vocabulary page, and a consuming product feature do not share one release clock.
variesBy now describes an option envelope
Before the fresh change, variesBy named the axes that distinguish members of a ProductGroup: color, size, material, memory, CPU, or another property. The merged model can carry a PropertyValue for an axis and list its available values.
A shortened example based on the new Schema.org fixture looks like this:
{
"@context": "https://schema.org/",
"@type": "ProductGroup",
"productGroupID": "LAPTOP-72",
"variesBy": [
{
"@type": "PropertyValue",
"name": "Memory size",
"value": [16, 32, 64],
"unitCode": "E34",
"unitText": "GB"
},
{
"@type": "PropertyValue",
"name": "CPU",
"value": ["low_8core", "high_16core"]
}
]
}
This says that memory and CPU are variant dimensions and identifies values found within those dimensions. It does not say that every member of this mathematical set exists:
{16, 32, 64} GB × {8-core, 16-core} = 6 possible pairs
The merchant may sell only:
16 GB + 8-core
32 GB + 16-core
64 GB + 16-core
The other three pairs may be technically impossible, discontinued, market-restricted, or never assigned a SKU. The dimension envelope has six possible pairs; the sellable catalog has three members.
hasVariant remains the relationship for actual Product members. Each real member needs its own stable identity and variant facts. Its Offer needs the current price, currency, availability, condition, and a URL that selects that member. If a pipeline generates hasVariant entries by multiplying dimension values, it turns vocabulary convenience into phantom inventory.
Four layers prevent phantom variants
A robust product model keeps four layers rather than one wide variant object.
| Layer | Grain | Example fact | What it must not infer |
|---|---|---|---|
| Option dimension | Product group plus dimension | Memory has observed values 16, 32, and 64 GB | Every memory value combines with every CPU value |
| Variant member | One real product or SKU | SKU LAPTOP-72-32-H16 selects 32 GB and high 16-core |
The SKU is currently purchasable in every market |
| Offer | SKU plus seller, market, currency, and time | AUD 1,899, in stock, ships to Australia | The same price or availability applies elsewhere or later |
| Consumer projection | Vocabulary version plus consumer profile | Google-supported ProductGroup fields emitted in initial HTML |
Every valid Schema.org term drives a Google search feature |
This model also handles ordinary catalog complications:
- one color is available only in two sizes;
- one memory option requires a different processor;
- a variant exists in the product information system but is not published in Australia;
- a product is visible but back-ordered rather than in stock;
- one seller has an offer while another does not;
- a variant URL exists but its selector fails to preselect the expected option;
- the page changes availability in the browser while initial JSON-LD remains stale.
The correct join is from a real variant record to its current eligible offers. It is not from option values to a generated grid.
Vocabulary, validators, and consumers move independently
Structured-data rollouts often treat “valid Schema.org” as the final gate. It is only one gate.
A product property can occupy several states:
- Proposed. The issue describes a useful model, but names and ranges can still change.
- Merged to pending. The repository contains the term under the pending extension so implementers can test and give feedback.
- Merged to core source. The canonical source has changed, but generated pages and validators may not yet reflect it.
- Published by Schema.org. The term and range appear in a deployed vocabulary version.
- Accepted by a syntax or schema validator. The document is structurally valid for the selected profile.
- Documented by a consumer. Google, a marketplace, an agent, or an internal search service says how it interprets the term.
- Used by a consumer feature. The field contributes to an observable result for eligible content.
Those transitions are not automatic promotions.
Google's current product-variant examples use variesBy to name dimensions with Schema.org property URLs and use hasVariant for actual products. The documentation does not yet say that its merchant listing feature consumes a PropertyValue option envelope. The correct migration is therefore not to replace the documented representation on every page as soon as the Schema.org commit merges.
Use consumer profiles:
product_structured_data_profiles:
google_merchant_listing:
source: google_product_variant_documentation
varies_by_representation: property_urls
real_variants_only: true
distinct_selectable_url: required
initial_html: preferred
schemaorg_experiment:
source_revision: 262f6427298a
property_value_varies_by: enabled_in_test_fixture
production_consumer_claim: none
pending_retail_terms:
source_revision: 13e92551b59f
emit_in_production: false
review_when:
- term_is_published
- target_consumer_documents_support
The values are an implementation pattern, not vendor settings. The useful control is that an experiment can validate the richer graph without pretending a search feature supports it.
The page, feed, and JSON-LD need one variant identity
Google's Search documentation supports both single-page and multi-page product designs. In either design, each selectable variant needs a distinct URL or URL state that Google can request directly. That request must preselect the intended variant and show the corresponding image, price, availability, and add-to-cart choice.
Merchant Center adds another representation. It asks merchants to submit each variant as a separate product, use the same item_group_id for members of one group, provide variant-identifying attributes, and keep the feed aligned with the landing-page experience.
A practical identity join is:
catalog group ID
-> real SKU ID
-> selected option values
-> market-specific offer ID
-> variant landing URL
-> Product / Offer node IDs
-> Merchant Center item ID + item_group_id
Do not join on a display title such as “Blue laptop.” Titles change, translations collide, and several combinations can share the same visible label. Use stable group, SKU, and offer identifiers; keep human names as attributes.
For one URL, a release test should reconstruct the same member across all representations:
variant_contract_probe:
requested_url: https://shop.example/laptop?memory=32&cpu=high16
expected:
product_group_id: LAPTOP-72
sku: LAPTOP-72-32-H16
selected_options:
memory_gb: 32
cpu: high_16core
currency: AUD
observed:
visible_selection: matches
visible_price: matches_offer
visible_availability: in_stock
add_to_cart_variant_id: matches_sku
jsonld_product_sku: matches
jsonld_offer_url: matches_requested_url
merchant_item_id: matches_feed
merchant_item_group_id: LAPTOP-72
A Rich Results Test pass cannot prove the selector, cart payload, feed, or live inventory. A browser test cannot prove the crawler receives equivalent initial markup. The contract probe has to cross those boundaries.
The pending retail terms carry provenance requirements
The 25 August merge is broader than variants. Its terms model facts merchants commonly already hold, but several are unsafe to fill from convenient page copy.
| Pending term | Appropriate source | Failure mode to avoid |
|---|---|---|
specification with valueGroup |
Product information system with typed units and reviewed labels | Scraping a marketing table into ambiguous strings or duplicating conflicting additionalProperty values |
consumerNotice |
Compliance-approved notice tied to product and market | Hiding a required warning in JSON-LD while the buyer never sees it |
isOftenBoughtWith |
Defined merchandising rule or measured co-purchase method with exclusions | Presenting paid placement or one operator's hunch as observed popularity |
itemPopularity |
Marketplace- or catalog-wide rank with population, direction, and update time | A merchant self-asserting “number one” without a comparison set |
MaximumRetailPrice |
Authoritative market-specific price record | Treating MRP as an ordinary universal list price; the merged definition is specifically for India |
minimumOrderValue |
Shipping-rate rule with currency, destination, and effective period | Attaching free shipping to one product when the cart has not met the threshold |
shipping provider |
Current shipping method or rate configuration | Naming a carrier that is unavailable for the selected destination or service |
These properties become useful when they preserve source and scope. They become misleading when a template fills every field merely because the vocabulary offers it.
The itemPopularity definition is particularly deliberate: it is intended for platform-level or catalog-wide comparative ranking rather than self-asserted promotion. A ranking needs a comparison population, direction, and observation time. Rank 12 among 500 laptops is not the same fact as twelve purchases, a 4.8 rating, or a manually ordered collection position.
Likewise, an “often bought with” edge can come from transaction evidence, a compatibility rule, or a merchandising choice. Those are different claims. Store the method internally even if the public property does not expose all of its provenance.
Build the projection from event-aware catalog data
A nightly page scraper is a weak source for structured product facts. It sees one rendered state and tends to lose identities, markets, effective times, and unavailable combinations.
Prefer an event-aware projection:
product information changes
+ variant publish state changes
+ offer price or availability changes
+ market eligibility changes
+ shipping policy changes
+ compliance notice changes
-> rebuild affected group projection
-> validate vocabulary profile
-> compare page, JSON-LD, feed, and cart
-> publish atomically or retain last known consistent version
“Atomically” does not require every external consumer to refresh at once. It means the site's selectable state, visible facts, cart mapping, and embedded structured data should be generated from one versioned catalog snapshot where practical. Feed publication can carry the same snapshot ID so lag is measurable rather than guessed.
Keep change classes separate:
- descriptive change: name, specification label, image, or notice copy;
- topology change: variant added, removed, merged, or moved to another group;
- commercial change: price, currency, availability, seller, or market;
- consumer-profile change: supported vocabulary terms or required fields;
- URL change: canonical or preselection route changes.
Topology and URL changes deserve stronger checks than a copy edit. They can create orphan feed items, duplicate group membership, dead variant links, and phantom selector choices even when the JSON parses successfully.
A deployment gate for richer product data
Use this sequence before adopting the fresh vocabulary:
- Snapshot the sellable graph. Export group IDs, real SKU members, selected option values, offers, markets, and variant URLs from authoritative systems.
- Test for Cartesian leakage. Compare generated members with real SKU IDs. Fail if a dimension combination appears without a catalog member.
- Pin a vocabulary revision. Record whether each field is proposed, pending, merged to core source, or present in a published Schema.org version.
- Pin consumer profiles separately. Keep Google's documented fields, Merchant Center attributes, marketplace feeds, and experimental Schema.org fields in different allowlists.
- Render from one catalog snapshot. Generate selector options, visible facts, JSON-LD, and cart IDs from the same version where possible.
- Request every important variant URL. Confirm preselection, image, price, availability, currency, canonical handling, and add-to-cart identity.
- Compare initial and hydrated markup. Detect JavaScript that replaces a correct server snapshot with a stale or different variant.
- Reconcile the product feed. Check item ID, group ID, option values, link, image, price, and availability against the live page.
- Validate unsupported-term claims. A syntax pass is not evidence of a rich-result feature. Record “valid but unsupported” explicitly.
- Monitor topology drift. Re-run when a SKU, option, market, URL, shipping rule, notice, or consumer profile changes—not only on frontend deploys.
The decision rule is: promote a new product property only when its vocabulary status is acceptable, the target consumer's treatment is understood, the source fact has trustworthy provenance, and the live customer path agrees with the projection. A pending term can remain in a test fixture until those conditions are met.
Failure modes worth rehearsing
The option envelope becomes a Cartesian catalog
A generator sees three memory values and two CPUs, then emits six Product nodes. Three have no SKU or cart target. Generate members only from authoritative variant records; use dimensions to describe and validate them, never to invent them.
A merged range is treated as deployed consumer support
The repository accepts PropertyValue for variesBy, so production markup replaces the representation documented by the search consumer. Schema.org validation improves while the intended merchant feature ignores the field. Pin separate vocabulary and consumer profiles, and keep experimental output measurable.
Pending retail terms become invisible marketing copy
A product gains a safety notice, popularity claim, MRP, and free-shipping threshold only in JSON-LD. The visible page omits or contradicts them. Require page-visible evidence and compliance review where the fact affects safety, price, or purchase conditions.
An unavailable SKU remains a selectable variant
The catalog member still exists, but its market offer expired. The page selector, JSON-LD, and feed disagree about whether it can be bought. Preserve the product member if appropriate, but update or remove the market-specific offer consistently and test the cart response.
Group identity changes during a catalog migration
A new PIM generates different parent IDs, splitting one family in the feed while the page and JSON-LD retain the old productGroupID. Keep an explicit ID migration table; do not derive permanent group identity from a mutable title or category path.
A URL selects the wrong member after hydration
The server returns the requested 32 GB variant and correct JSON-LD. Client state restores the last viewed 16 GB choice, while the URL and metadata remain unchanged. Test both initial HTML and hydrated selection, then confirm the cart receives the same SKU.
Frequently bought together leaks private or meaningless evidence
A relationship is generated from a tiny number of orders, returned products, staff purchases, or sensitive category combinations. Define minimum evidence, exclusions, retention, and whether the edge is behavioural or editorial before publishing it.
The practical conclusion
The fresh Schema.org work fills real product-data gaps. Variant dimensions can carry their available values instead of naming only an axis. Retail catalogs can begin testing clearer properties for specifications, notices, related products, popularity, price conventions, shipping providers, and order thresholds.
The richer graph makes boundaries more important, not less. An option envelope does not enumerate feasible combinations. A product member does not guarantee a live offer. A merged term does not guarantee a deployed vocabulary page. A valid vocabulary term does not guarantee support in Google or another consumer. A correct JSON-LD object does not guarantee the selected page and cart sell the same SKU.
Start with the sellable catalog. Preserve group, SKU, option, offer, market, URL, and effective-time identities. Project only real members. Gate vocabulary status separately from consumer support. Reconcile the page, initial markup, hydrated state, feed, and cart with one variant contract probe.
That produces more than valid structured data. It produces a product graph that can explain exactly which choices exist, which combinations are real, which offer is current, and which public claim each consumer is actually equipped to understand.