Attributing Shipping Weight To SKU-Level Contribution Margin

A practical method for backing out average shipping cost into per-SKU load using dimensional weight, so heavy and bulky SKUs stop hiding margin-negative behaviour behind the order average.
Quick answer
Allocate shipping cost per SKU by taking each line's chargeable weight (the greater of actual weight and dimensional weight) and splitting the order's real shipping cost proportionally. Then subtract that allocated shipping from the SKU's gross margin to get true contribution margin. The €6 order-average is a reporting artefact — it averages a €2.10 lipstick over a €14.80 ceramic mug and makes the mug look profitable when it isn't.
Attributing Shipping Weight to SKU-Level Contribution Margin
Splitting an order's real shipping cost across its line items by chargeable weight, so each SKU carries its own shipping load in margin reports.
Attributing shipping weight to SKU-level contribution margin is the practice of replacing the blended per-order shipping average with a line-item allocation driven by chargeable weight — the larger of actual weight and carrier dimensional weight. Each order's real carrier-billed cost is divided across its SKUs in proportion to how much of the parcel they account for, and that allocation is then folded into the SKU's contribution margin alongside COGS, payment fees, and returns.
The method matters because a single store-wide shipping average disguises the SKUs that quietly destroy margin every time they ship. Once shipping lives at the line item, heavy and oversized products stop being subsidised by the small, light bestsellers in your catalogue.
Most Shopify and WooCommerce P&Ls book shipping as a single COGS-adjacent line. That works at the order level. It collapses the moment a buyer asks which SKUs to discount, bundle, or quietly delist.
Why the €6 average breaks at the SKU level
Carriers don't charge by order. They charge by parcel dimensions and weight, with a dimensional-weight floor (length × width × height ÷ a divisor — typically 5,000 for DHL Express, 4,000 for UPS). A 1.4 kg ceramic mug in a 30×20×15 box bills as if it weighed 1.8 kg dim. A 90 g lipstick in a polymailer bills as 0.1 kg.
When you report a €6 order-average across both, you're claiming the mug costs €6 to ship and the lipstick costs €6 to ship. The carrier invoice says one is €9.40 and the other is €3.20. The averaged number hides an 18-point swing in contribution margin.
The fiction this resolves
If your finance team is still using "average shipping per order" in SKU profitability reviews, every heavy or oversized product in the catalogue is being cross-subsidised by your lightest movers. The bestseller list and the contribution-margin leaderboard will quietly disagree — and merchandising decisions made on the bestseller list will erode total margin month over month.
How to detect the distortion in your own data
Pull 90 days of orders with the carrier-billed shipping cost per order, the SKUs on each order, and each SKU's actual weight plus packed dimensions. Shopify exposes order-level shipping in the Orders export and the Shipping API; WooCommerce exposes it via the order meta. The pipeline pattern is covered in the per-SKU CM data pipeline spoke.
For each line, compute chargeable weight = max(actual_kg, L×W×H ÷ divisor). Allocate the order's shipping cost across lines in proportion to chargeable weight × quantity. The exact divisor depends on carrier — see the dimensional-weight formulas reference for DHL, UPS, GLS and Colissimo. Then recompute contribution margin per SKU with the new allocation in place. Compare it to the previous report. The gap is the lie.
How to fix it: the allocation rule that actually works
Use a two-step rule. First, calculate each SKU's standalone chargeable weight. Second, for any multi-item order, split the parcel's billed cost by each line's share of total chargeable weight in that parcel. This is the same logic carriers use internally when consolidating, and it survives audit. The multi-item allocation edge cases — split shipments, oversize surcharges, fuel — are handled in the dedicated allocation spoke.
Don't forget return shipping. For fashion and footwear, where return rates sit at 25–40%, return-leg cost must also land on the SKU's margin. A returned €70 dress that cost €4.10 to send and €4.10 to take back is a €78 cash transaction with €8.20 of shipping load — and that load only shows up in the line-item view.
Where this hits hardest
Heavy, bulky, or low-AOV-relative-to-size categories: pet food, ceramics, glassware, small appliances, books, candles, anything in protective inserts. If shipping eats more margin than COGS for a SKU, it belongs on the watchlist — not in the next "hero product" Meta campaign.
Experiments to run once the data is clean
Test repricing or repacking the bottom decile of CM-after-shipping SKUs first. Common winners: switching a 30×20×15 box for a 25×18×8 mailer drops dim weight by 60% for soft goods; raising the free-shipping threshold by €5 recovers margin on heavy SKUs without measurably hurting conversion when AOV is already above the new line.
Watch the interaction with free-shipping thresholds carefully — they redistribute who pays for shipping, but they don't change the carrier bill. A heavy SKU added to qualify for free shipping can flip the entire order's contribution margin negative. That dynamic is the subject of its own playbook on free-shipping thresholds and per-SKU shipping load.
Frequently asked questions
Because carriers bill on the higher of the two. A pillow weighs 400 g but ships as 3 kg dim. If you allocate by actual weight, you'll under-attribute shipping to bulky low-weight SKUs — which are usually the worst offenders in margin terms. Use chargeable weight (max of actual and dim) to match what you're actually being invoiced for.
It's an allocation, not a measurement, so yes there is some approximation in multi-item orders. But going from a single store-wide €6 average to per-SKU chargeable-weight allocation typically reveals 15–30% of SKUs as margin-negative that previously looked profitable. That's a precision gain that comfortably justifies the modelling effort.
Order-level shipping charged to the customer is in the Orders export. The actual carrier-billed cost lives in your Shopify Shipping invoice (or your 3PL/carrier invoice if you ship externally). Joining these by order ID is the foundation of the pipeline — covered in detail in the Shopify-to-per-SKU-CM data spoke.
Compute chargeable weight × quantity for each line, sum them, and split the order's billed shipping in proportion. A 2 kg SKU and a 0.5 kg SKU in the same parcel get 80% and 20% of the cost respectively. Edge cases (split shipments, multi-parcel orders, oversize surcharges) are handled separately.
Yes, for any category with a return rate above ~10%. Apparel and footwear absolutely need it — the return leg often equals or exceeds the outbound cost, and ignoring it overstates fashion margins by 5–12 points. Calculate expected return shipping per unit as return_rate × return_leg_cost and add it to the SKU's allocation.
They're the same thing. Different carriers use different terms — DHL and FedEx say "dimensional weight", DPD and many EU carriers say "volumetric weight" — and different divisors (5,000, 4,000, or 6,000 for some surface lanes). The formula is identical: L × W × H ÷ divisor.
Yes. Once you know the per-SKU shipping load, you can set thresholds that protect contribution margin instead of just hitting an AOV target. A threshold calibrated against the average shipping cost will systematically lose money whenever a heavy SKU is added as the qualifying item.
If everything you sell is roughly the same size and weight (single-SKU subscription, one-size cosmetics line) the distortion is small and a blended average is fine. The moment you have meaningful variance — a candle line plus a diffuser line, or apparel plus footwear — the allocation pays off.
Recompute chargeable weights when you change packaging or launch a SKU, and re-pull carrier invoices monthly. Carrier rates, fuel surcharges, and zone mixes drift enough that a quarterly refresh is the practical minimum for the reports merchandising actually uses.
Almost always, yes — bestsellers carry political weight and reattributing shipping is what turns some of them into margin-negative SKUs on paper. The conversation is easier when you frame it as fixing a reporting fiction rather than penalising the category. The merchandising-resistance spoke covers how to run that conversation.
Get an AI expert review of your site
Paste your URL — Metricuno's AI runs the same heuristic checks a senior CRO consultant would, scoring your page and prioritising the fixes that'll move conversion fastest.