billahdotdev
2026-09-02

Your ad account is missing sales you already made

Why a meaningful share of conversions never reach the platform, and why the dashboard stays confident about it.

Here is an uncomfortable exercise. Count the orders in your own system for last month. Then count the purchases your ad platform says it produced. The two numbers will not match, and the gap is usually large enough to change what you would have done.

Nobody is lying. The events simply never arrived.

The browser is a hostile environment now

A browser conversion event is a small request that has to survive a long list of obstacles. Ad blockers remove the script outright. Tracking protection, now switched on by default in most browsers, blocks the request. The customer taps the back button before the script finishes loading. The network drops between the thank you page rendering and the event firing. On a weak mobile connection, that last one is not rare.

Each of those is a single digit percentage. Stacked together, on real traffic, the losses are not single digit anymore.

What the platform does with the gap

It does not report it as missing. It reports what it received as if that were all there was.

Then it optimises. The algorithm looks at the conversions it can see, works out what those people had in common, and goes to find more of them. If the people whose events survive are systematically different from the people whose events die, which they are, you are now paying to find more of a group that was never the point.

The cruelty is that the dashboard remains perfectly confident throughout. It has no way to display a number it never received.

Sending it twice, counting it once

The fix is old and unglamorous: send the event from the browser, and send the same event from your server, where there is no ad blocker and no tracking protection and no back button.

The only thing that makes this work is the identifier. Both copies carry the same event id and the same event name, so when the platform receives the pair it recognises them as one event seen twice, and deduplicates. Get that wrong and you have not fixed your reporting, you have doubled it, which is worse, because now the numbers are inflated and confident.

Two details decide whether this actually works. The identifier must be generated in one place and used by both paths, rather than each path minting its own. And the server events must leave from your own domain, not a third party endpoint, or you have reintroduced the exact category of request you were routing around.

What to check before you trust any of it

Open your events manager and look for the same event name arriving on both the browser row and the server row, with the platform reporting them as deduplicated. If only one row is populated, you are not sending two copies. If both rows are populated and nothing is deduplicated, your identifiers do not match and your numbers are now fiction.

That check takes five minutes. It is the difference between a measurement system and a decorative one.

Writing