Every direct to consumer storefront has a compare-at price. The question nobody
answers with numbers is how much of the catalogue is actually on sale at any moment, and how deep
the discount really goes. Here is a measurement across 6,409 distinct products from 51 Shopify
storefronts.
The headline
2,264 of the 6,409 products, 35.3%, have onSale set. The median discount across those is 43.4%
and the mean is 44.4%. The maximum is 100%, which is its own small story and I will come back to
it.
A third of the catalogue being marked down at once is higher than most people guess. It is also
the number that makes the compare-at price hard to read as a signal: when a third of everything
is permanently discounted, the strikethrough is a pricing style, not an event.
Discount depth is a store level decision, not a product level one
Grouping the sale items by storefront, restricted to stores with at least 50 discounted products
so the medians mean something:
| store | median discount | sale items |
|---|---|---|
| www.everlane.com | 70% | 260 |
| gymshark.com | 70% | 335 |
| www.bando.com | 62% | 53 |
| www.pupford.com | 60% | 52 |
| www.allbirds.com | 57% | 51 |
| parachutehome.com | 54% | 50 |
The tight clustering inside each store is the interesting part. Everlane and Gymshark both land
on a median of exactly 70%, which is not what you would see if discounts were set per product by
someone reading inventory reports. It is what you see when a store runs a sitewide rule and lets
it apply across a whole category at once.
For catalogue size, the sample is led by gymshark.com with 1,162 products, then
www.everlane.com at 385, www.taylorstitch.com at 333, www.tentree.com at 319, outdoorvoices.com
at 276 and japanesetaste.com at 261. Currency is mostly USD at 5,900 products, with GBP at 406
and CAD at 103.
What a row gives you that a product page does not
The useful trick here is that compareAtPrice, discountPercent, inStock and
daysSincePublished all sit on the same row. A product page in a browser shows you the price
today. The row lets you ask whether the thing is actually available at that price, and how long
it has been sitting there.
Take https://reapx.dev/data/shopify-store-products-scraper/a5a9t-nc0s-xs/, a Gymshark Crest
Oversized Zip Up Hoodie in Lifestyle Brown:
compareAtPrice 48
discountPercent 70
inStock False
createdAt 2024-08-09
daysSincePublished 103
imagesCount 6
Seventy percent off, and out of stock. That combination is extremely common in this data and it
is exactly what you cannot see from an aggregator that only reads the advertised price. A second
example, https://reapx.dev/data/shopify-store-products-scraper/b4c8f-bb2j-xxs/, a Juicy Peach
Long Sleeve T-Shirt, shows a compare-at of 54 with the same 70% and the same inStock: False,
44 days after publication.
Across the full set, 5,247 products are in stock and 1,162 are not. So roughly 18% of what is
listed cannot be bought, and the deep discount bucket is disproportionately represented in that
18%. If you are scraping competitor pricing to set your own, filtering on inStock before you
compute anything is the single highest value line of code you will write.
The 100% cases
A discountPercent of 100 means the compare-at price is intact while the price has gone to zero.
These are almost always gift-with-purchase items, samples, or configuration mistakes in the
storefront rather than genuine free products. They are worth excluding from any average, which is
why the median at 43.4% is the number to quote rather than the mean at 44.4%.
The shape of the index
These pages are keyed on SKU, so one page is one purchasable variant rather than one product
family, which is why the slugs look like a5a9t-nc0s-xs with the size on the end. The index is
at https://reapx.dev/data/shopify-store-products-scraper/ and each page cites the runs that
produced its rows. The complete row set, which is what the aggregates above were computed from,
is at https://huggingface.co/datasets/reapxdev/shopify-store-products-scraper.
If you replicate this, watch the deduplication. The raw rows include repeat observations of the
same SKU from different runs, and counting them without collapsing on store plus product id will
inflate every percentage you produce.
Top comments (0)