Here is a conversation we have had more times than any other. A brand shows us an ad account doing 4.2x ROAS. Spend is up, revenue is up, the dashboard is green. And the business is making less money than it did last year.
Nobody is lying. The number is real. It is just measuring the wrong thing, and the ad platform is dutifully optimising toward it — which means every day the account runs, it gets better at the wrong thing.
This is the most expensive reporting gap in performance marketing, and it is entirely fixable. Here's the mechanism, the maths, and the layer you need to build.
What ROAS actually measures
Return on ad spend is revenue divided by spend. That's it. It has no opinion about what that revenue costs you to deliver.
Two products, same £100 price, same £25 acquisition cost. Both report 4x ROAS. One has 70% gross margin and ships in an envelope. The other has 28% margin, weighs nine kilos, and gets returned a fifth of the time. On the dashboard they are identical. In the P&L one funds the business and the other is a slow leak.
Now add the part that makes it compounding rather than merely wrong: the algorithm optimises toward the signal you send it. Feed it revenue events and it will find more of whatever generates revenue — which, given a mixed catalogue, means it will systematically discover your highest-priced, lowest-margin, highest-return-rate products, because those maximise the number it was asked to maximise.
A revenue-optimised account doesn't drift toward unprofitability by accident. It is being paid to get there.
The four leaks ROAS hides
1. Gross margin variance
Any catalogue with a spread of margins has a blended ROAS that describes nothing real. The average of a 68%-margin product and a 22%-margin product is a number that applies to neither.
2. Returns and refunds
Platform-reported revenue is booked at purchase. Returns land weeks later, in a different system, and almost never make it back into the ad account. In apparel and furniture we routinely find 15–30% of "revenue" reversing after the fact, concentrated in exactly the campaigns the algorithm favours.
3. Discounting
Codes stack. Sitewide promotions overlap with welcome offers. The order confirms at £100, settles at £74, and costs the same to fulfil. Unless discount value flows into your conversion signal, you are optimising toward your most discount-hungry audience.
4. Fulfilment and payment costs
Shipping, packaging, payment processing, pick-and-pack. Small per order, decisive at the margin. A 3.5x ROAS product at 30% gross margin is roughly break-even once these land — and the account will happily scale it.
The fix: contribution margin as the optimisation target
The goal is to send platforms a number that reflects what the order is actually worth to the business. We build it in three layers.
Layer one — a true contribution value per SKU
For every product: price, minus COGS, minus average discount, minus fulfilment, minus payment fees, minus expected return cost weighted by that SKU's real return rate. This is a finance exercise more than a marketing one, and it is where most of the value is created. Get the inputs from the people who own them; do not estimate.
Layer two — send contribution, not revenue
Pass that value as the conversion value in your server-side events rather than order total. From that moment the algorithm is bidding against profit. Nothing else about the account has to change for the behaviour to change.
Expect reported ROAS to fall, often dramatically — a 4.2x account might report 1.6x on contribution. Nothing got worse. You are finally looking at the real number, and you need everyone who reads the dashboard briefed before the change lands, or you will spend a fortnight defending an improvement.
Layer three — set the target from the P&L
Your break-even contribution ROAS is 1.0. Your target is 1.0 plus whatever the business needs to cover overhead and profit. That's a number your finance lead can give you in an afternoon, and it turns "is 3.4x good?" — a question with no answer — into a threshold anyone can act on.
The reframe
Stop asking "what's our ROAS?" and start asking "what is a customer worth after everything it costs to serve them, and are we paying less than that?" Every useful decision follows from the second question.
The objections, answered
"Our margins are commercially sensitive." You are sending an index, not a price list. Scale contribution by a consistent factor if you need to; the optimisation only cares about relative differences.
"We'll lose the learning phase." You will have a re-learning period, typically one to two weeks. Plan for it, don't skip the change because of it. Compounding a wrong signal is worse than a fortnight of noise.
"Our finance data isn't clean enough." It doesn't need to be perfect, it needs to be directionally right. A rough contribution value beats an exact revenue value, because it points in the right direction. Start with your top 20 SKUs by spend and expand.
What changes once it's running
Predictably, and quickly: spend rotates away from high-revenue, low-margin products toward the ones that fund the business. Discount-led audiences get bid down. Return-heavy categories stop eating budget. Blended ROAS on the old dashboard drops while actual profit rises — which is why you brief the readers of that dashboard first.
The second-order effect is more interesting. Once profit is the target, decisions elsewhere get easier to make. Creative testing gets judged on contribution rather than clicks. Landing-page work gets prioritised by margin impact. Product teams find out which SKUs marketing can actually afford to promote. The measurement layer becomes the shared language, which is exactly what we build toward in analytics architecture engagements.
It also changes what "good creative" means. When you test at volume — as we cover in creative testing at volume — a winner judged on revenue and a winner judged on contribution are frequently different ads.
How to start this week
- Pull your top 20 SKUs by ad spend. Not by revenue — by spend.
- Build the contribution number for each one with finance in the room. Price through to expected return cost.
- Rank them. The gap between the revenue ranking and the contribution ranking is your current misallocation, in one table.
- Send contribution as conversion value server-side, and set the target from break-even upward.
- Hold the line for three weeks while the account relearns, then read it.
Most brands find the first table alone justifies the project. It is uncomfortable reading, and it is the most useful spreadsheet the marketing team will build that year.
Want your account measured against profit instead of revenue?
We rebuild measurement layers as part of every Performance Marketing engagement — contribution modelling, server-side events, and a dashboard your finance team recognises.
The short version
ROAS is not wrong, it is incomplete — and incompleteness compounds when an algorithm optimises against it. Build the contribution number, send it as your conversion value, set the target from the P&L, and accept that the dashboard number will get smaller while the business gets healthier.
If you'd rather have this built than build it, talk to a strategist or look at how we've approached it in client work.





