What is contribution margin?

Contribution margin is what is left of an order's revenue after the costs that scale directly with it: the cost of the goods sold, the shipping it cost you to fulfil, and the payment processing fee. It excludes fixed overhead — rent, salaries, software — on purpose: it answers "does selling one more of this make money," not "is the business profitable," which is a separate, larger question (net operating profit).

Formula

contribution margin % = (net revenue − COGS − shipping cost − payment fees) ÷ net revenue

Worked example

A product line sells for €50,000 of gross revenue, with €2,000 of order-level discounts applied (net revenue €48,000). Cost of goods sold is €22,000, shipping cost allocated to those orders is €3,000, and payment fees are €1,440. Contribution margin is €48,000 − €22,000 − €3,000 − €1,440 = €21,560, or 44.9% of net revenue.

How Saldo Metrics computes it

canonical.v_contribution_margin is the line-item-grain source every other margin figure in the product rolls up from, counting completed sales only — cancelled orders, and orders refunded in full, are excluded, which is the intended definition of a countable sale across the app. For each order line it takes line_revenue_base, subtracts that line's pro-rata share of the order's discount (allocated_order_discount_base), the resolved unit cost from cost_source_record times quantity (line_cogs_base — the highest-trust confirmed cost record valid on the order date), and that line's pro-rata share of the order's shipping cost plus payment fee (allocated_overhead_base). All four inputs are *_base (EUR) columns: every margin figure is arithmetic on amounts already converted to euros at the ECB rate for the transaction's own date, so no metric is computed from mixed currencies. Displaying that figure in a non-euro currency is a separate, final step applied to the finished number at one as-of rate.

Two populations read off this figure. The per-product, per-brand, per-category and per-supplier rollups below stay on v_contribution_margin's net-sale population. The P&L, net operating profit, order-level and SKU-level net profit, the store, channel and geo-opportunity margin and cost-coverage breakdowns, the v_country_revenue view, and order accounting's own margin column all instead read v_contribution_margin_all, which also books orders refunded in full — the shipping and payment fees those orders cost you were already spent and are not coming back, so leaving them out would erase real cost from exactly the figure meant to catch it, without erasing the revenue it earned. The revenue-by-country widget is not one of them: it reads order accounting filtered to net sales, so its margin covers net-sale orders only.

Four rollups aggregate that line-grain view to the grain each key needs: v_product_margin (top_margin_products, worst_margin_products, product_margin_pct), v_brand_margin (brand_margin, brand_margin_pct), v_category_margin (category_margin), and v_supplier_margin (supplier_margin). Each sums margin and net revenue at its grain and divides. avg_margin_pct is the average of v_product_margin.margin_pct across every product; margin_total_30d sums contribution_margin_base directly from v_contribution_margin over the trailing 30 days.

A refund is netted against the order it came from, not the month it happened in. When goods actually come back, both the revenue and the cost of those units reverse — so a March order refunded in April still corrects March's figure, because that is the sale being unwound. Shipping and payment fees are not reversed: you already spent them getting the order out, refunded or not. A refund with nothing returned — a goodwill credit for a damaged box, say — reverses only the revenue; the goods are still gone, so their cost stays charged. That distinction runs on the number of units the platform reports as returned, not on the refund amount: v_refund_reversal reads that count off each refund event, and when a platform cannot report one, the cost stays charged rather than being guessed, with the line marked refund_quantity_unknown so it can be told apart from an ordinary one.

Why it matters

Revenue tells you what sold. Contribution margin tells you what selling it was worth — a bestseller with thin margin can contribute less to the business than a slower mover with a healthy one. Reprice, delist and product-mix recommendations are all built on this figure, not on revenue.

Common mistakes

  • Reading contribution margin as net profit. It excludes fixed overhead by design — a business can have healthy contribution margin on every order and still lose money if overhead outgrows it. Net operating profit is the figure that includes overhead.
  • Comparing margin % across products at very different price points without checking absolute margin too — a low-price, high-margin-% item can contribute less cash than a higher-price item at a lower percentage.
  • Trusting a margin figure with a high missing-cost rate. A line with no confirmed cost record has its COGS treated as zero, not flagged as unknown, which inflates margin % for products with incomplete cost data. v_contribution_margin exposes this per line as missing_cost; v_product_margin rolls it up per product as any_missing_cost.
  • Comparing this month's figure against the same month on the P&L. The two date refunds differently on purpose — this figure corrects the order that was refunded, the P&L books the refund in the month the credit note cleared — so they can disagree on a month with late refunds. See net operating profit.

Where you see this in the app

Dashboard, in the average margin KPI and the top/worst margin product tables; and the brand, category and supplier margin breakdowns across the app's profitability views.