D2C Playbook 3-- Why your conversions look too good
The short version
Every D2C brand is running ads on Meta and Google. If you're reading their conversion numbers and trusting them, this one's for you. Those numbers are inflated, in two separate ways, and the gap between what the platforms claim and what you actually made is the most expensive blind spot in your account. The fix isn't to make the numbers match. You can't. The fix is to take only your spend from the ad platforms, build attribution in-house, and treat your own model as the source of truth.
Your backend is telling you the truth. The ad platforms aren't.
Start from the one number you can trust. Your backend records an order the moment payment is captured. No model, no window, no attribution guesswork, just a financial record of money that actually arrived. Whatever your system of record is, your own database, your order table, your payment provider, that's your truth about revenue.
Now put the ad platforms next to it, and you'll see two different problems. They're worth separating, because they have different causes and different fixes.

Problem one is the totals. Add up the revenue Meta says it drove and the revenue Google says it drove, and the sum comes out higher than what your backend recorded for the same week. The platforms, combined, are claiming credit for more sales than your business actually made. The money on the dashboards doesn't fit inside the money in the bank.
Problem two is per-channel. This one only shows up if you have a product analytics setup of your own. Say your own data says Meta contributed ₹10,000 this week. You open Meta, and Meta says it drove ₹20,000 for the same period. Same channel, same dates, double the number. Your model and Meta's model are looking at the same reality and reporting two different answers.
Two problems, not one. Let's take them in order, because the second is really the first plus one extra thing.
Why the totals don't add up
The first problem is double-counting, and it's almost mechanical once you see it.
Picture one customer. They see your ad on Instagram in the morning. Later that day they search your brand on Google and click. Then they buy. One sale. But Meta saw that user and counts it as a Meta conversion, because its default setting is 7-day click and 1-day view, and that view counts. Google saw a click and counts it as a Google conversion. Both platforms log the same single order as their own win. Neither is told about the other. So the same ₹1,000 sale shows up in two places, and when you add the dashboards together you've counted it twice.
There's a second layer to the totals problem on the Meta side specifically, and it's the 1-day view. If someone scrolls past your ad without clicking, then buys hours later through a Google search or by typing your URL, Meta still records that as its own conversion. The ad may have planted the idea. It may have been noise the buyer never registered. Meta can't tell the difference, because it can't even prove the ad was looked at, and it credits itself anyway. That's revenue Meta is claiming that, by any honest read, Google or direct should get, or that nobody earned.
A detail worth knowing, because it tells you which number was always soft: in January 2026 Meta permanently removed the 7-day-view and 28-day-view windows from its reporting API. You can no longer ask Meta to credit a conversion to an impression from three weeks ago. When the platform itself quietly retires the long view windows to look more like independent analytics, that's the platform admitting those windows were padding the count.
So the totals overshoot because every platform grabs credit for the same orders, and Meta grabs a little extra on top through view-through. Nobody's lying. They're each grading their own homework, generously, in isolation.
Why one channel reads double
The per-channel gap, your model says ₹10,000 and Meta says ₹20,000, is the double-counting above plus one more thing: the customers you can't attribute at all.
Here's the case that does most of the damage. A customer sees your Meta ad on their phone. They don't buy. Two days later they come back on their laptop and purchase. If you haven't set up a way to recognize that the phone visitor and the laptop buyer are the same person, your own analytics sees a brand-new anonymous user who arrived with no ad touch, and it files that sale under direct. Your in-house number for Meta is missing that customer entirely. That's part of why your model reads low at ₹10,000.
But Meta isn't missing them. Meta recognized that user across the session, through its own logged-in graph, and counts the sale as Meta-driven. So Meta reads high, partly because it's claiming view-through and shared credit it shouldn't, and partly because it genuinely connected a cross-device journey that your setup dropped.
This is the part that ties back to Part 2. The reason your model under-counts isn't that your model is dumb. It's that reconciling one human across devices, browsers, and sessions is genuinely hard, and most setups quietly fail at it. On a single device it's already fragile: Safari's tracking prevention caps a JavaScript-set cookie at seven days, and drops it to twenty-four hours if the visit carried a click ID like fbclid or gclid, so a Safari user who takes longer than a week to return looks like a new person and the original ad touch is gone.
How you reconcile users
The per-channel problem is fixable, but only if you can recognize the same person across their journey. There's no magic here, and anyone selling you magic is selling you false matches. There are two honest approaches and one lever that beats both.
Deterministic reconciliation links sessions through a shared identifier you actually have, an email, a logged-in user ID, an anonymous ID you pass through deliberately. The moment you have a key, you call your analytics tool's identify() and it retroactively stitches the earlier anonymous events to that person. This is what Mixpanel, PostHog, and Amplitude all do under the hood. It's clean, and it's the one most teams should rely on. Its limit is obvious: it only works once you have a key, so the cold anonymous part of the journey stays unsolved.
Probabilistic reconciliation, fingerprinting, tries to match sessions by device and behavioral signals without a shared key. It's how you'd attempt to connect that phone-then-laptop journey when neither session logged in. Be careful with it. Mobile-to-desktop matching is exactly where fingerprinting performs worst, and false matches mean your funnels start lying in a new and harder-to-spot way. Reach for it only if attribution accuracy genuinely matters more to you than analytics integrity, which for most D2C brands it doesn't.
The lever that beats both is capturing identity earlier in the funnel. If your flow is land, browse, sign up, you'll lose cross-device until signup every time. If you can shift it to land, then email gate or lead magnet or WhatsApp opt-in, then browse, then buy, you've got an identifier days or weeks earlier and the deterministic stitch just works. This is where most of the real recovery comes from. Not a clever algorithm, an earlier email.
And one piece that connects directly to the platforms: pass the ad click IDs, gclid, fbclid, through to your backend and into the platform's Conversions API. That gives you a server-side, deterministic link between a specific ad click and a specific order, which is the cleanest cross-device signal you can get, because it doesn't depend on a cookie surviving in the browser.
You will not reconcile everyone. You can reconcile enough that your in-house number stops being a guess.
The right way to use these numbers
Here's the whole thing in one rule. From the ad platforms, take only your spend. Build attribution in-house, and treat that as your source of truth. Treat the ad platforms' conversion numbers as a secondary, biased reference, never as the primary record.
Spend is the one number in the relationship the platform can't inflate. You know what you paid, to the rupee. Everything the platform reports past that, conversions, attributed revenue, ROAS, is the platform marking its own exam, and it marks generously. So you pull spend from Meta and Google, and you pull revenue and attribution from your own warehouse built on your own events, reconciled with the methods above. That model becomes the number you put in the board deck, the number you allocate budget against, the number you trust.

If building full in-house attribution sounds like a lot, build it anyway, even a basic version. A first-touch or last-touch model on your own reconciled event data, sitting in your own warehouse, is worth more than the prettiest dashboard Meta will ever show you, because it's yours and it isn't biased toward selling you more ads. Start simple and make it your source of truth from day one.
Then use the gap as a diagnostic. Once you have your own model, the difference between it and the platform's number stops being noise and starts being a signal. A roughly stable gap is normal, that's just the platform's built-in bias being consistent. But a huge gap, or a gap that suddenly moves, almost always means one of two things: your attribution is broken, you're losing users you should be reconciling, or your conversion tracking setup on the ad platform is broken, your Conversions API is misfiring or your pixel is double-counting. Either way the gap is telling you where to look. You can only read that signal if you have your own number to compare against, which is the entire reason to build one.
What to do Monday
Pick your system of record and write it down. For most D2C brands that's your backend order data or your payment provider, the place that logs an order when money actually moves. Every revenue number that leaves the building comes from that one source, not Meta, not Google.
Stop trying to reconcile the platforms to each other. Take the recurring hours your team spends making Meta match your backend and kill that task. The numbers aren't supposed to match. The only number you make match anything is your own in-house model against your own system of record.
Pull spend, not conversions, from the ad platforms, and start building your own attribution on reconciled events, however basic. Pass your click IDs server-side, capture identity earlier in the funnel, and get your own number standing on its own feet.
Then watch the gap. When your model and Meta drift far apart, treat it as an alarm on your own setup, not as a number to average out. The brand that has its own source of truth and knows how to read the gap is the one that stops setting budget on fire.
Want this on your own stack?
Datalyze rebuilds your data foundation, then finds the growth it's been hiding — proven across 150+ startups.
Book a free analytics audit →