Product facts

How do I make product variants and stock readable for AI agents?

Give every variant its own URL that preselects it, write each option's name and stock state as text in the page, and describe the product as a ProductGroup with variesBy, one Product per variant and an availability value on each offer. Agents fail when sizes and colours exist only as unlabeled swatches, or when sold out is shown only as a greyed-out button.

Author
Aiscovery team
Published
Updated
Reading time
9 min read

Where variant pickers lose AI agents

Browsing agents read a page through its text, its accessibility tree and screenshots. A picker that a person understands at a glance can carry no words at all. Anthropic's computer use docs note that some interface elements, such as dropdowns, can be tricky for the model to operate with the mouse.

Variant picker problems and what the agent sees
On the pageWhat the agent seesFix
Colour swatches with no textA row of unnamed buttons or imagesA visible or screen-reader label with the colour name
Sold-out size shown greyed out or struck throughA size that looks selectableThe words Sold out in the label, and a disabled control
Price and stock change only after a clickThe first variant's price for every variantA URL per variant that renders its own price and stock
Custom dropdown built from divsText with no control to operateA native select or radio buttons
Stock message loaded by an app after the pageNothing, if it reads the page before the app runsRender the stock state in the HTML

Make the picker readable

  1. Step 1: Label every option in text

    Use radio buttons or a native select with real labels. A swatch can stay visual, but its label must name the colour. Put the stock state in the label too.

    HTML: labeled options with a stock state
    <fieldset>
      <legend>Size</legend>
      <input type="radio" id="size-s" name="size" value="S">
      <label for="size-s">S</label>
      <input type="radio" id="size-m" name="size" value="M" disabled>
      <label for="size-m">M, sold out</label>
    </fieldset>
    <p id="stock-status" aria-live="polite">Olive, size S: in stock, ships in 1 to 2 business days.</p>
  2. Step 2: Give each variant a URL that preselects it

    Shopify themes already use ?variant= with the variant ID. Open one directly and check that the page shows that variant's price, stock and image before you click anything. Google requires this for variant markup.

  3. Step 3: Write stock as words

    In stock, Only 3 left, Sold out, Back order: ships in 2 weeks, Pre-order: ships in March. A colour or an icon alone carries no meaning to an agent.

  4. Step 4: Keep the default variant honest

    If the first variant is sold out, don't preselect it with no message. Preselect an available one, or say clearly that the selected option is sold out and which ones aren't.

Stock states, on-page text and schema.org availability
Your stock stateSay on the pageavailability
In stockIn stockInStock
Low stockOnly 3 leftInStock or LimitedAvailability
Out of stock, can't be orderedSold outOutOfStock
Out of stock, still orderableBack order: ships in 2 weeksBackOrder
Not released yetPre-order: ships on a datePreOrder
Won't come backNo longer availableDiscontinued

Mark up variants as a ProductGroup

Google's variant markup groups variants under a ProductGroup. variesBy names the dimensions (Google supports colour, size, suggested age, suggested gender, material and pattern), hasVariant lists one Product per variant with its own sku or gtin, and productGroupID is the parent SKU. Each variant's offer carries its own price, URL and availability.

  1. Step 1: On Shopify, write your own ProductGroup

    The theme's {{ product | structured_data }} leaves out variesBy, colour and size. Replace that line in the product section with your own JSON-LD, so the page doesn't carry two product groups. This version maps the first option to colour and the second to size; change it to match your options. It marks variants that keep selling at zero stock as BackOrder.

    Liquid: sections/main-product.liquid (Dawn) or your product section
    <script type="application/ld+json">
    {
      "@context": "https://schema.org",
      "@type": "ProductGroup",
      "name": {{ product.title | json }},
      "productGroupID": {{ product.id | json }},
      "url": {{ product.url | prepend: request.origin | json }},
      "variesBy": ["https://schema.org/color", "https://schema.org/size"],
      "hasVariant": [
        {%- for variant in product.variants -%}
        {
          "@type": "Product",
          "name": {{ product.title | append: " - " | append: variant.title | json }},
          "sku": {{ variant.sku | json }},
          "color": {{ variant.options[0].name | json }},
          "size": {{ variant.options[1].name | json }},
          "offers": {
            "@type": "Offer",
            "url": {{ variant.url | prepend: request.origin | json }},
            "price": {{ variant.price | divided_by: 100.0 | json }},
            "priceCurrency": {{ cart.currency.iso_code | json }},
            "availability": "https://schema.org/{% if variant.available %}{% if variant.inventory_policy == 'continue' and variant.inventory_quantity <= 0 %}BackOrder{% else %}InStock{% endif %}{% else %}OutOfStock{% endif %}"
          }
        }{% unless forloop.last %},{% endunless %}
        {%- endfor -%}
      ]
    }
    </script>
  2. Step 2: On WooCommerce, check what core outputs

    Core marks up a variable product as one AggregateOffer with a low and a high price. A URL that selects one variation gets that variation's offer with inProductGroupWithID. For full ProductGroup markup you need an SEO plugin that supports it or the woocommerce_structured_data_product filter.

  3. Step 3: Test a variant URL

    Run a product URL and one ?variant= URL through Google's Rich Results Test, and check that each variant's price and availability match the page.

Check what the store exposes

Both platforms publish product data you can read without logging in. Compare it with what the page shows: if the data says a size is available and the page doesn't say so in words, an agent reading the page misses it.

Terminal: Shopify product JSON and the WooCommerce Store API
# Shopify: variants with price (in cents) and available
curl -s https://yourstore.com/products/your-handle.js

# WooCommerce: public, unauthenticated Store API
curl -s 'https://yourstore.com/wp-json/wc/store/v1/products?stock_status=outofstock'

Checking stock and comparing two products are key shopping tasks in Aiscovery's AI agent test runs. Named AI agents try them on your store in a read-only browser, and the step screenshots show which option they picked and what they read. See how a test run works.

Keep going

Questions store owners ask

Do AI agents read structured data or the visible page?

It depends on the tool. Agents that browse read the visible page, its text and its accessibility tree; search systems that index your store can also read structured data. Make both say the same thing.

Shopify already outputs a ProductGroup. Why change it?

The structured_data filter lists the variants, but on the demo stores we checked it has no variesBy, colour or size, which Google uses to tell variants apart.

What availability should I use for Continue selling when out of stock?

BackOrder, if the variant is at zero or below and still orderable, with the expected ship time on the page. Shopify only offers that setting when inventory is tracked.

Should each variant have its own page?

No. Google supports one page for the group, as long as each variant can be preselected with a distinct URL, such as Shopify's ?variant= parameter.

How many variants can an agent see in Shopify's product JSON?

Shopify's Ajax product JSON contains up to 250 variants in its variants array.

Sources

Every technical claim on this page comes from the vendor's own documentation, checked on the date shown as Updated. Crawler names and settings change, so check the source before you edit a live store.

  1. 01Product variant structured data (ProductGroup, Product)Google Search Central
  2. 02Merchant listing (Product, Offer) structured dataGoogle Search Central
  3. 03structured_data filterShopify.dev
  4. 04Product API reference (Ajax API)Shopify.dev
  5. 05variant (Liquid object)Shopify.dev
  6. 06Selling out of stock productsShopify Help Center
  7. 07class-wc-structured-data.phpWooCommerce on GitHub
  8. 08Store APIWooCommerce Developer Docs
  9. 09Store API: productsWooCommerce Developer Docs
  10. 10Computer use toolClaude Developer Platform

See what AI agents do in your store.

A short call: we run the site check on your store, show what robots.txt tells each AI crawler, and walk through a test run where named AI agents try key shopping tasks.

Have a real workflow to test now? Apply as a launch partner

We only use this to arrange your demo. Privacy notice