Jun 21, 2026 · 10 min read

Finding Margin Leakage Between Ad Spend and Shopify Profit

Daymark Product & Data TeamAnalytics practitioners at Daymark

First-hand guidance from the Daymark team on analytics workflows, growth reporting, and the operational metrics teams use to make decisions.

Your ad dashboards and your Shopify profit and loss are reporting two different businesses. Google Ads and Meta Ads show spend against attributed revenue. Shopify shows what actually got collected, after discounts, refunds, fees, and the real cost of the product. The gap between those two numbers is where margin leaks out, quietly, a little at a time, until a quarter ends and the cash doesn't match the ROAS.

This guide covers the six places that gap usually opens up, and a monthly process for catching it before it compounds into a real profit problem.

Why Ad Platforms and Shopify Never Agree on Profit

Google Ads and Meta Ads are built to report performance against their own conversion tracking. Conversion value is the order total at checkout, inside an attribution window, sometimes adjusted by modeled conversions for users the platform can't directly observe. None of that number reflects what happens to the order afterward.

Shopify's order and payout data reflects what actually happened. A $120 order can become $98 in net sales after a 15% discount code, $94 after a 2.9% payment processing fee, and $60 after a return three weeks later. The ad platform never sees any of that. It logged a $120 conversion and moved on.

That gap is not a tracking bug to fix. It's a structural difference between attributed revenue and realized profit. The fix is not better tracking. It's a margin layer that sits between the two reports and tells you what actually happened to the money.

Six Places Margin Quietly Leaks Out

Each of these shows up the same way: ad performance looks stable or improving, while Shopify profit drifts down underneath it. None of them show up in a ROAS number.

Discounting

A discount code tied to a campaign does two useful things. It gives the ad something to convert on, and it gives you a clean way to attribute revenue back to that campaign. It also does one costly thing: it lowers net sales on every order that uses it, while the ad platform still counts the full pre-discount order value as conversion value.

A campaign running a 20% code can show the same ROAS for months while contribution margin on that traffic quietly shrinks, especially once a code outlives the promotion it was built for and keeps getting used by repeat customers who would have bought anyway.

Returns and Refunds

Ad platforms attribute a sale the moment it happens. Shopify keeps adjusting the picture for weeks afterward as returns and refunds come in. A category with a 12% return rate looks identical to a category with a 2% return rate in Google Ads or Meta Ads reporting. In Shopify, they're entirely different businesses.

This matters most for categories where return rates vary a lot by product, like apparel with sizing issues or anything prone to damage in transit. If campaign budget keeps flowing toward a high-return SKU because its attributed ROAS looks fine, the margin on that spend is worse than it appears by exactly the size of the return rate.

Payment Processing Fees

Processing fees scale with revenue, not profit. They sit at roughly 2.9% plus a fixed fee per transaction for most Shopify Payments setups, more for certain card types, currencies, or buy-now-pay-later options. None of that is visible in an ad dashboard. It's a real, recurring cost that compresses margin a little on every single order, and it compresses it more on channels or campaigns that skew toward smaller average order values, because the fixed-fee portion eats a larger share of a smaller order.

Shipping Subsidies

Free shipping above a threshold, or free shipping as a blanket policy, is a real cost that ad platforms have no visibility into. If a campaign is driving orders that land just above your free-shipping threshold, you're absorbing fulfillment cost on every one of them. That cost doesn't move with the campaign's spend or its attributed revenue. It moves with order count and basket composition, which a ROAS number was never built to track.

COGS Drift

Landed cost of goods rarely stays fixed for long. Supplier price increases, new freight surcharges, packaging changes, or a shift to a different manufacturing batch can all move COGS without anyone updating the number used in margin calculations. If your contribution margin math is still using a COGS figure from six months ago, every campaign performance number built on top of it is wrong by the same margin, and getting more wrong every month the underlying cost has drifted.

This is the leak that's easiest to miss because nothing about the ad reporting changes. Spend, clicks, and attributed revenue can look exactly the same month over month while real margin quietly narrows because the product underneath got more expensive to make or ship.

Channel Mix Shifting Toward Lower-Margin SKUs

Performance Max and Meta's automated campaign types are built to chase whatever converts, not whatever is profitable. If a lower-margin SKU happens to have better creative, a lower price point, or more remarketing data behind it, automated bidding will quietly route more budget toward it. Blended ROAS can hold steady or even improve while the mix of what's actually being sold shifts toward thinner margin.

This is the leak most likely to compound, because the platform's own optimization logic is actively making it worse over time, not staying neutral. The algorithm has no concept of contribution margin. It only knows what converted.

A Monthly Process for Catching Leakage Before It Compounds

Each of these six leaks is small on its own. They become a real problem when several of them move in the same direction during the same month and nobody is looking at the combined number until a quarterly review. The fix is a recurring check, not a one-time audit.

Step 1: Pull Net Sales, Not Gross Order Value

Start from Shopify's net sales, after discounts, for the period you're reviewing. This is the number that should anchor every margin conversation. If a team is still reporting against gross order value or attributed ad conversion value as the headline revenue number, that's the first thing to fix, before any of the steps below matter.

Step 2: Apply a Real Margin Layer, Not Last Quarter's Estimate

Update COGS, payment fees, and an average shipping subsidy figure for the period being reviewed, not a number carried forward from the last time someone built this spreadsheet. The formula stays simple:

Contribution Margin =
  Net Sales (after discounts)
  - COGS
  - Payment Processing Fees
  - Shipping Subsidy
  - Returns and Refunds
  - Ad Spend

If any input in that formula is more than a quarter old, treat the output as directional, not reliable. COGS drift alone can move a margin number enough to change a budget decision.

Step 3: Break It Out by Channel and Campaign, Not Just Store-Wide

A store-wide contribution margin number can look healthy while one channel is bleeding margin and another is subsidizing it. Run the same formula at the campaign level for Google Ads and Meta Ads spend, matched to actual Shopify orders rather than each platform's self-reported conversions. Google Ads attribution and Shopify profit and Meta Ads CAC and Shopify margin both go deeper into how to do that matching for each platform specifically.

Step 4: Track SKU Mix Inside Each Channel

Pull the product mix behind each campaign's revenue, not just the revenue total. A channel with flat or rising ROAS and a mix that's quietly shifting toward your lowest-margin SKUs is the channel-mix leak in action. This is the one automated bidding makes worse on its own, so it needs a recurring check rather than a one-time look.

Step 5: Compare Period Over Period, Not Just Against a Single Snapshot

A single month's contribution margin number doesn't tell you whether a leak is opening up or holding steady. Compare the same channel and SKU breakdown against the prior month and the same month last year if seasonality matters for your category. A small, steady decline across three consecutive months is the pattern that becomes expensive. A one-off dip from a single promotion usually isn't.

Rebuilding this view by hand each month, across a Google Ads export, a Meta Ads export, and a Shopify orders and refunds export, is slow enough that most teams only do it quarterly, by which point a small leak has had three months to compound. Daymark connects Google Ads, Meta Ads, and Shopify into one workspace, so the contribution margin breakdown by channel and SKU is a plain-English question instead of a recurring spreadsheet rebuild.

What to Do When You Find a Leak

Finding the leak is only useful if it changes a decision. A simple way to triage what you find:

  • Discounting or shipping subsidy leak: check whether the promotion or threshold is still tied to a goal that's still active. Old codes and stale thresholds are the easiest leaks to close.
  • Returns leak concentrated in one SKU or category: treat it as a product or fulfillment problem, not an ads problem. Pausing spend on a high-return SKU fixes the symptom, fixing sizing, descriptions, or packaging fixes the cause.
  • COGS drift: update the margin inputs immediately, then re-run the channel and campaign breakdown. A budget decision made on stale COGS can point the wrong direction entirely.
  • Channel mix drift toward low-margin SKUs: add product-level exclusions or a margin-aware bid strategy where the platform supports it, rather than letting automated bidding keep optimizing purely for conversion volume.

Frequently Asked Questions

Why does Shopify profit keep falling when ad ROAS looks stable?

ROAS measures attributed conversion value against spend. It has no visibility into discounts, returns, payment fees, shipping subsidies, COGS changes, or a shift toward lower-margin SKUs. Any of those can erode real profit while attributed conversion value, and therefore ROAS, stays flat. The fix is checking contribution margin separately, not trusting ROAS as a profit proxy.

How often should a D2C brand check for margin leakage?

Monthly is a reasonable baseline for most Shopify brands. Weekly is better once spend is high enough that a channel or SKU mix shift would be expensive if it ran unnoticed for a month. Quarterly is too slow. Several small leaks compounding over three months can be a meaningfully larger problem than any one of them would suggest on its own.

Which leak usually costs the most, discounting or returns?

It depends on the category. Apparel and anything with sizing variability tend to lose more to returns. Promotion-heavy categories tend to lose more to discount creep, especially codes that outlive their original campaign and keep getting used long after the promotion ended. The more reliable approach is checking both every period rather than assuming one is always bigger for your business.

Can automated bidding actually make margin leakage worse?

Yes. Performance Max and similar automated campaign types optimize for conversions, not contribution margin. If a lower-margin SKU converts well, the platform will route more budget toward it without any signal that margin is shrinking. Blended ROAS can hold steady or improve while the underlying product mix quietly shifts toward thinner margin.

Do I need a finance background to build a margin leakage check?

No. The formula is simple: net sales minus COGS, payment fees, shipping subsidy, returns, and ad spend. The harder part is keeping the inputs current and breaking the result out by channel and SKU consistently every month, which is a process and discipline problem more than a finance skills problem.

Conclusion

Ad spend reporting and Shopify profit will never naturally agree, because they're measuring different things. The six leaks above, discounting, returns, payment fees, shipping subsidies, COGS drift, and channel mix shift, are where that disagreement turns into real lost profit if nobody is checking. A monthly contribution margin review by channel and SKU catches them while they're still small.

For the formula itself in more depth, see the guide to contribution margin for ecommerce. For the channel-specific version of this process, see Google Ads campaign profitability and Meta Ads real CAC against Shopify margin.

Related articles