Guide

How to set up COGS

Cost per variant, entered once, applied to every order that contains it. Enter them in the cost modal or bulk-load them by CSV.

What COGS does to every number on the site

Cost of goods sold is the first deduction on the profit ladder, and everything below it inherits whatever you put here. Gross profit is revenue minus COGS. Contribution margin starts from gross profit. Net profit starts from contribution margin. A cost that is wrong by two dollars is wrong by two dollars on every order containing that variant, in every report, for as long as it stands.

This is also the only cost NetNet cannot obtain for you. Shopify knows what you charged; it does not know what you paid your supplier. Ad platforms report their own spend, carriers report their own labels, gateways report their own fees — all of those sync. COGS is the number that has to come from you, which is why it is the first thing set up and the one place worth being slow and careful.

Costs are configuration, not data entry per order

You are not costing orders. You are describing what each variant costs, once, and the calculator applies that description to every order that contains it — past, present and future. Set a cost today and it governs the orders that arrive tomorrow without you touching them again.

The practical consequence is that setup effort scales with catalogue size, not with order volume. A store doing four hundred orders a month across forty variants configures forty things, not four hundred.

Method 1: The cost modal

Best for a handful of variants, or for anything needing a date range. Clicking a cost opens one modal that sets the default cost and any cost periods together — there is no inline editing to half-save.

1.Go to Costs → Product COGS
2.Use the All / Missing / Set up tabs, or search, to find the variant
3.Switch between Product and Variant view with the view toggle
4.Click the cost (or “Set cost”) to open the cost modal
5.Enter a default cost as an amount, or as a margin if you price on markup
6.Add effective_from / effective_to periods if the cost changed on a known date
7.Save — the coverage strip updates to show one more exact cost

Method 2: CSV import

Best for a first load, or any time you are setting more than a dozen costs at once.

1.Click Export CSV — downloads every variant with its SKU, name and current cost
2.Fill in the cost_per_unit column in Excel or Google Sheets
3.Optionally add effective_from and effective_to columns for date-ranged costs
4.Click Import CSV and upload the file
5.Read the validation report: imported, skipped (no matching SKU), and errors
6.Costs match on SKU exactly — confirm SKUs are set on your Shopify variants first

Exact costs, estimated costs, and the difference

A variant with no cost is not skipped. It is estimated from your default margin — average unit price multiplied by one minus that margin — and displayed with a ≈ so you can see at a glance which figures are real. The estimate uses exactly the same formula the profit calculator uses, so what you read in the table cannot drift from what lands in your P&L.

That design is deliberate. The alternative is a dashboard with holes in it, where gross profit is overstated by however much unconfigured stock cost you, and nothing on screen says so. An estimate is honest about being an estimate; a blank is not.

The coverage strip above the table keeps the split visible — how many variants are exact, how many are estimated at your current default margin, and a link to change that margin. When the estimated count stops moving, you are done.

Costs that change over time

Supplier prices move, and a single cost per variant forces a choice between two wrong answers: apply the new price backwards and rewrite history, or leave the old price standing and understate today.

Cost periods remove the choice. Each cost can carry an effective-from and effective-to date, so a price rise in March applies from March while February keeps what it actually paid. Overlapping periods are resolved automatically rather than silently double-counting.

Lookup runs in priority order: country and period, then country and default, then global period, then global default. The most specific rule that covers the order date wins, which means you can add a narrow exception without disturbing anything else.

Landed cost, not invoice cost

The most common costing error is not a typo. It is recording the supplier's price and stopping there, when inbound freight, duty and customs brokerage were also paid to get that unit into the warehouse.

On imported goods the gap is routinely fifteen to thirty percent of the invoice, and it is uneven across a catalogue — heavier and bulkier items absorb more inbound freight per unit. Leaving it out does not just understate cost overall, it distorts the ranking between products, which is the thing the ranking exists to answer.

Divide each shipment's freight and duty across the units in it and add that to the per-unit figure before entering it. If your inbound costs are lumpy, cost periods let you attach a different landed figure to each shipment window.

When the numbers look wrong

A product shows implausibly high margin. It almost always has no cost and no default margin reaching it, or it is a bundle with no component definition, so its COGS is zero and its revenue is pure profit.

Import skipped most of the file. Matching is on SKU, exactly. Blank SKUs in Shopify, a leading space, or a case difference all miss. Export first and fill the file you were given rather than building one from your supplier's spreadsheet.

Historical orders did not change after a cost edit. New costs apply to new orders immediately; existing orders keep their stored values until reprocessed, so the change you made is real but has not yet been pushed backwards.

One variant is dragging a product down. Expand the product. A parent showing a healthy blended margin regularly contains one variant losing money on every unit, and the parent row is the last place that will tell you.

Tips

Set costs at variant level — Size M and Size XL rarely cost the same, and a product-level average hides the difference

Multi-variant products show “Varies” and expand in place into individually editable variant rows

Orders with missing COGS carry a warning badge in the orders list, and the dashboard banners it

Future orders use new costs immediately; historical orders keep their stored values until reprocessed

Bundle COGS sums component cost × quantity, one level deep — currently available via the API only

CSV Format Example
sku,cost_per_unit
PRO-JERSEY-BLUE-M,28.75
PRO-JERSEY-BLUE-L,28.75
PRO-JERSEY-WHITE-M,28.75
CAP-CLASSIC,12.40
TEE-STANDARD-S,19.50
TEE-STANDARD-M,19.50
SAMPLE-PACK,32.80
            

Two columns required: sku and cost_per_unit. SKU must match your Shopify variant SKU exactly.

Frequently asked questions

What happens to orders that arrive before I set a cost?

They are costed with your default margin and shown as an estimate rather than left blank, so the ladder still reconciles. Once you enter a real cost, reprocessing those orders replaces the estimate with the exact figure.

Do I set costs on the product or on the variant?

On the variant. Sizes and colours frequently differ in both supplier price and shipping weight, and a product-level average hides the variant that loses money on every unit. Multi-variant products show “Varies” and expand into individually editable rows.

My supplier raised prices. Does that change last quarter's numbers?

Not unless you want it to. Costs can carry an effective_from and effective_to date, so a price rise applies from the date it took effect and historical orders keep the cost that was true when they shipped.

Why did my CSV import skip rows?

Costs are matched by SKU against your Shopify variant SKUs, exactly and case-sensitively. Rows skip when the SKU is blank in Shopify, differs by whitespace or case, or belongs to a product that has since been deleted. The validation report names every skipped row.

How do I cost a bundle?

Define it as a list of component products with quantities and its cost is the sum of component cost multiplied by quantity. Bundles are one level deep — a component cannot itself be a bundle. This is currently API-only; the interface for it is not built yet.

Scale profitably.

Know what every order made you.

Install Free on Shopify