Unadhi Guides

Broken size run sheet for clothing and shoe shops: which sizes each style has sold out of, from the shop's own product data

Updated 24 Oct 2026 · Disclosure: the product data scraper linked below is an Unadhi product on the Apify Store. This guide is free, and the idea also works with the free exports from your own Shopify admin. Current Apify pricing is only on the Store page. This page has no affiliate links and nobody paid to be mentioned.

What you get: a broken size run list in one Google Sheet, built from a web shop's public product data. It has one row per product: product name, shop, link, how many sizes or variants are offered, how many are in stock, which ones are sold out (for example White / M), which of your core sizes are missing, a share-in-stock figure and a Status column (Sold out / Broken run / Some sold out / Full run). Sort by Status every Monday and you know which styles to reorder before Black Friday and Christmas, and which to move to markdown. Formulas are below. The example rows are made up.

The finished sheet

sizerun tab (example rows are made up; core sizes in settings: S, M, L)

ProductOfferedIn stockSold outCore sizes missingShare in stockStatusNext step
Linen shirt, white42M, LM, L50%Broken runReorder M and L
Cotton tee65White / MM83%Broken runReorder white M
Wool jumper, navy54XS80%Some sold outLeave
Canvas tote11100%Full run
Silk scarf, rust10Default Title0%Sold outHide or reorder

The cotton tee row shows why the sheet works per variant, not per product: the product is still "in stock" because five of six variants are, but a customer looking for a white medium finds nothing.

Who this is for

Owners and merchandisers of small clothing, footwear and lingerie shops that sell online, and buyers at multi-brand boutiques who want to see which sizes a brand's own web shop has run out of. A style that has sold out of its middle sizes but still has XS and XXL looks "in stock" on a product list, yet it no longer sells. This sheet puts those styles at the top.

Step 1: get the products into a tab named scrape

With the product data scraper

Open the E-commerce Product Data Scraper (Shopify, WooCommerce, any shop) on the Apify Store and use this input with the shop's address:

{ "startUrls": [{ "url": "https://your-shop.example" }],
  "maxProductsPerShop": 2000, "includeDescription": false }

The scraper follows robots.txt and reads the shop's terms page. If the terms forbid automated access (Shopify's default terms do), it skips the shop and charges nothing. Check the run's Storage → Key-value store → SHOPS_SUMMARY: the shop should show ok. If it shows blocked-by-terms, use the free admin route below for your own shop, and leave other shops alone.

In the run, export the dataset as CSV. In your Google Sheet use File → Import → Upload, "Insert new sheet", and name the tab scrape. Do not rename the headers.

What the variant columns contain

Free, from your own Shopify admin

Products → Export gives one row per variant with the option values (Option1 Value, Option2 Value and so on), and the inventory export gives stock per variant and location. With those you can count sold-out sizes per product in a pivot table instead of using the formulas below. Your admin also shows quantities, which public data does not.

Step 2: the settings tab

Add a tab named settings. In B1 type your core sizes, separated by commas, exactly as they appear in variant titles: for example S, M, L, or 8, 10, 12, 14, or UK 6, UK 7, UK 8. A style missing any of these counts as a broken run.

Step 3: build the sizerun tab

Add a tab named sizerun. Row 1 holds the headers below; row 2 holds the formulas, which you copy down one row per row of scrape.

ColHeaderFormula (row 2)
AProduct=IFERROR(INDEX(scrape!$A2:$ZZ2, MATCH("title", scrape!$A$1:$ZZ$1, 0)), "")
BShopsame pattern with "shop"
CLinksame pattern with "url"
DOffered=IFERROR(COUNTA(FILTER(scrape!$A2:$ZZ2, REGEXMATCH(scrape!$A$1:$ZZ$1, "^variants/\d+/title$"), scrape!$A2:$ZZ2<>"")), 0)
EIn stock=IFERROR(COUNTA(FILTER(scrape!$A2:$ZZ2, REGEXMATCH(scrape!$A$1:$ZZ$1, "^variants/\d+/available$"), UPPER(scrape!$A2:$ZZ2&"")="TRUE")), 0)
FSold out=IFERROR(TEXTJOIN(", ", TRUE, FILTER(FILTER(scrape!$A2:$ZZ2, REGEXMATCH(scrape!$A$1:$ZZ$1, "^variants/\d+/title$")), UPPER(FILTER(scrape!$A2:$ZZ2, REGEXMATCH(scrape!$A$1:$ZZ$1, "^variants/\d+/available$"))&"")="FALSE")), "")
GCore sizes missing=IF(F2="", "", IFERROR(TEXTJOIN(", ", TRUE, FILTER(TRIM(SPLIT(settings!$B$1, ",")), ISNUMBER(SEARCH("/ "&TRIM(SPLIT(settings!$B$1, ","))&" /", "/ "&SUBSTITUTE(F2, ", ", " / ")&" /")))), ""))
HShare in stock=IF(N(D2)=0, "", E2/D2) (format as %)
IStatus=IF(A2="", "", LET(s, UPPER(IFERROR(INDEX(scrape!$A2:$ZZ2, MATCH("inStock", scrape!$A$1:$ZZ$1, 0)), "")&""), IF(s="FALSE", "Sold out", IF(D2=0, IF(s="TRUE", "In stock, no size data", "Check"), IF(G2<>"", "Broken run", IF(F2<>"", "Some sold out", "Full run"))))))
JPricesame pattern as A with "price"
KNext stepyou type: reorder / markdown / hide / ask brand / leave

Notes on the formulas:

Step 4: the Monday routine

  1. Run the scraper again (or re-export from your admin) and re-import the scrape tab with "Replace current sheet". The sizerun formulas and your Next step notes stay, but check that row order still matches if products were added; sorting scrape by title before importing keeps it stable.
  2. Add a filter on sizerun and show only "Broken run". These are the styles to reorder first.
  3. Styles that stay "Broken run" for several weeks and that you will not reorder are markdown candidates: the remaining sizes are what customers can still buy.
  4. For a brand you stock, a broken run on the brand's own web shop can mean the brand itself is short of those sizes. Ask your rep before you plan a reorder around it.

Check before you act on it

Partner programme opening soon

Partner programme opening soon: join the free waitlist. Planned terms are 50% of each referred sale (75% once you have 5+ paying customers), single level, paid through Gumroad only from revenue received.

Sources

Related

← All guides

Unadhi Guides are free, independent explainers. We correct errors as soon as we find them: write to mininglife7@gmail.com.