In brief
- Dead stock is stock that has stopped turning into sales. Measured at cost, it is cash you have already paid out and will not see again until it sells.
- The checker sorts every variant with stock by days since its last sale: under 90 days, 90 to 179, 180 to 364, a year or more, or never sold. Stock that still sells, but too slowly to clear in 180 days, counts as slow.
- It values each variant at units on hand × cost per item, ranks them by that cash, and suggests a markdown that never prices under cost plus 5%.
- It runs Store Diagnosis's own dead-stock code in your browser. Your files are not uploaded, and the page's security policy does not let them be.
How the checker decides
Every variant with stock goes into exactly one group, from the date of its last sale in your orders. The groups and their names are the ones Mufatech Clearance uses for "How old is your stock", and the money in them adds up to the money in stock to the cent.
| Group | Rule | Suggested first move |
|---|---|---|
| Never sold | In stock, and not in a single order in your export | 35% off, then check the listing |
| A year or more | Last sale 365 days ago or more | 40% off plus 5 points for each extra quarter unsold, up to 55% |
| 180–364 days | Last sale 180 to 364 days ago | About 40% off, stop reordering |
| 90–179 days | Last sale 90 to 179 days ago | About 25% off |
| Selling slowly | Still selling, with more than 180 days of stock at the pace of the last 90 days | Keep the price, stop reordering |
| Season ahead | Sold well last year in the 90 days now ahead, and still sells a little now (needs a year of orders) | Wait for its season |
| New stock | First sale less than 30 days ago | Nothing yet |
| Selling | Everything else | Nothing |
Thresholds are Store Diagnosis's defaults. "Not selling" in the report is the four orange groups at the top; "stuck" adds slow stock.
- Cash tied up is units on hand × cost per item. Where cost per item is empty, the checker assumes a 50% margin, marks the row "cost estimated" and says how many it guessed.
- The dead stock score is 100 − 100 × (never sold + 180 days or more + half of 90–179 days + a quarter of slow) ÷ all stock at cost. 100 means no money is stuck.
- The markdown is rounded down to a 5% step and never prices a unit under its floor, cost plus 5%. If the floor leaves less than 5% of room, it suggests a bundle with a steady seller, or clearing the stock another way, instead of a discount.
- Days of stock is units on hand ÷ the daily pace of the last 90 days, counted over the days the variant could actually sell. "No sale in 90 days" means there is no pace to divide by.
For the same products, stock and orders, the figures are the ones Store Diagnosis shows: the checker is its dead-stock engine, bundled for the browser, and the page's tests run both on Diagnosis's demo store and compare every variant to the cent. One difference is the file format's: a product export has no "date added", so a variant with no sale at all is listed as never sold even if you added it last week. Store Diagnosis reads that date from your store and leaves stock under 30 days old alone.
How to export the files from Shopify
You need to be the store owner or a staff member who can export products and orders. Large exports are emailed to you rather than downloaded, so keep your inbox open.13
- Products export. In your Shopify admin go to Products and click Export. Choose All products and CSV file for Excel, Numbers, or another spreadsheet program, then Export products. For all products Shopify emails the file to you.1 The checker reads the handle, title, SKU, options, price, Cost per item, Inventory quantity and status. Fill in cost per item first if you can: it is "how much it costs you to make or acquire the product or variant", and without it every figure is an estimate.2
- Orders export. Go to Orders, click Export, choose All orders (or Orders by date covering at least the last 13 months), pick the CSV format and click Export orders, not "Export transaction histories". More than 50 orders are emailed to you; a very large store can wait an hour or more.3 The checker reads the order number, date, status, currency and each line item's quantity, name, price and SKU. The export also holds your customers' emails, names, addresses and phone numbers;3 the checker skips those columns as it reads.
- Inventory export (optional). The products file's inventory quantity is meant for stores with one location.2 With more than one, go to Products › Inventory, click Export, choose All locations, All states, All variants and the CSV format, then Export inventory.4 The checker adds up On hand across locations, which is what Store Diagnosis counts; with the "Available" layout it adds up the location columns.
- Drop the files above. All at once is fine: the checker reads each file's header to tell which is which. A 50 MB orders file takes a few seconds; the page stays usable while it reads.
Export every order
A variant whose last sale is older than your orders file looks as if it never sold. An export of the last 90 days turns everything that sold 100 days ago into "never sold". Take all orders, or at least 13 months, which also lets the checker spot seasonal stock.
Why nothing is uploaded, and how you can check
An orders export is a list of your customers. It should not go to a website to answer a question about stock, so the checker is built so that it cannot:
- The files are read in this tab. The checker hands them to a Web Worker, a background script of this page, which reads each file in 1 MB pieces straight from your disk. Only the summary you see comes back to the page.
- Customer columns are never kept. In the orders file the reader keeps nine columns: order number, date, cancelled date, financial status, currency, and the line item's quantity, name, price and SKU. Every other cell, including email, billing and shipping names and addresses, phone numbers and notes, is skipped as it is parsed and never stored. The report lists the columns it skipped.
- The page is not allowed to send your data anywhere. Its Content Security Policy permits connections to one address only, Cloudflare's cookieless page-view counter, and our code never calls it; the worker that reads your files is served with a policy that permits no connections at all.6 Browsers enforce these rules themselves.
- The download is made here. The results CSV is built in memory and saved by your browser.
To check for yourself, open your browser's developer tools on the Network tab, then drop your files. The only new request is the checker's own code, engine.js, fetched once, and nothing is sent after it. Its source, and the page's app.js, contain no network call at all. Close the tab and the data is gone.
Do it by hand in a spreadsheet
The checker saves the work, but the method is simple enough to do yourself with the same two exports:
- In the products export, keep the rows with stock above zero and add a column for cash tied up = inventory quantity × cost per item.
- In the orders export, leave out cancelled orders, then find the latest Created at for each Lineitem SKU. A pivot table with SKU as rows and the maximum of Created at as the value does it.
- Look up each product row's SKU in that pivot and add days since last sale = today − last sale. No match means it never sold in the file.
- Group the rows into 90–179 days, 180–364 days, a year or more and never sold, total the cash in each, and sort the whole list by cash tied up, largest first.
- For each row at the top, the floor is cost × 1.05, and the deepest markdown it allows is 1 − floor ÷ price. Start at 25% for 90–179 days and 40% for 180 days or more, never deeper than the floor allows. The markdown calculator adds card fees, shipping, returns and VAT to the floor.
The dead stock guide covers the Shopify reports that help, the formulas and the pitfalls, such as variants without a SKU, which order exports cannot match.
Every night, automatically: Store Diagnosis
Exports go out of date the day after you make them. Store Diagnosis is our free, read-only Shopify app, live on the Shopify App Store. It runs this same dead-stock engine on your store every night, from live stock, cost and every order, with each product's real date added, so new stock is never called dead. Each finding shows the arithmetic, the markdown and the steps to do it in your admin. It never changes a price.
Store Diagnosis, free and read-only.
- Dead, stale and slow stock valued at cost, every night
- A markdown that stays above cost
- Best-sellers about to run out
- Discounts and refunds that cost margin
Mark it down safely: Mufatech Clearance
Mufatech Clearance is the app that changes the prices. It takes the stuck stock this checker finds, marks it down step by step as it ages, previews every change, blocks any price under your floor, and puts back exactly the prices it changed when a sale ends. It is coming to the Shopify App Store and cannot be installed yet. When it is listed it will have a Free plan for up to 3 campaigns and 200 variants, Pro at $3.99 a month, and Plus at $7.99 a month.
Frequently asked questions
Are my files uploaded anywhere?
No. The files are read by a script running in your browser tab, and the page's security policy does not allow it to send them anywhere: the page may connect only to Cloudflare's cookieless page-view counter, which our code never calls, and the worker that reads your files may not connect at all. Customer columns in the orders file are skipped as they are read. You can watch the Network tab in your browser's developer tools while it runs.
Which Shopify exports do I need?
The products export (Products › Export) and the orders export (Orders › Export), both as CSV. Add the inventory export (Products › Inventory › Export) if you stock more than one location. Export all orders, or at least the last 13 months, so every variant's last sale is in the file.
Why does a product I added last week show as never sold?
A Shopify product export has no date added, so the checker cannot tell a new product from an old one that never sold. Products that have sold are dated from their first sale, and those first sold less than 30 days ago are left alone. Store Diagnosis reads the real date from your store and does not have this gap.
How is the dead stock score worked out?
It is 100 minus the share of your stock at cost that is stuck, weighted by how stuck it is: stock that never sold or has not sold for 180 days or more counts in full, 90 to 179 days counts by half, and slow stock by a quarter. 100 means nothing is stuck. It is the dead-stock score Store Diagnosis shows.
How is the suggested markdown worked out?
It starts at 25% for stock without a sale in 90 to 179 days, 35% for stock that never sold and 40% for 180 days or more, adding 5 points for each further 90 days unsold, up to 15 points more and never above 60%. It is rounded down to a 5% step and never prices under the floor, cost plus 5%. If the floor leaves less than 5% of room, the checker suggests a bundle or another way to clear the stock.
Will it handle a big orders file?
Yes. Files are read in 1 MB pieces, and only the columns the checker needs are kept, so a 50 MB orders export is read in a few seconds on a laptop without the page freezing.
Sources
- Shopify Help Center. Exporting products: Products › Export, the choice of products and file type, and when the file is emailed rather than downloaded, checked 10 Oct 2026. vendor-published
- Shopify Help Center. Using CSV files to import and export products: the product CSV columns, including Cost per item and Inventory quantity, which applies to stores with a single location, checked 10 Oct 2026. vendor-published
- Shopify Help Center. Exporting orders: Orders › Export, emailed exports above 50 orders, and the order CSV columns, including Email, Phone and the billing and shipping name and address columns, checked 10 Oct 2026. vendor-published
- Shopify Help Center. Inventory CSV files: Products › Inventory › Export, the All states and Available layouts and their columns, checked 10 Oct 2026. vendor-published
- Mufatech Studio. How accurate Store Diagnosis is: the demo store with known answers that this checker's tests also use. first-party
- MDN Web Docs. CSP: connect-src: the directive that restricts the URLs a page's scripts can load with fetch, XMLHttpRequest, WebSocket, EventSource and sendBeacon. reference