# AggregateOffer in Schema.org: what it is and when to use it

> What AggregateOffer is in Schema.org, which properties Google asks for, why it doesn't fit your product page's variants and which pages it really suits.

URL: https://clione.ai/glossary/aggregateoffer/
Lang: en

AggregateOffer usually turns up behind one specific question: I have a T-shirt that costs one price in size S and another in XXL, so how do I tell Google "from $X"? **Google's answer is that AggregateOffer is not the way**. It is a type from [Schema.org](/glossary/schema-org/), and it has nothing to do with an offer in the sense of a promotion: "aggregate" means it sums up several. It matters to you because it is an easy mistake in the [structured data](/glossary/structured-data/) of a store with [product variants](/glossary/product-variants/), and because, placed on the wrong page, it shuts the door on one of the two kinds of product [rich results](/glossary/rich-results/) Google has.

## How it works

Schema.org defines AggregateOffer for **when a single product is associated with several offers**, and gives the example of the same pair of shoes sold by different merchants. It descends from [Offer](/glossary/offer-schema/), so it is an offer that sums up other offers, and it adds four properties of its own:[^schema-org-aggregateoffer]

| Property     | What it says                                                 |
| ------------ | ------------------------------------------------------------ |
| `lowPrice`   | The lowest price among all the available offers              |
| `highPrice`  | The highest price among all the available offers             |
| `offerCount` | The number of offers for the product                         |
| `offers`     | The offers it sums up, if you want to detail them one by one |

Google takes the type and narrows it. In its product snippet documentation it describes it as a kind of Offer that represents the sum of other offers, which can be used, for example, for a product sold by several merchants, and adds a line worth reading twice: **do not use AggregateOffer to describe a set of variants of a product**.[^google-product-snippet]

When it is used, Google asks for two properties: `lowPrice` and `priceCurrency`, the currency in three-letter ISO 4217 format. It recommends two more: `highPrice` and `offerCount`.[^google-product-snippet]

And there is a Google experience it does not unlock. Of the two ways Google presents a product, product snippets accept Offer or AggregateOffer, but [merchant listings](/glossary/merchant-listings/) require Offer, because to qualify for them the merchant has to be the one selling the product.[^google-merchant-listing] A store that marks up its own [product page](/glossary/product-page/) with AggregateOffer is describing a comparison site, not a store.

Variants have their own path. Google asks for a [ProductGroup](/glossary/productgroup/) that gathers the variants with `hasVariant`, says with `variesBy` what changes between them (size, color) and carries the parent product's reference in `productGroupID`; each variant is a [Product](/glossary/product-schema/) with its own offer and its own price.[^google-product-variants] The price range, in that model, is not written: it is worked out from each variant's offers.

## In a store

Two pages, two kinds of markup. **Fictional example**: the stores, the product, the prices and the number of offers are made up.

The first is a comparison site that shows the same espresso maker in several stores. There AggregateOffer fits: the comparison site does not sell, it sums up.

```json
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Lucia stovetop espresso maker, 6 cups",
  "offers": {
    "@type": "AggregateOffer",
    "lowPrice": "24.90",
    "highPrice": "32.50",
    "priceCurrency": "USD",
    "offerCount": "5"
  }
}
```

The second is the product page of a store that sells that espresso maker in two sizes, each at its own price. There what fits is a group with one offer per variant, as Google describes for variants:[^google-product-variants]

```json
{
  "@context": "https://schema.org",
  "@type": "ProductGroup",
  "name": "Lucia stovetop espresso maker",
  "productGroupID": "LUCIA",
  "variesBy": "https://schema.org/size",
  "hasVariant": [
    {
      "@type": "Product",
      "name": "Lucia stovetop espresso maker, 3 cups",
      "sku": "LUCIA-3",
      "size": "3 cups",
      "offers": { "@type": "Offer", "price": "22.90", "priceCurrency": "USD" }
    },
    {
      "@type": "Product",
      "name": "Lucia stovetop espresso maker, 6 cups",
      "sku": "LUCIA-6",
      "size": "6 cups",
      "offers": { "@type": "Offer", "price": "27.90", "priceCurrency": "USD" }
    }
  ]
}
```

The difference is not a matter of style. In the first case, the page says "there are five offers for this product between this price and that price," which is true on a comparison site. In the second, the page sells, and each size is a product with its price: writing it as a range with AggregateOffer would be describing variants, which is exactly what Google asks you not to do,[^google-product-snippet] and it would leave the product page out of merchant listings.[^google-merchant-listing] Both snippets are trimmed examples: a real product page also carries the image, the availability and the rest of the properties each experience asks for.


Using AggregateOffer to show the price range of the sizes or colors on your own product page. It looks made for that, because it has a lowest and a highest price, but Google expressly rules it out for sets of variants,[^google-product-snippet] and on a page that sells, merchant listings only accept Offer.[^google-merchant-listing]


## How to check

1. **Search for "AggregateOffer" in the source code of your product pages.** If it does not appear, this term does not affect you; if it does, keep going.
2. **See where `lowPrice` and `highPrice` come from.** If they are the prices of your own sizes or colors, the markup describes variants, and Google asks you not to do that with this type.[^google-product-snippet]
3. **Run the URL through the [Rich Results Test](/glossary/rich-results-test/)** and note which experiences it detects. A page where people buy should be able to qualify for a merchant listing, and for that the offer has to be an Offer.[^rich-results-test][^google-merchant-listing]
4. **If your page does compare sellers**, check that it carries `lowPrice` and `priceCurrency`, which are required, and add `highPrice` and `offerCount`, which Google recommends.[^google-product-snippet]


## Related concept: ProductGroup

The underlying confusion is not between AggregateOffer and Offer, which the Offer entry already separates, but between **summing up offers and grouping variants**. AggregateOffer sums up offers for a single product, usually from different sellers.[^schema-org-aggregateoffer] ProductGroup groups products that differ only in something like size or color, and each one carries its own offer.[^google-product-variants] If your page has a size selector, the word you are looking for is ProductGroup; if it has a list of stores selling the same thing, it is AggregateOffer.

To go further, the [structured data reading path](/learn/structured-data/) lays out the rest of the terms, and the guide to [auditing a product page's structured data](/guides/audit-product-page-structured-data/) walks through a product page with variants property by property.
