Contribution margin ladder

How to compute Contribution Margin for Indian DTC brand

Contribution margin is not one number. This post walks through CM1, CM2, and CM3 with the formulas, inputs, examples, and common mistakes that make the ladder unreliable.

Contribution margin isn’t a number, it’s a ladder: CM1, CM2, CM3, three rungs, three decisions. That post was about what the rungs mean.

This one is about how you compute them. The formulas, the inputs each rung needs, and the handful of places the arithmetic quietly goes wrong.

The whole ladder is one move repeated three times. You start at net revenue, subtract one layer of variable cost, stop, and name where you stopped.

Net Revenue
− COGS → CM1 (after product)
− fulfilment + returns → CM2 (after delivery)
− performance ad spend → CM3 (after growth)


Let me walk down it with one real order, so every step has a number attached. Figures illustrative: one ₹1,299 apparel unit sold on your own store. Percentages are of net revenue.

Rung zero: compute net revenue first

You don’t start at what the customer paid. You start at what you earned and kept.

Net Revenue = Final amount paid − returns − cancellations − taxes

Two steps trip people here.

Strip tax, per unit. If your prices are tax-inclusive, the sale price isn’t revenue. A chunk of it is GST you’re only holding for the government. A ₹1,299 apparel order at 12% GST is ₹1,160 of net revenue and ₹139 of tax. Compute it per unit, because when one unit of a multi-unit order comes back you reverse only that unit’s tax, not the whole order’s.

A return reverses the sale, it doesn’t discount it. The revenue leaves entirely, and as you’ll see at CM1, the COGS on that unit leaves with it.

Sale price (incl. 12% GST) ₹1,299
− GST −₹139
Net Revenue = ₹1,160

That ₹1,160 is the top of the ladder. Everything below is subtraction.

CM1: after product

CM1 = Net Revenue − Net COGS

The arithmetic is trivial. Getting COGS right is the whole job, and “right” means three things.

Landed cost, not invoice cost. COGS is what the unit cost to be sitting in your warehouse ready to ship: manufacturing or purchase price plus inbound freight, duties, and non-creditable GST. The supplier invoice is where COGS starts, not where it ends.

Effective-dated, not blended. The unit you sold in March cost you something different than the same SKU in September. Hold cost as a dated table, this SKU cost this much between these two dates, and join each order to the cost that was true the day it shipped. One blended average silently misprices every month except the mean one.

Net of returns. When a unit comes back into sellable stock, its cost comes back too.

Net COGS = COGS on units sold − COGS on units returned

For our order, landed COGS is ₹430.

Net Revenue ₹1,160
− Net COGS (landed, dated) −₹430
CM1 = ₹730 (63%)

If CM1 is thin, no ops discipline and no ad genius saves the SKU. The product is the problem, and this rung is where you find that out.

CM2: after delivery

This is the rung with the most inputs, and the one where the numbers live outside your store. Each cost is computed differently, so take them one at a time.

CM2 = CM1 − forward shipping − payment fees − packaging − storage − marketplace fees − returns provision

Forward shipping comes from the courier invoice, priced by weight slab × zone. A tier-3 pincode costs more than a metro one, so don’t use a flat average if you can join the actual shipment.

Payment and COD fees are the payment gateway’s cut. Prepaid is roughly 2% of the collected amount. COD is a flat handling fee plus the return risk that lands on the returns line below. Take the prepaid case: 2% × ₹1,299 ≈ ₹26.

Packaging is a fixed per-order constant. Small, real, and the one people forget entirely. Say ₹20.

Storage and warehousing is the cost of the unit occupying space until it ships. It’s a period cost, so you allocate it per unit by space × time held (cubic feet × days on shelf), or take it straight from your 3PL’s per-unit storage bill or Amazon’s FBA storage fee (~₹45/cu ft/month). A fast-mover carries almost none. A SKU that sits for months carries a lot, which is exactly why dead stock quietly bleeds CM2. Say ₹15 for our fast-moving unit. Judgment call: variable 3PL/FBA storage clearly belongs here; a fully-fixed owned-warehouse rent is sometimes held below the CM line as an operating cost. Just be consistent about which you do.

Marketplace fees, if the order sold on a marketplace, belong here on CM2: the referral, closing, and FBA fees are all delivery costs. This is why the definition matters.

Returns and RTO are the one line that’s computed, not observed. A delivered order carries no return cost. But you can’t compute a representative CM2 by ignoring the orders that come back, so you provision for them across every order sold.

Returns provision per order = return rate × extra cost per returned order
extra cost per returned order = reverse leg + repack


At a 15% return rate and ₹95 of extra cost per returned order (₹75 reverse leg + ₹20 repack):

0.15 × ₹95 = ₹14 per order

Allocate that to the order that caused it, or at least to the SKU, pincode, or payment-mode cohort that caused it. Never spread it as one blended company-wide number, or your good cohorts silently subsidise your bad ones and you never find the leak.

Walking CM1 down:

CM1 ₹730
− Forward shipping −₹75
− Payment gateway (2%) −₹26
− Packaging −₹20
− Storage / warehousing −₹15
− Returns provision (15%×₹95) −₹14
CM2 = ₹580 (50%)

CM2 is the honest answer to “did this order make money once it actually moved.”

CM3: after acquisition

CM3 = CM2 − attributable performance media
Fully-loaded CM3 = CM3 − brand & agency spend (fixed marketing)

The input here is CAC, computed with two decisions made on purpose.


Performance media only, brand and agency drop below. CM3 nets just the variable, attributable performance media: the ad spend that scales with orders. Two fixed marketing costs are deliberately not in it, brand and top-of-funnel spend and agency retainers, because neither moves with any single order. Subtract them one rung lower and you get a second figure, fully-loaded CM3. So you carry two numbers on purpose: clean CM3 for the marginal “should I sell one more?” decision, fully-loaded CM3 for the honest all-in. A pure %-of-spend agency fee is the exception that scales with the media and could later fold into CM3. For now all brand and agency spend sits in the fully-loaded tier.

At a CAC of ₹180:

CM2 ₹580
− Acquisition (CAC) −₹180
CM3 = ₹400 (34%)

Clean CM3 is the marginal contribution of one more order. Below it sit the fixed marketing costs that define fully-loaded CM3, brand and agency, and below that sits true overhead: team, tooling, rent. CM3 tells you whether the next order pays. Fully-loaded CM3 tells you whether the whole growth motion does.

The full ladder, one order, end to end

Sale price (incl. 12% GST) ₹1,299
− GST −₹139
Net Revenue ₹1,160
− Net COGS (landed, dated) −₹430
CM1 ₹730 (63%)
− Forward shipping −₹75
− Payment gateway −₹26
− Packaging −₹20
− Storage / warehousing −₹15
− Returns provision −₹14
CM2 ₹580 (50%)
− Acquisition (CAC) −₹180
CM3 ₹400 (34%)

One order, one number at each rung, each computed from its own input, each meaning something different. The last rung hides one more distinction the single number doesn’t show: not every ad rupee is the same kind of spend.

Telling performance from brand

That two-tier CM3 only works if the split between the two buckets is reliable. The most robust way to get it is a mix of a structured campaign naming convention and the platform’s native ad types.

The intent tagged into each campaign name, read alongside the campaign objective and ad type the platform already reports, classifies brand versus performance straight off the campaign, the same way every time, with no hand-sorting of spend after the fact. Top-of-funnel and awareness route below CM3 into the fully-loaded tier.

The scheme itself isn’t the point. The point is that the performance-versus-brand line stops being an argument and becomes a parse, so clean CM3 and fully-loaded CM3 both build automatically.

Splitting the ladder: CM by SKU, channel, and geo

That classification also unlocks the more useful move. Because the ladder is built from atomic order-line data rather than a blended monthly P&L, you can compute it at any grain you can group by: CM1, CM2, CM3 per SKU, per channel, per region. Same three rungs, sliced however the decision needs.

Most rungs split cleanly, because their costs are already attached to the order line. COGS is per SKU. Shipping, payment fees, and packaging are per order. Returns are per order. Group by SKU and they simply sum, so everything up to CM2 is objective.

CM3 is the rung that fights you, because ad spend rarely arrives attached to a SKU. Product spend, a Sponsored Product on one ASIN or a product-specific keyword, maps cleanly to a SKU. Category and brand spend (“vitamin C serum,” category awareness) drives demand across many SKUs and maps to none of them. So if you compute per-SKU CM as revenue − COGS − directly-attributed spend, you get a systematic distortion: SKUs that carry direct spend look artificially unprofitable (all their ad cost is visible), while SKUs that free-ride on category and brand demand look artificially profitable (they carry none of the acquisition cost that actually drove them).

Our best practice is to handle spend in three layers that match how it was actually bought, and the classification above is what tags each rupee into the right layer.

  • Directly-attributable spend → 100% to the SKU. A Sponsored Products ad on one ASIN, or a product-specific keyword, belongs entirely to that product. Assign it whole.

  • Category and multi-SKU spend → split by the conversions it actually drove. A campaign spanning ten products is apportioned across them by each SKU’s share of the conversions that campaign drove, not by total revenue share, which would dump ad cost onto SKUs that sell organically and never touched the campaign.

  • Brand and top-of-funnel spend → hold it below CM3, as a separate fully-loaded CM3. Upper-funnel spend that lifts the whole portfolio can’t be click-mapped to any one SKU.

Those three layers give you CM3 by SKU and by channel. Geo is the one grain with an extra dependency, because it needs the platform to hand you geography on both sides: ad spend and sales. On your own store you have both. Every order carries its destination pincode, and the costs that vary most by geography, like shipping to a tier-3 pincode or a higher RTO rate, are already sitting on the order line, so CM1 and CM2 split by geo cleanly. On a marketplace it’s conditional. Some platforms surface sales by region and let you attribute spend to it. Many mask the customer’s location, or report ad spend only at the campaign level. So CM-by-geo is clean up to CM2 wherever you own the fulfilment, and complete through CM3 only where the platform actually gives you geography on both the sales and the spend.

The honest part, and it’s the important one. There is no objectively correct way to split category or brand spend down to a single SKU. Every method is a modeling assumption. The failure mode is showing an allocated per-SKU margin as if it were a fact, when it’s really hiding a choice.

So the right way to present it isn’t one number. It’s CM-before-allocation and CM-after-allocation side by side, with the allocation rule visible and switchable. Glass-box, not black-box. The marketer sees the assumption and can change it.

Put the objective cost-to-serve and the modeled allocation together and you get the artefact a CFO actually trusts: a per-SKU × per-channel contribution matrix, four rows exposed, the allocation rule a toggle. One ₹599 SKU, illustrative. Assumption.

Per unit

DTC

Blinkit

Amazon

Selling price

₹599

₹599

₹599

− COGS

₹150

₹150

₹150

− Fulfilment / platform take

₹52

~₹165

~₹128

− Storage

₹8

₹5

₹12

− Returns / payment

₹82

₹40

₹55

= CM before marketing

₹307

₹239

₹254

− Direct ad (attributed)

₹120

₹90

₹110

= CM after direct ad

₹187

₹149

₹144

− Allocated category (modeled)

modeled

modeled

modeled

= CM after allocable spend

₹187 − cat

₹149 − cat

₹144 − cat

Brand and top-of-funnel spend isn’t in this matrix at all. It’s subtracted below CM3 as a portfolio-level line, the separate fully-loaded CM3, never split into a SKU, because any key you’d use (revenue or unit share) would be a fabrication, not a measurement. Per-SKU CM3 stops at directly-attributed plus category-allocated media, and brand comes off one rung lower.

The top and bottom of that matrix carry the whole point. CM before marketing is objective and stable, the SKU’s economics before a rupee of ad spend, and already different by channel because Blinkit’s take and Amazon’s fees bite harder than your own store. CM after allocable spend is where the modeled category allocation lands, shown as a lens, not a fact.

That’s what turns true CM from a slogan into a number a CFO trusts, and it surfaces the thing brands genuinely cannot see today: this hero SKU is only profitable because category spend it’s never charged for is carrying it, or this margin engine on DTC actually bleeds on Blinkit after fees.


Where this leaves you

Net revenue tells you what you earned. The CM ladder tells you what you keep, and, computed one input at a time with each cost on its own rung, exactly where it leaks.

Most of the work isn’t the arithmetic. It’s getting every system to agree on what one order cost, and stopping on the rung the decision in front of you actually needs.

That’s the number a brand actually runs on.