POAS vs ROAS: Why Profit Beats Revenue Reporting
A worked comparison of ROAS and profit-on-ad-spend (POAS) reporting for Shopify stores, showing where ROAS misleads and how to build POAS instead.
Written by Mantas Jurgutis — Founder, Adsify — builds the Google & Meta automation merchants use daily
Editorially reviewed by Adsify Editorial on March 1, 2026 — Reviewed against Shopify, Google Ads and Meta official documentation.
Two ratios, two different questions
ROAS answers 'how much revenue did this ad spend generate?' POAS answers 'how much profit did this ad spend generate?' They're calculated similarly — ROAS is revenue ÷ ad spend, POAS is (revenue − costs) ÷ ad spend — but the second calculation requires knowing your actual product costs, which ad platforms simply don't have access to. This is why two campaigns with identical 4x ROAS can have wildly different POAS if one sells a 60% margin product and the other sells a 20% margin product.
Worked comparison at the same ROAS
Campaign A: $10,000 ad spend, $40,000 revenue, 4x ROAS. Product COGS is 25% of revenue ($10,000), payment fees ~2.9% of revenue ($1,160), no separate shipping charge to model (absorbed at $4/order across roughly 570 orders, ~$2,280). Profit before ad spend = $40,000 − $10,000 − $1,160 − $2,280 = $26,560. POAS = $26,560 ÷ $10,000 = 2.66. Campaign B: same $10,000 spend, same $40,000 revenue, 4x ROAS, but COGS is 55% of revenue ($22,000), fees the same, shipping the same. Profit before ad spend = $40,000 − $22,000 − $1,160 − $2,280 = $14,560. POAS = 1.46. Identical ROAS, POAS nearly double for Campaign A.
What POAS of 1.0 means
A POAS of 1.0 means the campaign generated exactly enough gross profit (after COGS, fees, and shipping, before ad spend) to cover its own cost — true break-even. A POAS above 1.0 means the campaign is net profitable after all variable costs and ad spend; below 1.0 means the campaign is a net loss even though the ROAS figure on the platform dashboard likely still looks positive and even attractive. This is precisely the gap that causes stores to unknowingly scale unprofitable campaigns — the dashboard says 'good,' the bank account says otherwise.
Why platforms can't calculate POAS natively
Google Ads and Meta both use order value (the transaction total) passed via conversion tracking or Shopify's native integration as their revenue metric. Neither platform has access to your COGS, landed cost, or variable shipping cost per SKU — that data lives in Shopify's product catalog and cost-of-goods fields, which merchants often don't even populate. Per Shopify's own documentation, the Cost per item field on each product/variant is optional, meaning POAS-equivalent reporting is simply structurally unavailable to any tool unless it's explicitly built to read and use that field.
The variant-level cost problem
Even stores that populate cost-of-goods data often do so only at the product level, not per variant — meaning a $30 small and a $30 large sold as the 'same' product might have meaningfully different actual costs if the larger size uses more material. Worked impact: if true variant costs range from $9 to $13 against a modeled flat $11 COGS assumption, a campaign skewed toward selling the large size will overstate POAS by roughly 2 percentage points of margin per order — small per order, compounding at volume.
Building a basic POAS calculation manually
Without dedicated tooling, a manual POAS build requires: exporting campaign-level revenue and spend from Google Ads and Meta Ads Manager, exporting order-level COGS and shipping cost from Shopify (via the Cost per item field and shipping reports), matching orders to campaigns via UTM parameters or platform attribution, and calculating (revenue − COGS − fees − shipping) ÷ spend per campaign in a spreadsheet. This is workable at low order volume but becomes error-prone and time-consuming past roughly 200-300 orders per month across multiple campaigns.
Where reported ROAS most commonly misleads
The gap between ROAS and POAS is largest in three common Shopify scenarios: low-margin categories like consumables or dropshipped goods (where a seemingly strong 3-4x ROAS can still be a loss), stores with high variable shipping relative to AOV (subscription boxes, bulky goods), and stores running frequent discount codes that reduce realized revenue below the order value platforms track. In each case, ROAS looks stable while true profit is eroding, often for months before it shows up clearly in bank balances.
Worked example: discount code distortion
A campaign drives $25,000 in tracked order value at 5x ROAS ($5,000 spend), looking strong. But 40% of those orders used a 20% discount code, meaning realized revenue was actually $25,000 − (0.40 × $25,000 × 0.20) = $25,000 − $2,000 = $23,000. Applying a 45% contribution margin to realized revenue: profit before ad spend = $23,000 × 0.45 = $10,350. POAS = $10,350 ÷ $5,000 = 2.07 — still healthy, but meaningfully lower than the 5x headline ROAS suggested, illustrating why discount-heavy campaigns need POAS tracking specifically.
POAS and budget scaling decisions
When deciding whether to scale a campaign's budget, POAS is the more reliable signal because it directly reflects cash generated per dollar spent. A campaign at 3x ROAS but only 1.3x POAS has very little room to absorb the CPA increase that typically accompanies scaling into a broader audience; a campaign at 3x ROAS with 2.2x POAS has considerably more buffer. Scaling decisions made on ROAS alone risk pushing a thin-margin campaign into a loss the moment CPA rises even 10-15% during expansion.
How Adsify approaches this
Adsify reads product cost data directly from the Shopify catalog and combines it with ad spend and order data to calculate POAS and profit per campaign automatically, refreshed alongside its optimizer cycle roughly every 6 hours. This removes the manual export-and-match process described earlier and lets a merchant see, at the campaign level, whether last week's 'good ROAS' campaign is actually a profit driver or a slow leak — without building a spreadsheet model by hand.
A hybrid reporting approach for stores without full cost data
Stores that haven't populated per-variant COGS in Shopify can still build a directional POAS estimate using a blended average margin percentage across the catalog, applied uniformly to campaign revenue. It's less precise than SKU-level POAS but is a meaningful improvement over ROAS alone — worked example: applying a blended 48% contribution margin to a campaign's $18,000 revenue and $4,200 spend gives profit before ad spend of $8,640 and POAS of 2.06, versus a raw ROAS of 4.3x that alone tells you nothing about whether that's a good outcome.
Making the switch operationally
Transitioning a team from ROAS-first to POAS-first reporting doesn't require abandoning ROAS — it requires demoting it to a secondary, diagnostic metric (useful for understanding CPC/CVR trends) while POAS becomes the primary metric for budget and scaling decisions. Set POAS thresholds analogous to the break-even ROAS work covered elsewhere: a POAS floor of 1.0 for pausing consideration, and a POAS target of 1.3-1.5 for continued scaling, adjusted to your specific margin and growth-stage goals.
