Optimization Guide

Ecommerce Aggregate Offer Schema — AggregateOffer, Multi-Seller Listing & Price Range Structured Data

AI shopping agents handling queries like "cheapest new iPhone 16 Pro across sellers," "best-rated used MacBook Air under $600," or "compare refurbished vs new Sony headphones pricing" need machine-readable price ranges, seller identities, and condition spectrums on a single product page. Shopify's default single-Offer JSON-LD can't express this. AggregateOffer is the schema.org solution — covering multi-seller marketplace pages, wide price-range variant products, and new-plus-used dual-condition listings.

TL;DR Use AggregateOffer instead of Offer when a product page shows multiple sellers or a price range. Set lowPrice (lowest), highPrice (highest), offerCount (number of distinct offers), and priceCurrency. Include each individual Offer in the offers array with Offer.seller (Organization) and itemCondition. For Shopify multi-variant price ranges, calculate min/max prices in Liquid and conditionally render AggregateOffer vs single Offer.

When to Use AggregateOffer vs Offer

Schema.org's AggregateOffer is a subtype of Offer designed specifically for situations where one product page represents multiple individual offers. The key decision point is whether your page shows one price or a price range that depends on seller or condition selection.

Scenario Use Why
Single seller, one fixed price Offer No aggregation needed — one offer, one price
Single seller, variants with same price Offer Price is not variable — single Offer with eligibleQuantity for sizes
Single seller, variants with different prices AggregateOffer Expresses price range honestly — e.g., S/M/L at $29, XL/2XL at $34
Multi-seller marketplace page AggregateOffer Each seller is a distinct Offer with its own seller, price, condition
New + used condition on one page AggregateOffer Different itemCondition per Offer, different price — aggregate wraps both
Multiple storage/config tiers (64GB/128GB/256GB) AggregateOffer Each configuration is a distinct Offer at its own price point

Shopify's default behavior is to always output a single Offer with the lowest available variant price — even for products where the highest variant price is 3× the lowest. This creates incorrect structured data: an AI agent sees "price: $29" for a product that actually costs up to $89 in the larger size. AggregateOffer corrects this by expressing the honest price range.

Full AggregateOffer Example — Multi-Seller Marketplace Page

The classic marketplace use case: a single product listed by multiple third-party sellers on a Shopify store using the Shopify marketplace framework or a multi-vendor app (WCFM, MultiSafepay MarketPlace, Zegsu).

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Sony WH-1000XM5 Wireless Noise-Cancelling Headphones",
  "description": "Industry-leading noise cancellation, 30-hour battery, multipoint Bluetooth. The Sony WH-1000XM5 available from multiple verified sellers.",
  "sku": "WH-1000XM5",
  "mpn": "WH1000XM5/B",
  "gtin13": "4548736132115",
  "brand": { "@type": "Brand", "name": "Sony" },
  "offers": {
    "@type": "AggregateOffer",
    "lowPrice": "249.00",
    "highPrice": "349.99",
    "priceCurrency": "USD",
    "offerCount": 4,
    "offers": [
      {
        "@type": "Offer",
        "price": "249.00",
        "priceCurrency": "USD",
        "availability": "https://schema.org/InStock",
        "itemCondition": "https://schema.org/UsedCondition",
        "url": "https://example-marketplace.com/products/sony-wh1000xm5?seller=gadgetresale",
        "seller": {
          "@type": "Organization",
          "name": "GadgetResale Pro",
          "url": "https://gadgetresalepro.com",
          "sameAs": ["https://www.trustpilot.com/review/gadgetresalepro.com"],
          "aggregateRating": {
            "@type": "AggregateRating",
            "ratingValue": "4.7",
            "reviewCount": "312",
            "bestRating": "5"
          }
        },
        "description": "Grade A refurbished — 90-day warranty, original accessories included"
      },
      {
        "@type": "Offer",
        "price": "299.00",
        "priceCurrency": "USD",
        "availability": "https://schema.org/InStock",
        "itemCondition": "https://schema.org/RefurbishedCondition",
        "url": "https://example-marketplace.com/products/sony-wh1000xm5?seller=certifiedtech",
        "seller": {
          "@type": "Organization",
          "name": "CertifiedTech Outlet",
          "url": "https://certifiedtech.com",
          "aggregateRating": {
            "@type": "AggregateRating",
            "ratingValue": "4.9",
            "reviewCount": "1240",
            "bestRating": "5"
          }
        },
        "description": "Sony Certified Refurbished — 1-year manufacturer warranty"
      },
      {
        "@type": "Offer",
        "price": "328.00",
        "priceCurrency": "USD",
        "availability": "https://schema.org/InStock",
        "itemCondition": "https://schema.org/NewCondition",
        "url": "https://example-marketplace.com/products/sony-wh1000xm5?seller=audioworld",
        "seller": {
          "@type": "Organization",
          "name": "AudioWorld Direct",
          "url": "https://audioworlddirect.com",
          "aggregateRating": {
            "@type": "AggregateRating",
            "ratingValue": "4.8",
            "reviewCount": "892",
            "bestRating": "5"
          }
        },
        "description": "Brand new in sealed retail box — US warranty"
      },
      {
        "@type": "Offer",
        "price": "349.99",
        "priceCurrency": "USD",
        "availability": "https://schema.org/InStock",
        "itemCondition": "https://schema.org/NewCondition",
        "url": "https://example-marketplace.com/products/sony-wh1000xm5?seller=premiumav",
        "seller": {
          "@type": "Organization",
          "name": "Premium AV Store",
          "url": "https://premiumavstore.com"
        },
        "description": "New sealed box, includes Sony 2-year extended warranty registration"
      }
    ]
  }
}
</script>

The outer AggregateOffer provides the price summary signal (lowPrice: $249, highPrice: $349.99, offerCount: 4). AI agents parsing this can answer "Sony WH-1000XM5 price range" ($249–$350) and "best-rated seller" (CertifiedTech at 4.9★ from 1,240 reviews) from structured data alone, without scraping the page.

Shopify Variant Price Range — AggregateOffer Pattern

The most common single-seller use case for AggregateOffer in Shopify is a product where size, configuration, or storage variant substantially changes the price. The standard Shopify JSON-LD outputs only the lowest variant price, which misrepresents the product to AI agents.

{% comment %} product-schema-aggregate.liquid — AggregateOffer for variant price ranges {% endcomment %}
{% assign prices = product.variants | map: 'price' %}
{% assign min_price = prices | sort | first %}
{% assign max_price = prices | sort | last %}
{% assign offer_count = product.variants | where: 'available', true | size %}

{% if min_price == max_price %}
  {% comment %} All variants same price — use single Offer {% endcomment %}
  {% assign use_aggregate = false %}
{% else %}
  {% assign use_aggregate = true %}
{% endif %}

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": {{ product.title | json }},
  "description": {{ product.description | strip_html | truncatewords: 60 | json }},
  "sku": {{ product.selected_or_first_available_variant.sku | json }},
  "brand": { "@type": "Brand", "name": {{ product.vendor | json }} },
  "offers": {
    {% if use_aggregate %}
    "@type": "AggregateOffer",
    "lowPrice": {{ min_price | money_without_currency | json }},
    "highPrice": {{ max_price | money_without_currency | json }},
    "offerCount": {{ offer_count }},
    "priceCurrency": {{ cart.currency.iso_code | json }},
    "offers": [
      {% for variant in product.variants %}
      {% if variant.available %}
      {
        "@type": "Offer",
        "price": {{ variant.price | money_without_currency | json }},
        "priceCurrency": {{ cart.currency.iso_code | json }},
        "availability": "https://schema.org/InStock",
        "url": "{{ shop.url }}{{ product.url }}?variant={{ variant.id }}",
        "sku": {{ variant.sku | json }},
        "name": {{ variant.title | json }}
      }{% unless forloop.last %},{% endunless %}
      {% endif %}
      {% endfor %}
    ]
    {% else %}
    "@type": "Offer",
    "price": {{ min_price | money_without_currency | json }},
    "priceCurrency": {{ cart.currency.iso_code | json }},
    "availability": {% if product.available %}"https://schema.org/InStock"{% else %}"https://schema.org/OutOfStock"{% endif %},
    "url": "{{ shop.url }}{{ product.url }}"
    {% endif %}
  }
}
</script>

This Liquid snippet conditionally outputs AggregateOffer (when variants have different prices) or a plain Offer (when all variants share the same price). The forloop.last check prevents trailing commas in the Offer array.

itemCondition Spectrum for Refurb and Resale Marketplaces

When AggregateOffer covers products across multiple condition states, the itemCondition on each individual Offer is what enables AI agents to filter by condition. The schema.org OfferItemCondition vocabulary has six values:

itemCondition value Schema.org URL When to use
NewCondition https://schema.org/NewCondition Factory sealed, never used, original packaging
RefurbishedCondition https://schema.org/RefurbishedCondition Restored to manufacturer spec — use for Certified Refurbished, OEM-refurbished, or third-party Grade A refurb with warranty
UsedCondition https://schema.org/UsedCondition Pre-owned, may show wear, may lack original packaging
DamagedCondition https://schema.org/DamagedCondition Visibly damaged, cosmetic defects, sold as-is
OldCondition https://schema.org/OldCondition Vintage/antique items sold because of their age — not just pre-owned
OpenBoxCondition https://schema.org/OpenBoxCondition Opened but unused — returned, display unit, or scratch-and-dent

For each condition tier, add a description on the Offer explaining what that condition means for your specific grading system (e.g., "Grade A: 0–2 minor scratches, battery above 85%, all original accessories"). AI agents use this free-text description alongside the structured itemCondition to answer nuanced condition queries like "like-new condition, no major scratches."

Offer.seller with Trust Signals for Marketplace Pages

When multiple sellers list the same product, the seller identity and reputation are the primary differentiators. The Offer.seller Organization entity can carry trust signals that AI shopping agents use to rank offers beyond just price:

{
  "@type": "Offer",
  "price": "299.00",
  "priceCurrency": "USD",
  "seller": {
    "@type": "Organization",
    "name": "TechVault Pro",
    "url": "https://techvaultpro.com",
    "telephone": "+1-800-555-0199",
    "address": {
      "@type": "PostalAddress",
      "addressCountry": "US",
      "addressLocality": "Austin",
      "addressRegion": "TX"
    },
    "sameAs": [
      "https://www.trustpilot.com/review/techvaultpro.com",
      "https://www.bbb.org/us/tx/austin/profile/electronics/techvault-pro-0000-0000"
    ],
    "aggregateRating": {
      "@type": "AggregateRating",
      "ratingValue": "4.8",
      "bestRating": "5",
      "reviewCount": "2341"
    },
    "vatID": "US-27-3456789"
  },
  "warranty": {
    "@type": "WarrantyPromise",
    "durationOfWarranty": { "@type": "QuantitativeValue", "value": "1", "unitCode": "ANN" },
    "warrantyScope": "All defects, including battery, screen, and all components"
  }
}

The sameAs array pointing to Trustpilot and BBB profiles enables AI agents to cross-reference seller reputation from external verification sources — not just the seller's own claims. AI trust systems trained on marketplace data weigh third-party verification URLs in sameAs as stronger signals than unverifiable internal ratings. See Ecommerce Seller Organization Schema for the full seller trust signal pattern.

5 Common AggregateOffer Schema Mistakes

# Mistake Impact Fix
1 Using single Offer for wide price-range variant products (e.g., $29–$89 by size) AI agents see only the lowest price (Shopify default) and treat the product as a $29 item — buyers reaching the page expecting $29 find the size they want costs $89, causing distrust and exit. Price misrepresentation in structured data also risks Google's product data quality penalties Use AggregateOffer with lowPrice and highPrice reflecting the actual variant price range, and include individual Offer entries for each significantly-priced variant
2 Omitting offerCount from AggregateOffer Google's rich result eligibility for marketplace-style product pages requires offerCount. Missing it reduces the likelihood of the enhanced "N offers" display in search results and signals to AI agents that the aggregation is incomplete Always set offerCount to the integer count of available (in-stock) Offer entries in the offers array
3 No itemCondition on individual Offers in a new+used AggregateOffer Without condition values on individual Offers, AI agents cannot distinguish new from used pricing — "best price for new Sony headphones" queries cannot filter out used-condition offers that are cheaper but not what the buyer wants Set itemCondition on every individual Offer within AggregateOffer — do not rely on AggregateOffer-level condition since it applies to all child Offers equally
4 Seller entity has no aggregateRating or sameAs verification URLs On marketplace pages, buyers rely on seller reputation to choose between equal-price offers. Without aggregateRating on the Offer.seller entity, AI agents have no structured signal for seller quality — all sellers appear equally trustworthy regardless of actual reputation Add aggregateRating to each Offer.seller Organization, and include sameAs pointing to Trustpilot, BBB, or Google Business Profile — these verification links carry stronger trust weight than internal ratings
5 AggregateOffer lowPrice and highPrice inconsistent with actual variant prices If lowPrice/highPrice don't match the actual range of child Offer prices, Google's structured data validator flags it as an error and may reduce rich result eligibility. AI agents that cross-check prices against individual Offer entries may also flag the page as having data quality issues Calculate lowPrice and highPrice programmatically from the same variant data used to populate individual Offer entries — never hardcode them independently

Frequently Asked Questions

When should I use AggregateOffer vs single Offer?

Use AggregateOffer when: (1) multiple distinct sellers list the same product on one page; (2) a product has variants at substantially different price points (different by more than ~15%); (3) the page shows both new and used condition options. Use a single Offer when one seller offers the product at one price, or when all variants share the same price. For Shopify stores, the most common AggregateOffer case is a product where apparel sizes, storage configurations, or material choices drive price differences. See also Shopify ProductGroup Variant Schema for the variant-per-Offer pattern within a ProductGroup.

What is offerCount and why does it matter?

offerCount is the integer number of distinct offers for the product — sellers × conditions. Google uses it for rich result display in search (showing "4 offers from $249" in product panels). AI agents use it as a marketplace signal: a high offerCount suggests competitive pricing across multiple sources. Always compute it from the actual available Offer count — out-of-stock Offers should not be counted. For Shopify variant price ranges, offerCount = number of in-stock variants with distinct price points.

How does Offer.seller work in multi-seller AggregateOffer?

Each Offer in the array has a seller property pointing to an Organization entity: { '@type': 'Organization', 'name': 'Seller Name', 'url': 'https://sellersite.com' }. Add aggregateRating and sameAs (Trustpilot, BBB, Google Business) to the Organization for trust signals. This pattern is identical for both Shopify marketplace apps and multi-vendor stores. For the full seller Organization trust pattern, see Ecommerce Seller Organization Schema.

Can AggregateOffer show new and used condition offers together?

Yes — this is AggregateOffer's primary use case alongside marketplace listings. Include Offer entries with different itemCondition values: NewCondition, RefurbishedCondition, UsedCondition, OpenBoxCondition. The AggregateOffer lowPrice reflects the cheapest offer (usually used) and highPrice the most expensive (usually new). AI agents filtering by condition use itemCondition on individual Offers, not on the AggregateOffer level. For the full condition vocabulary, see Shopify Pre-Owned & Resale Condition Schema.

Does Shopify support AggregateOffer natively?

No — Shopify's built-in product JSON-LD always outputs a single Offer with the lowest variant price. To implement AggregateOffer, add a custom script block in your theme's product.liquid that conditionally renders AggregateOffer when product.price_varies is true (Shopify's built-in flag for products with price-varying variants). Use Liquid to loop through variants and calculate min/max prices. Alternatively, use a structured data app like Schema Plus or Rich Snippets which support AggregateOffer generation automatically. Run a CatalogScan audit to check whether your current theme is outputting correct price ranges or single-price misrepresentation.

Are your multi-variant price ranges misrepresented in structured data?

CatalogScan audits your Shopify store's structured data and identifies products where single-Offer output misrepresents variant price ranges, missing seller trust signals, incorrect itemCondition values, and absent offerCount — ensuring AI shopping agents see accurate pricing and seller data.

Run Free Scan

Related Resources