Your ad platform grades its own homework. It counts the orders it thinks it caused, and it never hears about the ones that got cancelled, returned or refunded. I reconcile what the platform claims against what your backend actually banked โ per ad โ then fix the tracking defects causing the gap.
A D2C supplements brand, ongoing retainer. Client identity withheld; every figure below comes from a live dashboard I run โ ad platform API, first-party tracker and the shop database, reconciled against each other.
The gap was not one problem. It was two, and they multiply:
Over that window, roughly a fifth of the "revenue" the platform was optimising against never actually arrived.
| Ad | Reported ROAS | Real net ROAS | Cancel rate | Over-claim |
|---|---|---|---|---|
| Ad A | 10.39ร | 2.91ร | 16.7% | +257% |
| Ad B | 8.71ร | 5.32ร | 20.9% | +64% |
| Ad C | 5.89ร | 3.41ร | 26.2% | +73% |
| Ad D | 5.42ร | 5.14ร | 18.8% | +5% |
| Ad E | 4.44ร | 4.02ร | 23.1% | +10% |
| Ad F | 4.26ร | 2.94ร | 16.7% | +45% |
Ad A was the #1 ranked ad in the account by the platform's own numbers. Net of over-claim and cancellations, it was the worst performer in the account. Budget was flowing toward it.
Neither error is uniform. Over-claim ranged from +5% to +257%. Cancellation ranged from 16.7% to 26.2%. That matters more than it sounds: applying one blanket correction factor to the whole account โ which is what most "we adjust for returns" approaches do โ produces a different wrong answer. It has to be measured per ad.
The obvious objection to any first-party-versus-platform gap is that the first-party data is under-counting. So that gets ruled out before any conclusion is drawn:
The clicks were real. The pixel was firing. The orders genuinely were not there.
Including, for a while, mine. This is the part I would want to read if I were hiring someone.
Nearly every free pixel-checker โ and a lot of paid audits โ fetch your page's raw HTML and pattern-match for fbq, gtag, G-, AW-. Tags injected at runtime by a tag manager do not appear in raw HTML. So the audit reports them missing, and the report lands in front of a client whose developer disproves it in two minutes.
I rebuilt the engine on a real headless browser โ mobile viewport, throttled connection, watching actual outbound network requests, on both the homepage and the conversion page. Then I re-ran the 97 sites I had already audited.
97 out of 97 findings changed. Sites flagged "no analytics" had analytics. Sites flagged "no conversion tracking" were tracking conversions.
Three rules are now enforced in code, because an audit that can only ever find fault is a sales script, not an audit:
name attribute is only reported when the form also has an action. JavaScript-submitted forms do not need it, and flagging them is noise.Each of these is a real defect found in a live account, each one silently costing money before it was found.
An education account reported a CPA that looked outstanding. The "conversions" were click proxies โ phone-button taps and chat-button clicks โ set as the primary conversion action. After switching to verified leads matched back by click ID and uploaded as offline conversions, true CPA was ~13.8ร higher. Every report built on the old figure had been overstating performance by that factor.
A server-side conversion feed read cf-connecting-ip ahead of X-Forwarded-For. Behind a proxy that is always the sending server's own IP โ so every conversion was stamped with a datacenter IP instead of the buyer's. Result: junk geo data, a wrong client_ip_address sent to the conversions API, and 40 orders a day from one IP heading straight toward a repeat-IP fraud rule.
A chat-button click was firing as a conversion and the resulting enquiry was being uploaded again as an offline conversion. The bidding algorithm was being trained on double-counted signal.
An entire ad account running without dynamic URL parameters. Analytics could not attribute a single paid visit โ all of it landing as unassigned traffic, while the team debated which channel was working.
A portfolio health check reported 9 of 9 properties in the red. All 9 were false: one was a conversion-code remap, one a firewall returning 403 to the checker, the rest simply low-volume days. Alerts nobody can trust get ignored โ including the real one.
On mobile, a flex-basis value became a height. The callback form input rendered as a ~340px circle. Desktop was fine, so nobody caught it. Nine days of mobile enquiries, gone, with no error anywhere to indicate it.
Implementation is quoted separately once the audit tells us what actually needs building. Ongoing signal ownership โ acting as the tracking lead for an agency or an in-house team โ is a monthly retainer.
A 20-minute call. Bring one ad account and your backend revenue number for the same period. If I do not think there is a meaningful gap worth paying me to find, I will tell you on the call.
Remote engagements across the UAE, UK, Australia and North America. Based in India โ overlapping hours with Gulf and European mornings.