Shopify's Cost per item doesn't update when you receive stock
You raise a purchase order, the supplier's price has gone up, you receive the delivery — and the cost on the product page is still last year's number. This isn't a bug or a permissions problem. It's how the field works, and it quietly distorts every margin figure you look at afterwards.
Receiving moves quantities, not costs
In Shopify, "each product variant has a single static Cost per item field," and — in Shopify's own words — that cost stays fixed when you receive a purchase order or a transfer.
So the receiving flow does exactly half of what people expect. Stock levels go up by what arrived. The cost stays at whatever someone last typed into the field, whether that was three weeks ago or three years ago.
Two consequences follow, and the second one is the expensive one:
- Your current cost is wrong whenever the last purchase came in at a different price. Margin reports are computed from the field, so they'll read high after a price increase and low after a discount.
- There is no history at all. The field holds one number. Update it, and the old value is gone — there's nothing that records the price you paid on each order, so questions like "has this supplier crept up over the last four orders?" can't be answered from Shopify.
Merchants keep asking for this. There's an open feature request in the Shopify community for a landed-cost field in the purchase-order receiving workflow, and threads going back years asking why receiving doesn't touch product costs.
Three ways merchants keep unit costs true
Ordered from cheapest to most automatic. All three are legitimate — which one fits depends on how many SKUs you buy and how often prices move.
1. Update the field by hand after each delivery
Free, and fine for a handful of SKUs. Use the bulk editor or a product CSV to change many variants at once. Two things to know before you rely on it: you're overwriting the only cost figure you have, so keep the supplier invoice as your paper trail, and if you forget one delivery there's no signal anywhere that the number is stale.
2. Keep a weighted average in a spreadsheet
One row per SKU, one line per receipt: date, quantity, unit price. The weighted average is total spend divided by total units, and it's the number you paste back into Cost per item. It survives audits because every input is visible, and it doubles as the cost history Shopify doesn't keep. The cost is discipline — it's only accurate while someone keeps entering receipts.
3. Let a purchasing app recalculate on receipt
Shopify's own migration guidance says that for weighted-average costing or automatic landed-cost allocation you should use a third-party inventory app. The behaviour to look for is specific: the cost is recalculated when you receive, not when you remember, and the app can write the new figure back to Shopify's Cost per item so your native reports stay honest too.
Weighted average, in one worked example
Say you stock a single SKU and buy it three times:
- March: 100 units at $4.00 → $400
- May: 150 units at $4.40 → $660
- July: 200 units at $4.75 → $950
Total spend $2,010 across 450 units, so the weighted average unit cost is $4.47. If Cost per item still says $4.00 — the March number nobody went back to change — your recorded cost is $0.47 per unit light, which is 10.5% of the true cost. Across those 450 units it's about $210 of margin you think you have and don't.
Two details that trip people up. First, weighted average is computed over units received, not units ordered, so partial deliveries have to be counted as they arrive. Second, if a purchase order is in another currency, the exchange rate at receipt is part of the cost — the same SKU bought at the same supplier price can land at a different cost twice in one year.
FIFO is the other common method: instead of blending, you consume the oldest batch first and each sale carries that batch's cost. It reflects reality more precisely for goods whose price moves fast, and it can't be maintained in a single field at all, because it needs the layers kept separately.
What our app does about it
We build Replenio, so treat this as the interested part of the page.
Replenio is a purchasing app for Shopify — purchase orders, supplier records, barcode receiving — and it recalculates unit cost on every receipt, using weighted average or FIFO, instead of holding one static number. Freight, duty and fees are allocated across the lines that carried them, so the figure is a landed cost rather than just the supplier's price. Each receipt is kept as a dated point, which gives you the per-SKU price trail the native field can't hold.
There's a free plan with no time limit that covers purchase orders, receiving and weighted-average costing on one location, so you can check the numbers against your own invoices before deciding anything.
If a spreadsheet is the right answer for your catalogue size, option 2 above is genuinely fine — the arithmetic is in this page and it doesn't need us.
Frequently asked
Does Shopify update Cost per item when you receive a purchase order?
No. The field is a single static value per variant, and Shopify's documentation says it stays fixed when you receive a purchase order or a transfer. Receiving moves quantities only.
Does Shopify keep a history of what I paid over time?
No. Editing the field replaces the previous value, so there's no per-SKU price trail inside Shopify. That history has to live outside the field — in a spreadsheet, or in an app that records each receipt.
Can Shopify calculate weighted average or FIFO?
Not natively. Shopify's migration guidance points merchants to a third-party inventory app for weighted-average costing and automatic landed-cost allocation.
What does a stale cost do to my reports?
Margin and cost figures use whatever the field currently holds, so a stale number overstates or understates profit on every unit sold from the batches it doesn't reflect.
Can I fix it in bulk instead of product by product?
Yes — the bulk editor and product CSV both write Cost per item across many variants at once. That solves the typing, not the forgetting: nothing flags the field as out of date, so it still depends on someone doing it after every delivery.