Merchgain
EN
Available now
Next, in this order
  • DeutschDE
  • EspañolES
  • FrançaisFR
  • ItalianoIT
  • PortuguêsPT
  • NederlandsNL

A language shows up here once its pages are actually written. Nothing on this site is machine-translated.

Install freeInstall

How profit and margin are calculated

A report is a set of decisions about what to count. Here are all of ours, in the order they affect the figure on the screen, with a worked example on the same demo data the screenshots use.

Updated 2026-10-11

Revenue

The net line total of the goods sold, after discounts, excluding tax and excluding shipping.

Tax is not yours, so it is out. Shipping is out because the core records no cost against a shipping line: counting the charge as revenue while its cost sits nowhere would make every margin look better than it is.

Coupons are already applied — WooCommerce stores line totals after discounts, so a 20% code shows up as lower revenue rather than as a separate deduction.

Cost of goods

The sum of the costs recorded on the sold items, read from the order lines, not from today’s product records.

This is the part that makes the report worth building: WooCommerce writes the cost onto the order line at the moment of sale, so an order from last March reports what the goods cost last March. The only thing that overwrites it is a refund, which is core behaviour explained separately.

Gross profit

gross profit = revenue on items with a known cost − cost of those items

Note the first half. Profit is calculated only on items whose cost is known. An item with no recorded cost still counts towards revenue, but it never enters the profit calculation as if the goods had been free.

The alternative — treating a missing cost as zero — produces a bigger, friendlier and completely false profit figure. That is the single most common way a profit report lies to a shop.

Margin

margin = gross profit ÷ revenue on items with a known cost

Profit divided by revenue, not markup on cost. A product bought for 60 and sold for 100 has a 40% margin here. Its markup is 66.7%, and suppliers usually quote that one — the margin and markup calculator converts between them.

Coverage — the number that qualifies every other number

coverage = revenue on items with a known cost ÷ total revenue

Printed at the bottom of the summary panel as a sentence rather than a badge:

Cost is known for 74% of revenue. Profit and margin above are calculated on that part only; zł1,119,760.42 of revenue has no cost recorded.

Coverage is not a score to get to 100%. A shop that gives away samples, or sells goods bought before the cost field existed, will sit below 100% forever — and that is the correct answer rather than a defect.

A worked example

The demo shop on the sample report, over twelve months:

FigureValueWhere it comes from
Revenuezł4,306,235.11all counted order lines
Revenue with a known costzł3,186,474.69revenue minus the uncovered part
Revenue with no cost recordedzł1,119,760.42the 26%
Cost of goodszł1,646,293.79costs recorded on those lines
Gross profitzł1,540,180.903,186,474.69 − 1,646,293.79
Margin48.3%1,540,180.90 ÷ 3,186,474.69
Coverage74%3,186,474.69 ÷ 4,306,235.11

Two things are worth noticing. Margin is computed on covered revenue, not on total revenue — otherwise it would silently drop by a quarter for a reason that has nothing to do with your prices. And the profit figure is smaller than “revenue minus cost” on the whole shop would suggest, because a quarter of the revenue is simply not part of the calculation.

Which orders are counted

Completed, processing and refunded. Cancelled, failed, pending, draft and on-hold orders are not counted at all — not as zero-profit sales, just absent.

Refunded belongs on that list for a reason that is easy to miss: a full refund flips the original order to refunded, so excluding that status would delete the sale while keeping the refund, and the order would count as minus its own value. The whole argument.

Refunds

A refund counts as a negative amount in the period it was issued, not in the period of the original sale. A September sale refunded in November leaves September exactly as it was.

Both sides move: the refund reduces revenue and recorded cost together, so a fully refunded order nets to zero rather than to minus its own margin.

What is deliberately left out

  • Shipping income and shipping cost. No cost field exists for a shipping line.
  • Payment and gateway fees. They are not in the order data in any standard form.
  • Orders in another currency. Named in a warning and excluded, with no exchange rates applied. Why.
  • Anything outside the goods — rent, salaries, ads. This is a gross profit report, and gross profit is a real, useful number precisely because its boundary is clear.

Categories overlap on purpose

A product in three categories is counted in all three, so the category rows can add up to more than the summary. WooCommerce has no primary category, so the alternative would be inventing one. The details.

How far back it reaches

There is no window. The report counts the dates you pick — the shortcuts stop at twelve months, but a custom range takes any two dates, back to your oldest order. Nothing is clamped on the way to the query, and the two date fields always show the days actually counted.

What ends the history is the cost data rather than the range: revenue reaches back to the oldest order, while profit and margin reach back only to the day costs started being recorded. How far back the report reaches.

Where these numbers come from in the database

For anyone who wants to check the arithmetic against their own SQL:

  • product cost — _cogs_total_value in postmeta, plus wc_product_meta_lookup.cogs_total_value, which is NULL when no cost is entered;
  • order line cost — _cogs_value in woocommerce_order_itemmeta, the same table under HPOS and classic storage;
  • order total cost — _cogs_total_value in wc_orders_meta under HPOS, in postmeta otherwise;
  • line revenue — the line item’s net total, from the same order items tables.

The report is calculated by your own database and never leaves your server. If a figure here does not match what you get by hand, that is worth an email — a wrong number is the only real failure this kind of product can have.