A 5x ROAS feels like a win. On a 25% gross margin product, it loses money on every order before you account for refunds. ROAS is the metric every Google Ads dashboard leads with and every founder runs their business on, and the gap between those two facts is what destroys ecom brands quietly.
On a 25% margin product after refunds. Net contribution: negative.
The arithmetic is unforgiving once you write it down.
POAS, profit on ad spend, closes the gap. It is the same metric as ROAS but with the math your CFO already does in their head. We use it as the optimisation target on every Ad-Lab account. Most agencies don't, because POAS forces them to look at the parts of your business they were happy to ignore.
Why this post matters
Two thirds of the accounts we audit are bidding against ROAS targets that look healthy on the dashboard and lose money on the spreadsheet. The campaigns that compound under a POAS lens are different campaigns from the ones that compound under a ROAS lens. Same accounts, same data, different decisions.
What POAS actually measures
ROAS is revenue divided by ad spend. POAS is profit divided by ad spend, where profit accounts for product margin, refund rate, return rate, and the new-customer-vs-repeat-customer mix.
The mechanical version: take attributed revenue, subtract product COGS, subtract a refund-rate haircut (typically 3-12% depending on category), subtract a return-rate haircut, then divide by spend. That's POAS. It's the number you'd write down if you were trying to decide whether to turn the ad up or down without lying to yourself.
The POAS formula in plain text. Drop it into a sheet, parameterise the four haircuts, and you have a working calculator. The full template at /resources/templates/roas-vs-mer-reconciliation has the spreadsheet version.
# Inputs
revenue = attributed_revenue_for_window
ad_spend = google_ads_spend_for_window
gross_margin_pct = (revenue - cogs) / revenue # from Shopify or finance
refund_rate_pct = refunds / orders # last 90 days
return_rate_pct = returns / orders # last 90 days
new_customer_pct = new_customers / total_customers # for the window
# Adjusted revenue
contribution = revenue * gross_margin_pct
contribution = contribution * (1 - refund_rate_pct)
contribution = contribution * (1 - return_rate_pct)
# POAS
poas = contribution / ad_spend
# Sanity
roas = revenue / ad_spend
gap_factor = poas / roas
# Most ecom brands run a gap_factor between 0.18 and 0.45.
# Below 0.18 means margin is too thin for paid acquisition at the
# current efficiency. Above 0.45 means you have room to scale faster.Why the four adjustments matter
- Product margin: a 5x ROAS at 25% margin makes 25 cents on every dollar of revenue, before fulfillment. A 5x ROAS at 60% margin makes 60 cents. The ad performs identically; the business outcome is twice as good.
- Refund rate: in apparel a 7-12% refund rate is normal. In supplements 2-3%. Reporting ROAS without baking refunds in overstates performance by exactly that percentage.
- Return rate: same logic, separately tracked. Returns also carry a fulfillment cost the refund rate doesn't capture.
- New vs repeat mix: if 40% of your 'Google Ads conversions' are existing customers, you're measuring acquisition against a base that isn't really being acquired. Splitting branded vs non-brand campaigns surfaces the real number.
Glossary references for the metric stack
Why agencies skip it
Two reasons, both structural
Reason 1: agencies don't have your margin numbers
Computing POAS requires the founder to share product COGS, refund rate, and return rate. Most agencies never ask. Some founders never offer. The data lives in the Shopify back-end and the CFO's spreadsheet, and nobody bridged the gap.
Reason 2: POAS makes campaigns look worse
A campaign reporting 4.5x ROAS that drops to 2.1x POAS exposes a structural problem the agency was happy not to see. The campaigns that survive the POAS lens are the ones genuinely making the business money. That number is harder to win on, which is exactly why it's the right target.
How to set the target
Don't set a POAS target the same way you'd set a ROAS target. The target depends on three things: your contribution margin per order, your CAC payback window, and whether you're funding growth or harvesting profit.
Working POAS targets by margin profile. These are starting points; calibrate against your own payback period and growth posture.
| Profile | Contribution margin | Payback window | Working POAS target |
|---|---|---|---|
| Aggressive growth, high LTV | 55%+ | 9-12 months | 1.0x to 1.3x first-order POAS |
| Standard DTC, mid LTV | 35-50% | 4-6 months | 1.4x to 1.8x first-order POAS |
| Margin-led, harvesting profit | 25-35% | 2-3 months | 1.8x to 2.2x first-order POAS |
| Thin-margin commodity | 15-25% | Same-cycle | 2.5x+ first-order POAS or rethink the model |
A high-margin brand with a 12-month CAC payback window can run aggressive POAS targets, 1.0-1.3x is fine because the second-purchase margin earns the spend back inside the year. A low-margin brand harvesting profit in the short term needs 1.8x+ on first-order POAS or the unit economics break.
The honest version: most ecom brands should run somewhere between 1.4x and 2.0x POAS as the target. Below that, you're funding growth (which can be the right call). Above that, you're under-investing in acquisition and the brand will plateau on repeat customers.
How to deploy POAS as the bid target
Pass margin signal into the conversion value
In Google Ads, the conversion value is normally the order revenue. Replace it with the contribution margin per order. Either via Conversions API with the value field set to revenue * margin, or via Google's Conversion Value Rules to apply category-level multipliers when product-level data isn't available.
Switch the bid strategy to Maximize Conversion Value with a tROAS target
Once Google Ads sees contribution margin as the conversion value, a tROAS target of 1.6x is the same instruction as 'POAS 1.6x'. The platform's bidding stays unchanged; only the value signal it's optimising against changes.
Run the parallel comparison for two weeks
Don't cut over to POAS-as-target on every campaign at once. Pick one PMax campaign or one Search non-brand campaign. Run the new value signal for 14 days alongside the old. Compare daily POAS, blended MER, and net new customer acquisition before promoting the change.
Lock the change with a written success metric
Write down what 'this is working' looks like before week three. POAS up by 8%? Net new customers flat? MER stable or improved? The metric is the thing that protects the decision when the dashboard ROAS dips during the transition.
Templates that operationalise POAS
- ROAS vs MER Reconciliation SheetThe sheet that bridges channel ROAS, blended MER, and POAS for a CFO conversation.
- Branded Search Bleed AuditSplits the new-vs-repeat mix question so POAS targets reflect real acquisition.
- PMax Structure AuditSurfaces the structural decisions that limit how aggressive your POAS target can run.
What to put in front of your CFO
Two charts. Replace whatever channel-ROAS spreadsheet you've been showing them.
First chart: blended POAS over time. One line. Trended weekly. The number that tells the CFO whether marketing as a function is making money.
Second chart: blended MER (total revenue / total marketing spend) on the same axis. MER and POAS should track together. When they diverge, POAS down while MER stable, that's the signal that the channel mix is shifting toward channels that look efficient but aren't.
Channel ROAS goes in a third tab if anyone asks. It's diagnostic, not strategic. The CFO doesn't run the company on it. Don't let your reporting suggest otherwise.
The shorter version
ROAS is a dashboard number. POAS is a business number. If you only optimise against one metric, optimise against POAS. The campaigns that survive the lens are the ones genuinely making your business money, and the ones that don't survive should be paused regardless of how the dashboard reads.
