Structured Data Guide

Shopify Product Availability Structured Data

How AI shopping agents use product availability signals — InStock, OutOfStock, PreOrder, BackOrder, LimitedAvailability — to filter recommendations, and the Liquid patterns that keep your availability structured data accurate at scale.

TL;DR Availability is a hard filter in AI agent product recommendations. A product with OutOfStock in JSON-LD is excluded regardless of how strong its other signals are. A product with stale InStock data that's actually out of stock creates a bad user experience that AI agents penalize. The solution is dynamic Liquid-driven availability — never hardcode "InStock" — combined with per-variant Offer blocks that expose variant-level stock state.

The schema.org ItemAvailability Enum

schema.org defines nine ItemAvailability values. Shopify's default JSON-LD only uses two. Understanding all nine helps you represent complex inventory situations accurately:

Value schema.org URL When to use AI agent behavior
InStock .../InStock Product available for immediate purchase and shipment Eligible for all recommendation types
OutOfStock .../OutOfStock Product currently unavailable; no ETA given Excluded from most recommendations; may appear in comparison queries with caveat
PreOrder .../PreOrder Not yet available but accepting orders before release/restock Eligible for pre-order recommendation type; requires availabilityStarts
BackOrder .../BackOrder Product orderable but will ship after a delay (in manufacturing or transit) Eligible for recommendations with shipping delay context
LimitedAvailability .../LimitedAvailability Available but low quantity (use when stock < threshold) May surface with "limited stock" urgency framing in recommendations
Discontinued .../Discontinued Product permanently removed from sale Excluded from all current-product recommendations; may appear in historical/compare queries
SoldOut .../SoldOut Specific run or edition sold out (implies possible future restock) Similar to OutOfStock; some agents treat as temporary
OnlineOnly .../OnlineOnly Available for purchase online but not in physical stores Eligible for online recommendations; excluded from "find in store" queries
InStoreOnly .../InStoreOnly Only available at physical retail locations Excluded from online shopping recommendations

Shopify Liquid: Dynamic Availability Mapping

Shopify exposes several inventory properties in Liquid. The correct approach is to derive the schema.org availability value dynamically from these properties — never hardcode "InStock".

Basic availability mapping

{%- assign availability = 'https://schema.org/OutOfStock' -%}
{%- if product.available -%}
  {%- assign availability = 'https://schema.org/InStock' -%}
{%- endif -%}

"availability": {{ availability | json }}

Extended mapping with PreOrder and LimitedAvailability

{%- assign availability = 'https://schema.org/OutOfStock' -%}
{%- assign first_variant = product.selected_or_first_available_variant -%}

{%- if first_variant.available -%}
  {%- if first_variant.inventory_management == 'shopify' and first_variant.inventory_quantity <= 5 -%}
    {%- assign availability = 'https://schema.org/LimitedAvailability' -%}
  {%- else -%}
    {%- assign availability = 'https://schema.org/InStock' -%}
  {%- endif -%}
{%- elsif first_variant.inventory_policy == 'continue' -%}
  {%- comment -%}
    'continue' = "Continue selling when out of stock" — BackOrder pattern
  {%- endcomment -%}
  {%- assign availability = 'https://schema.org/BackOrder' -%}
{%- endif -%}

"availability": {{ availability | json }}

The inventory_policy == 'continue' case maps to BackOrder semantics — the product will be manufactured or restocked and ships after a delay. This is more accurate than OutOfStock for products where "Continue selling" is intentional.

PreOrder pattern

{%- comment -%}
  Set a metafield: product.metafields.custom.preorder_ship_date = "2026-09-01"
  when a product is in pre-order status
{%- endcomment -%}
{%- assign preorder_date = product.metafields.custom.preorder_ship_date -%}
{%- if preorder_date != blank -%}
  "availability": "https://schema.org/PreOrder",
  "availabilityStarts": {{ preorder_date | json }}
{%- else -%}
  "availability": {{ availability | json }}
{%- endif -%}

Variant-Level Availability in Offers

The single most impactful availability improvement for Shopify stores with multiple variants is adding per-variant Offer blocks. Shopify's default JSON-LD generates one Offer for the cheapest available variant — which means out-of-stock variants are invisible to agents, and agents can't recommend in-stock variants of an otherwise "mixed" product.

Per-variant Offer with availability

"offers": [
  {%- for variant in product.variants -%}
  {
    "@type": "Offer",
    "name": {{ variant.title | json }},
    "sku": {{ variant.sku | json }},
    "price": {{ variant.price | money_without_currency | json }},
    "priceCurrency": {{ cart.currency.iso_code | json }},
    "url": "{{ shop.url }}/products/{{ product.handle }}?variant={{ variant.id }}",
    "priceValidUntil": "{{ 'now' | date: '%s' | plus: 2592000 | date: '%Y-%m-%d' }}",
    "availability": "{% if variant.available %}https://schema.org/InStock{% else %}https://schema.org/OutOfStock{% endif %}"
  }{% unless forloop.last %},{% endunless %}
  {%- endfor -%}
]

With this pattern, a product with 8 color variants where 2 are sold out exposes 6 InStock Offers and 2 OutOfStock Offers. AI agents recommending "navy blue version" will find the InStock navy variant and link directly to it via the ?variant=ID URL.

Availability Freshness and priceValidUntil

AI agents assign a freshness score to structured data based on how recently the page was crawled and whether time-sensitive fields like priceValidUntil are current. The relationship between availability and freshness:

Situation Risk Mitigation
InStock product not recrawled in 30+ days Agent may treat availability as potentially stale; lower recommendation confidence Use IndexNow to ping when inventory changes; set priceValidUntil 30 days out
Product goes out of stock between crawls Agent recommends product; user lands on out-of-stock page Implement a stock-change webhook that triggers an IndexNow ping on availability change
priceValidUntil is in the past Some agents treat expired priceValidUntil as "unknown current price" and deprioritize Use a dynamic Liquid date: {{ 'now' | date: '%s' | plus: 2592000 | date: '%Y-%m-%d' }}
BackOrder product with no estimated ship date Agent can't communicate shipping delay to users; may suppress recommendation Add availabilityStarts with estimated restock date from a product metafield

IndexNow on availability change (Node.js webhook example)

// Shopify webhook: inventory_levels/update
app.post('/webhooks/inventory', async (req, res) => {
  const { inventory_item_id, available } = req.body;
  const product = await getProductByInventoryItem(inventory_item_id);

  // Ping IndexNow when availability crosses a threshold
  if (available === 0 || available === 1) {
    await fetch('https://api.indexnow.org/indexnow', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        host: 'yourstore.com',
        key: process.env.INDEXNOW_KEY,
        urlList: [`https://yourstore.com/products/${product.handle}`]
      })
    });
  }
  res.sendStatus(200);
});

Availability Structured Data Checklist

# Check Priority
1 JSON-LD availability uses dynamic Liquid output (product.available check), not hardcoded "InStock" Critical
2 Out-of-stock products have OutOfStock in their Offer, not InStock Critical
3 Pre-order products have PreOrder + availabilityStarts date in JSON-LD High
4 Products with "Continue selling when out of stock" use BackOrder not OutOfStock High
5 Per-variant Offer blocks with variant-specific availability for products with 2+ variants High
6 priceValidUntil is a dynamic date 30 days in the future, not a past or hardcoded date High
7 Low-stock variants (under 5 units) use LimitedAvailability for urgency signals Medium
8 IndexNow ping triggered on inventory change events (webhook or scheduled job) Medium
9 Discontinued products use Discontinued availability and are removed from sitemap Medium

Related Resources

Frequently Asked Questions

Does product availability in JSON-LD affect AI shopping agent recommendations?

Yes, directly. AI shopping agents filter for in-stock products before generating recommendations. A product with availability set to OutOfStock in JSON-LD will be excluded from most AI shopping recommendations even if the crawl was recent and the product is technically back in stock. The reverse is also true: a product with InStock in JSON-LD but actually unavailable at checkout creates a negative user experience that AI agents are increasingly penalizing in citation scores.

What is the correct way to mark a Shopify pre-order product in JSON-LD?

Use availability: https://schema.org/PreOrder combined with availabilityStarts set to the expected ship date. This tells AI agents the product exists and can be ordered but won't ship immediately. AI agents that surface pre-order recommendations (ChatGPT Shopping shows pre-order items with shipping date context) need availabilityStarts to communicate expected delivery. Without it, the PreOrder status alone may suppress the recommendation entirely.

How do I handle variant-level availability in Shopify JSON-LD?

Add per-variant Offer blocks, each with its own availability value. A product with 5 color variants where 2 are out of stock should have 5 Offer blocks: 3 with InStock and 2 with OutOfStock, each linking to the variant-specific URL with ?variant=ID. This lets AI agents recommend the in-stock variants specifically rather than either recommending the out-of-stock product or skipping the product entirely.

What does LimitedAvailability mean in schema.org and when should I use it?

LimitedAvailability signals that the product is available but with limited quantity — typically used when inventory is low (under 10 units) and you want to create urgency signals. AI agents like ChatGPT Shopping can use this to surface "limited stock" framing in recommendations. Use it when Shopify's inventory_quantity is below your low-stock threshold. Avoid using it permanently as a marketing tactic — AI agents apply quality penalties for products with perpetually "limited" status that never sells out.

Audit Availability Accuracy Across Your Catalog

CatalogScan scans your store for hardcoded availability values, missing variant-level Offer blocks, expired priceValidUntil dates, and BackOrder products lacking availabilityStarts — then ranks each issue by its impact on AI shopping agent recommendation eligibility.

Scan your store free