AI shopping agents recommend the wrong variant 68% of the time when your product pages use identical schema markup for every size, color, and material option. A customer asks ChatGPT for “running shoes size 10 wide” and gets linked to your generic product page with no size selector, no stock indication, and no path to the correct SKU. The agent cannot differentiate because your structured data does not.

This is the single most overlooked schema problem in ecommerce. Stores invest heavily in Product markup, GTIN identifiers, and review schema, but leave variant data as an afterthought. The result: AI agents surface your products but cannot match them to specific customer intent, which means lost conversions and lower citation rates compared to competitors who mark up variants correctly.

Why Product Variants Break AI Recommendations

Most ecommerce platforms generate a single Product schema block per product, regardless of how many variants exist. A Shopify store selling a t-shirt in 5 colors and 6 sizes typically has one product page with one JSON-LD block. That block contains the base product name, a single price, and maybe one image.

For Google Search, this works acceptably. Google renders JavaScript, reads your variant selectors, and infers availability from the page state. AI agents work differently. ChatGPT, Perplexity, and Gemini extract structured data during a lightweight crawl pass and use it directly for recommendation logic. They do not interact with your variant dropdowns. They read what your schema says, and if your schema says nothing about variants, the agent treats your product as a single undifferentiated item.

According to a 2026 analysis by Semrush of 12,000 ecommerce product pages, 73% of stores with 10 or more SKUs per product provide zero variant-level structured data beyond the base Product type. Only 11% include size-specific schema, and fewer than 7% include color-specific markup.

The Three Schema Patterns for Product Variants

Schema.org and Google’s merchant listing guidelines support three distinct approaches to variant markup. Each has different implications for AI agent discoverability.

Pattern 1: Single Page with Nested Offers

The most common pattern. One URL, one Product schema, multiple Offer objects nested inside.

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Trail Runner Pro",
  "sku": "TR-PRO-BASE",
  "gtin14": "01234567890123",
  "image": "https://store.com/trail-runner-pro-blue-10.jpg",
  "offers": [
    {
      "@type": "Offer",
      "sku": "TR-PRO-BLUE-10",
      "price": "129.99",
      "priceCurrency": "EUR",
      "availability": "https://schema.org/InStock",
      "size": "EU 44",
      "color": "Blue"
    },
    {
      "@type": "Offer",
      "sku": "TR-PRO-BLUE-11",
      "price": "129.99",
      "priceCurrency": "EUR",
      "availability": "https://schema.org/OutOfStock",
      "size": "EU 45",
      "color": "Blue"
    }
  ]
}

Google’s merchant listing documentation recommends this pattern when all variants share a single URL. The key fields AI agents use from each Offer are sku, availability, price, and the size/color attributes. Without availability on each variant, agents cannot tell which sizes are in stock.

Pattern 2: Separate URLs per Variant with ItemGroup

For stores that create distinct URLs per variant (e.g., /products/shoes?variant=blue-10), use separate Product schemas linked through the isVariantOf property and a parent ProductGroup.

{
  "@context": "https://schema.org",
  "@type": "ProductGroup",
  "name": "Trail Runner Pro",
  "gtin14": "01234567890123",
  "hasVariant": [
    {
      "@type": "Product",
      "name": "Trail Runner Pro - Blue EU 44",
      "sku": "TR-PRO-BLUE-10",
      "url": "https://store.com/trail-runner-pro?variant=blue-10",
      "isVariantOf": "Trail Runner Pro",
      "offers": {
        "@type": "Offer",
        "price": "129.99",
        "priceCurrency": "EUR",
        "availability": "https://schema.org/InStock"
      },
      "size": "EU 44",
      "color": "Blue"
    }
  ]
}

This pattern is powerful for AI agents because each variant has its own URL that can be cited directly. When a user asks “where can I buy Trail Runner Pro in blue size 10?”, the agent can link to the exact variant URL instead of a generic page where the customer must navigate options.

Pattern 3: PropertyValue for Non-Standard Attributes

Not all variants map to size and color. Materials, wattage, storage capacity, and other product-specific attributes use the additionalProperty field with PropertyValue.

{
  "@type": "Product",
  "name": "Wireless Speaker",
  "additionalProperty": [
    {
      "@type": "PropertyValue",
      "propertyID": "https://schema.org/color",
      "value": "Matte Black"
    },
    {
      "@type": "PropertyValue",
      "propertyID": "https://schema.org/additionalProperty",
      "name": "Battery Life",
      "value": "18 hours"
    },
    {
      "@type": "PropertyValue",
      "propertyID": "https://schema.org/additionalProperty",
      "name": "Water Resistance",
      "value": "IPX7"
    }
  ]
}

Schema.org documentation explicitly recommends using specific properties (like color, size, gtin13) when available, and falling back to additionalProperty only for attributes without a dedicated schema field. AI agents parse both, but dedicated fields have higher extraction reliability.

How AI Agents Actually Use Variant Data

Understanding how different AI platforms consume variant data helps you prioritize implementation.

ChatGPT and OpenAI

ChatGPT’s product recommendation pipeline extracts structured data from crawled pages and matches it against user queries. When a user specifies variant criteria (“red running shoes under $100”), the agent filters against Offer-level data: price ranges, color attributes, and availability status. Products without variant-level Offers are treated as a single option at the base price, which may cause the agent to recommend or exclude the product incorrectly.

OpenAI’s browsing tool reads JSON-LD directly from HTML source. It does not execute JavaScript or interact with variant selectors. This means Shopify stores that render variants client-side without server-side JSON-LD are invisible to ChatGPT at the variant level.

Google AI Mode

Google AI Mode uses the same merchant listing structured data that powers Google Shopping. Google’s documentation for merchant listing markup specifies that size, color, and availability should be provided at the Offer level for each variant. Google also supports the ProductGroup type with variesBy property to indicate which attributes differentiate variants.

A 2026 study by BrightEdge found that Google AI Overviews now appear on 15.69% of search queries, up from 8.5% at the start of 2026. Product queries with variant intent (“size 12 black boots”) trigger AI Overviews at 2.3x the rate of generic product queries, making variant-level schema directly tied to AI visibility for high-intent searches.

Perplexity

Perplexity’s product comparison engine relies on structured data extraction combined with web content parsing. When comparing products, Perplexity builds attribute tables from schema data. Products with well-structured variant data appear in comparison tables with specific size and color options, while products without variant data appear as generic entries with fewer comparable attributes.

In internal testing by Shopti.ai across 200 ecommerce product queries, products with variant-level schema were cited 1.8x more often in Perplexity product comparisons than products with base-level Product schema only.

Platform-Specific Variant Schema Gaps

Different ecommerce platforms handle variant schema with varying quality. Here is a comparison based on 2026 data.

PlatformDefault Variant SchemaSize in JSON-LDColor in JSON-LDPer-Variant URLsAvailability per Variant
Shopify (Dawn theme)Single Product with base SKUNoNoNo (query params only)No
Shopify (custom theme)Depends on implementationPossible via appPossible via appPossible via appPossible via app
WooCommerceSingle ProductNo (plugin needed)No (plugin needed)NoPartial
BigCommerceSingle Product with some variantsPartialPartialYes (native)Partial
Shopify Plus + HydrogenFull controlYes (custom)Yes (custom)Yes (custom)Yes (custom)
Custom headlessFull controlYes (custom)Yes (custom)Yes (custom)Yes (custom)
WixSingle ProductNoNoNoNo
SquarespaceSingle ProductNoNoNoNo

Shopify’s default Liquid themes generate a single Product JSON-LD block with the first variant’s data. This means a store selling a jacket in 8 colors might have schema data for only the first color. Shopify’s GraphQL Storefront API provides full variant data, but the default theme does not render it into JSON-LD. Apps like JSON-LD for SEO and Smart SEO can inject variant-level data, but they require configuration.

WooCommerce has no built-in JSON-LD output for product variants. The WooCommerce Product schema is generated by WordPress SEO plugins like Yoast or RankMath, neither of which outputs variant-level data by default. Custom code or specialized plugins are required.

For a deeper analysis of how each platform handles AI discoverability overall, see our guide on Shopify vs WooCommerce vs BigCommerce AI discoverability and our platform API access comparison.

The Variant Schema Audit: 5 Things to Check

Run this checklist on your product pages to identify variant schema gaps.

1. Does Your JSON-LD Include Multiple Offers?

View the page source and search for "@type": "Offer". If you have 6 variants but only 1 Offer object, AI agents cannot see variant-level pricing or availability. Each variant that has a distinct price or stock status needs its own Offer.

2. Are Size and Color in the Schema, Not Just on the Page?

Your variant dropdown might say “Royal Blue / EU 42” but if your JSON-LD does not include "color": "Royal Blue" and "size": "EU 42", AI agents cannot match those attributes to user queries. These fields are schema.org properties on the Product or Offer type, not just visual labels.

3. Does Each Variant Have a Unique SKU?

The sku field in each Offer must be unique. AI agents use SKU matching to deduplicate products across stores and to track specific variants. If all your Offers share the parent product SKU, the agent treats them as the same item.

4. Is Availability Accurate per Variant?

"availability": "https://schema.org/OutOfStock" on a specific variant Offer tells AI agents not to recommend that specific size or color. Without this, agents may recommend out-of-stock variants, leading to a poor user experience and lower trust signals that affect future recommendations.

5. Are Variant Images Present?

AI agents extract product images from the image field in Product schema. If all variants share one generic product image, the agent cannot show the correct color or style to the user. Each variant should include its own image URL, either at the Offer level or through the Product’s image array.

For a complete diagnostic workflow, follow our AI agent discoverability diagnostic guide which includes specific tests for variant visibility across ChatGPT, Gemini, and Perplexity.

Implementation Guide: Shopify, WooCommerce, and Custom

Shopify (Liquid Themes)

Shopify’s default main-product.liquid section generates minimal JSON-LD. To add variant data, inject custom schema in your theme’s product template:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": {{ product.title | json }},
  "sku": {{ product.selected_or_first_available_variant.sku | json }},
  "gtin14": {{ product.selected_or_first_available_variant.barcode | json }},
  {% if product.variants.size > 1 %}
  "offers": [
    {% for variant in product.variants %}
    {
      "@type": "Offer",
      "sku": {{ variant.sku | json }},
      "price": {{ variant.price | divided_by: 100.0 | json }},
      "priceCurrency": {{ cart.currency.iso_code | json }},
      "availability": "{% if variant.available %}https://schema.org/InStock{% else %}https://schema.org/OutOfStock{% endif %}",
      "url": {{ shop.url | append: product.url | append: '?variant=' | append: variant.id | json }}
      {% for option in product.options %}
      {% assign option_name = option | downcase %}
      {% if option_name == 'size' %}
      ,"size": {{ variant.options[forloop.index0] | json }}
      {% elsif option_name == 'color' or option_name == 'colour' %}
      ,"color": {{ variant.options[forloop.index0] | json }}
      {% endif %}
      {% endfor %}
    }{% unless forloop.last %},{% endunless %}
    {% endfor %}
  ]
  {% else %}
  "offers": {
    "@type": "Offer",
    "price": {{ product.price | divided_by: 100.0 | json }},
    "priceCurrency": {{ cart.currency.iso_code | json }},
    "availability": "{% if product.available %}https://schema.org/InStock{% else %}https://schema.org/OutOfStock{% endif %}"
  }
  {% endif %}
}
</script>

This snippet iterates over all variants and creates an Offer object for each, including size and color when the Shopify option name matches. The url field includes the variant query parameter so AI agents can link to the specific variant.

WooCommerce

WooCommerce requires a PHP hook in your theme’s functions.php or a custom plugin:

add_action('wp_head', function() {
    if (!is_product()) return;
    global $product;
    $variants = $product->get_children();
    if (empty($variants)) return;
    
    $offers = [];
    foreach ($variants as $variant_id) {
        $variant = wc_get_product($variant_id);
        $attributes = $variant->get_attributes();
        $offer = [
            '@type' => 'Offer',
            'sku' => $variant->get_sku(),
            'price' => $variant->get_price(),
            'priceCurrency' => get_woocommerce_currency(),
            'availability' => $variant->is_in_stock()
                ? 'https://schema.org/InStock'
                : 'https://schema.org/OutOfStock',
        ];
        foreach ($attributes as $name => $value) {
            $name_lower = strtolower($name);
            if (strpos($name_lower, 'size') !== false) {
                $offer['size'] = $value;
            } elseif (strpos($name_lower, 'color') !== false || strpos($name_lower, 'colour') !== false) {
                $offer['color'] = $value;
            }
        }
        $offers[] = $offer;
    }
    
    $schema = [
        '@context' => 'https://schema.org',
        '@type' => 'Product',
        'name' => $product->get_name(),
        'offers' => $offers,
    ];
    
    echo '<script type="application/ld+json">' . json_encode($schema) . '</script>';
});

Note: this adds a second JSON-LD block alongside any schema generated by your SEO plugin. Test that the two blocks do not conflict. Some SEO plugins allow you to disable their product schema output so you can replace it with your own.

Custom and Headless (Hydrogen, Next.js, etc.)

Headless stores have full control over schema output. The recommended approach is to render variant data server-side so AI crawlers can read it without JavaScript execution. Generate JSON-LD in your server-side rendering function or API route.

For Hydrogen (Shopify headless), pull variant data from the Storefront API GraphQL response:

function generateProductSchema(product) {
  const offers = product.variants.nodes.map(variant => ({
    "@type": "Offer",
    "sku": variant.sku,
    "price": variant.price.amount,
    "priceCurrency": variant.price.currencyCode,
    "availability": variant.availableForSale
      ? "https://schema.org/InStock"
      : "https://schema.org/OutOfStock",
    "url": `https://yourstore.com/products/${product.handle}?variant=${variant.id}`,
    ...variant.selectedOptions.reduce((acc, opt) => {
      const name = opt.name.toLowerCase();
      if (name === 'size') acc.size = opt.value;
      if (name === 'color' || name === 'colour') acc.color = opt.value;
      return acc;
    }, {})
  }));

  return {
    "@context": "https://schema.org",
    "@type": "Product",
    "name": product.title,
    "gtin14": product.variants.nodes[0]?.barcode,
    "image": product.variants.nodes.map(v => v.image?.url).filter(Boolean),
    "offers": offers
  };
}

For more on headless advantages for AI agent discoverability, see our headless commerce AI discoverability guide.

Common Mistakes That Kill Variant Visibility

Mistake 1: Relying on Meta Tags Instead of JSON-LD

Some Shopify apps and WooCommerce plugins add variant data as HTML meta tags (<meta property="product:price:amount" content="129.99">). These are readable by Facebook and some social platforms but are ignored by most AI agents. JSON-LD is the primary extraction format for ChatGPT, Perplexity, and Google AI.

Mistake 2: Outputting Only the Selected Variant

Many stores dynamically update their JSON-LD to reflect the currently selected variant. This means the schema in the initial HTML source (what AI crawlers read) always shows the default or first variant. All variants should be present in the initial page source JSON-LD, not just the selected one.

Mistake 3: Using Generic Variant Names

Schema that says "size": "L" is less useful to AI agents than "size": "EU 44 / US 10" because agents must match user queries that may specify any regional sizing convention. Include multiple sizing systems when applicable.

Mistake 4: Missing Variant-Level Images

If your Product schema image array contains only one generic shot, AI agents cannot display the correct color or style. Include variant-specific images mapped to each Offer or use the image property on individual Product variants when using the ProductGroup pattern.

Mistake 5: Ignoring Out-of-Stock Variants

Some stores filter out-of-stock variants from their schema entirely. This creates a problem: AI agents that previously recommended a specific variant will suddenly lose it from their data, potentially dropping your product from recommendations altogether. Mark out-of-stock variants with OutOfStock availability instead of removing them.

Measuring the Impact of Variant Schema

After implementing variant-level schema, track these metrics to quantify the impact.

AI citation rate by variant-specific queries. Use Google Search Console and AI-specific tracking to measure how often your products appear for queries that include size, color, or material terms. Before variant schema, these queries typically return generic product links or competitor results.

Click-through rate on variant-specific citations. When AI agents link to a specific variant URL (Pattern 2), the CTR from AI referral traffic should be measurably higher than generic product links because the user lands on the exact product they requested.

Conversion rate from AI-referred traffic. Users who arrive from an AI recommendation for a specific variant have higher purchase intent than those who arrive from a generic product search. Track conversion rates separately for variant-specific vs generic AI referrals.

According to data from the Shopti.ai platform across 40 ecommerce stores that added variant-level schema between March and May 2026, variant-specific AI citations increased by an average of 2.1x within 45 days of implementation. Stores using Pattern 2 (separate variant URLs) saw the largest gains at 2.8x, compared to 1.6x for Pattern 1 (nested Offers).

FAQ

Do I need separate URLs for each product variant?

Not necessarily. Google and AI agents support both single-URL (nested Offers) and multi-URL (ProductGroup with variant pages) approaches. Separate URLs give AI agents a specific link to cite, which can improve click-through rates. But nested Offers on a single page also work well if the variant data is complete. Choose based on your platform capabilities and URL structure preferences.

How do I handle variants with different prices?

Include the variant-specific price in each Offer object. AI agents compare prices across variants and across stores. If your base Product schema shows one price but the variant the user wants costs more, the agent may recommend your product at the wrong price, leading to bounce-back behavior and lower trust scores.

What about apparel sizing systems (EU, US, UK)?

Include the primary sizing system your customers use and add alternative systems in the description or via additionalProperty. For example: "size": "EU 42" with "additionalProperty": [{"name": "US Size", "value": "10"}, {"name": "UK Size", "value": "8"}]. AI agents cross-reference sizing systems, so providing multiple improves match accuracy.

Will adding variant schema slow down my page load?

No. JSON-LD is a static script tag in the page HTML. Adding 5-10 variant Offers adds roughly 1-3 KB to the page size, which has negligible impact on load time. The schema is parsed by crawlers and agents, not by the browser rendering engine.

How do I validate variant schema?

Use Google’s Rich Results Test (search.google.com/test/rich-results) for merchant listing validation, and the Schema Markup Validator (validator.schema.org) for full schema compliance. Both tools will show whether your variant Offers are correctly parsed. For AI-specific validation, test your product pages through the Shopti.ai discoverability audit, which checks variant data extraction across multiple AI platforms.

Sources

  1. Google Merchant Listing Structured Data Documentation - Official documentation for Product schema with variant support, size specification, and Offer requirements. developers.google.com/search/docs/appearance/structured-data/merchant-listing
  2. BrightEdge AI Overviews Data (2026) - Research showing AI Overviews now appear on 15.69% of search queries with product variant queries triggering AI results at 2.3x the base rate. brightedge.com/resources/research-reports
  3. Semrush Ecommerce Schema Audit (2026) - Analysis of 12,000 ecommerce product pages showing 73% of multi-variant products lack variant-level structured data. semrush.com/blog/
  4. Schema.org Product and ProductGroup Specification - Canonical reference for Product type properties including size, color, additionalProperty, and ProductGroup with variesBy. schema.org/Product, schema.org/ProductGroup

Check your store’s agent discoverability score free at shopti.ai.