Going Stellar

Home/Methods

E-commerce · Unit economics

How to calculate profit per product for a cash-on-delivery store

Profit per product is the contribution each SKU leaves after its own costs: revenue without VAT, minus cost of goods, transport and marketing, counted on delivered orders only. Free gift units carry their real cost, transport comes from the real cost of each order with a fallback cascade, and marketing is allocated per order. The hard part is not the formula but taking each input from the right source.

Updated

What profit per product means for a cash-on-delivery store

Profit per product, in the sense we use, is contribution per SKU: contribution = revenue − COGS − transport − marketing, with revenue, cost of goods (COGS) and transport taken without VAT, and counted only on orders the customer actually received and paid for. Contribution is what a product leaves before fixed costs such as salaries, rent and software. A cash-on-delivery store is one where the customer pays the courier at the door, so an order that is placed but refused brings no revenue at all.

One rule holds the method together: there is a single place where VAT, cost of goods, transport, marketing and delivery status are defined, and every report that computes profit imports that logic rather than rewriting it. When two reports each had their own version of the formula, they disagreed, and nobody could say which one was right.

The steps below are the order in which we build profit per product. Each step names the input and the source it should come from, because almost every wrong number we produced came from a correct formula fed by the wrong source.

Step 1: count only delivered orders, and take delivery from the courier

Profit per product for a cash-on-delivery store starts with the list of delivered orders. Revenue and cost of goods are counted only on orders with a delivered status. Placed orders, cancelled orders and parcels still in transit stay out of the revenue side.

The delivered status should come from the courier's verdict, not from the shop's own status. In a cash-on-delivery shop the payment status often stays pending until someone reconciles it, and a shop's own tracking can mark a parcel as delivered when the courier actually returned it to the sender. We now treat an order as closed only when the courier has given a final verdict, and we re-check everything that has no such verdict.

Delivery also settles slowly. A cash-on-delivery parcel can stay in transit for days, so the current month always looks worse than it will end up. We do not judge a product on a month that is still open.

Step 2: revenue per product line, without VAT

Revenue per product is the product line's share of the order total, divided by (1 + VAT). We take the share by line value: if a line is half of the order's line value, it gets half of the order total. Using the order total rather than the list price spreads discounts and any shipping fee the customer paid across the lines that caused them.

VAT is the rate of the country the order is delivered to, because cross-border stores charge the destination rate. Orders in a foreign currency are converted with the exchange rate for that month before anything is added up. Refunded orders and cash-on-delivery orders that were never collected should count as zero revenue, so the revenue figure must be the order total after refunds, not the original total.

Step 3: cost of goods on every unit, including free gifts

Cost of goods per product is the quantity on the line multiplied by the unit cost of that product, without VAT. The unit cost belongs on the product variant in the shop, and a manual override table catches products whose cost is missing or wrong.

Free gift units count. A gift line has zero revenue but a real unit leaves the warehouse, so the gift line keeps its cost of goods and its quantity. In a per-product report the gift appears as its own line with zero revenue and a real cost, which is exactly what a gift is. The same applies to multi-unit promotions: a 2+1 offer ships three units for the price of two, and all three units carry cost.

A product with no unit cost at all is not free. We list such products separately so that a missing cost cannot quietly turn into a high margin.

Step 4: real transport per order, with a fallback cascade

Transport per product starts at the order: the courier cost of that order's parcel, without VAT, is shared across the order's lines in proportion to their revenue. A gift line with zero revenue therefore carries no transport, and the paid product that triggered the gift carries the parcel.

Real transport costs are not available for every order, so we use a cascade. First, the real cost the courier billed for that order. Second, if that is missing, the average real cost previously billed for parcels containing the same SKUs. Third, a flat cost per parcel for the store. Every order is labelled with the level it came from, and the report warns which products rely on estimates, because a product whose transport is estimated has an approximate profit.

Courier cost tables need care. A per-parcel table can hold the same parcel twice, which multiplies the cost if you add it up, while taking only one cost per order misses return legs and extra parcels. The rule is: remove duplicates first, then sum every leg the courier actually billed.

Step 5: marketing allocated per order

Marketing per product is the advertising cost that can be traced to the product, divided across that product's delivered orders. Where an ad names an exact SKU, its cost goes to that SKU. Where an ad names a product group, its cost is shared across the group's SKUs in proportion to their number of orders. Where only the brand is known, the cost is shared across all the brand's sold SKUs, again by orders. Test campaigns are kept out of product allocation.

Allocating per order means every order of a brand carries the same advertising cost, a uniform cost per acquisition (CPA). We allocate by orders rather than revenue because advertising buys orders; a revenue weighting would push the cost of cheap products onto expensive ones. How to trace ads to products when ads do not map one-to-one is a separate method that we describe in its own article.

Marketing should be net of VAT, and any spend that cannot be allocated to a sold product is reported as unallocated rather than dropped, so the per-product total can be reconciled with the advertising accounts.

A worked example with hypothetical numbers

The numbers below are round and hypothetical, chosen to make the arithmetic easy. They do not come from any store we run.

One delivered order: product A at 120 including VAT, plus a free gift unit of product B. VAT is 20%. Unit cost of A is 30, unit cost of the gift is 5. The courier billed 12 without VAT for the parcel. Product A had 100 delivered orders in the month and 1,500 of advertising traced to it.

Step 1. Revenue without VAT: 120 ÷ 1.2 = 100, all on line A, since the gift line has zero value.

Step 2. Transport: the whole 12 goes to line A, its share of revenue.

Step 3. Marketing per order: 1,500 ÷ 100 = 15 on line A.

Step 4. Line A: 100 − 30 − 12 − 15 = 43. Line B, the gift: 0 − 5 = −5. The order leaves 38.

If the gift line is dropped, the order appears to leave 43, and the gift stock disappears from the books without a cost. If transport is taken from a flat estimate instead of the real 12, product A moves by the difference on every order.

Where we were wrong

We trusted a derived cache for delivered orders. A summary table built from the profitability engine undercounted delivered orders on a recent window by about 1.6 times compared with the delivery source, which made profitable stores look like losses. We now confirm delivered orders, cost of goods and spend at their sources before any decision about money.

We skipped free gift lines. Our per-product report used to leave out lines with zero revenue. The gift's cost vanished, and products that came with a gift looked better than they were.

We read an intermediate courier status as a final refusal. A status meaning the parcel was back at the courier's office was mapped as refused, and the parcel then left the re-tracking queue, frozen. Orders that were later delivered sat in the refused column.

We let the shop's own tracking decide delivery. When the shop began tracking parcels itself, returned parcels with a delivered event in their history were counted as delivered, and a nightly resync rewrote correct statuses with empty ones.

Limits, and a short checklist

Profit per product is a contribution, not net profit: fixed costs are excluded. Our per-product report charges transport only on delivered orders, while the brand-level profit and loss charges every parcel that left, delivered, in transit or refused. A product that is refused often therefore looks better per product than it is, and its refusal rate has to be read next to its contribution. Marketing allocation is a model, and its quality depends on how well ads name their products.

Checklist: delivered orders only, from the courier's verdict; revenue as a line's share of the order total after refunds, without VAT at the destination rate, converted to one currency; cost of goods on every unit, gifts included, missing costs listed; transport real per order, then SKU average, then flat, with the source labelled; courier rows deduplicated before summing; marketing allocated per order, tests excluded, unallocated spend reported; a month judged only once delivery has settled.

Questions and answers

How do you calculate profit per product in a cash-on-delivery store?

Take only delivered orders. For each product line, revenue is its share of the order total divided by (1 + VAT). Subtract the cost of goods for every unit shipped, including free gifts, the line's share of the order's real transport cost without VAT, and the advertising cost allocated to that product per order. The result is contribution per SKU, before fixed costs such as salaries, rent and software.

Why count only delivered orders when calculating product profit?

In a cash-on-delivery store the customer pays only when the parcel arrives. Placed orders that are refused, cancelled or still in transit bring no revenue, so counting them overstates profit. The delivered status should come from the courier's final verdict, because the shop's payment status often stays pending and the shop's own tracking can mark returned parcels as delivered.

Should free gift units be included in cost of goods?

Yes. A free gift has zero revenue, but a real unit leaves the warehouse and was bought at a real cost. Keep the gift line with its quantity and unit cost. In a per-product report it then appears as a line with zero revenue and a negative contribution, and the order's total contribution is correct. Dropping gift lines makes stock disappear without a cost.

What if the real shipping cost of an order is missing?

Use a fallback cascade and label each order with the level used. First the cost the courier actually billed for that order, without VAT. If it is missing, the average real cost previously billed for parcels with the same SKUs. If that is missing too, a flat cost per parcel for the store. Report which products rely on estimates, since their profit is approximate.

How should ad spend be allocated to products for profit per product?

Trace each ad to an exact SKU, a product group or only a brand. Exact SKUs take their spend directly; group and brand spend is shared across the matching sold SKUs in proportion to their number of orders. Allocating per order gives every order the same cost per acquisition. Keep test campaigns out and report spend that cannot be allocated instead of dropping it.

How to cite this

Going Stellar (2026). How to calculate profit per product for a cash-on-delivery store. GOING STELLAR S.R.L..
https://goingstellar.ro/methods/profit-per-product-cash-on-delivery/

Read as Markdown

All methods

Contact

Tell us what is not working

Write in English or Romanian. A person reads it — usually the same person who would do the work — and answers within one business day.