How a CDN Was Quietly Corrupting Their Ad Tracking and Draining the Marketing Budget

A green CAPI status, totals that matched the backend, and a budget bleeding anyway. The bug was hiding one layer below everything anyone thought to check

A declining red ROAS chart beside two panels showing a losing ad getting 85 percent of the budget and a winning ad getting 15 percent, under the headline Corrupted Ad Tracking

We were hired by Andrew Hanoun, metabolism and weight-loss coach, Tony Robbins Platinum Partner, running a webinar-driven funnel that had been working for a long time. His marketing team hired us to figure out why it stopped.

He had a custom tracking setup. Not a single app you switch on, but a custom stack with a lot of moving parts wired together behind the scenes.

Then it broke. Performance fell off a cliff, money was leaving every day, and nothing on any dashboard explained why.

That is the worst kind of broken. Every number looks fine and the money leaves anyway.

So we did what you do when an account is bleeding money for no visible reason. We started ruling things out.

The wild goose chase

The list of obvious causes was long. We turned over every stone an experienced media buyer would, because skipping that step is how you end up treating the wrong disease.

We rechecked CAPI, then rechecked it again. We went back through every recent change on the account, looking for the edit that lined up with the day performance dropped.

We analyzed placements. We checked for bot traffic and junk clicks inflating the numbers. We added creative diversification in case the account had simply fatigued.

We tested CBO against manual bidding, then layered in cost caps. We swapped optimization events to see if the account was chasing the wrong signal. We spun up a separate ad account entirely.

And when even that did not move things, we started warming a brand-new ad account on a fresh domain with a new pixel, the clean-slate reset that is supposed to rule out account-level rot.

If you run ads, you already know what that list actually costs. It is not a checklist you breeze through in an afternoon.

Each one of those is days of spend, days of waiting for data to mature, days of telling yourself this next test is the one that cracks it.

And at the end of all of it, the account is still bleeding money the exact same way it was when you started. The list is long, the spend is real, and the needle does not move.

Every standard fix came back clean, which told us the problem was not in any of the places everyone is trained to look.

The misleading clue

A detective in a hat inspecting an analytics dashboard through a magnifying glass, with charts and a string-linked evidence board behind him
Every standard fix came back clean, so the only clue left was the gap between the data sources

So when the obvious causes are exhausted, the next move is to stop guessing and start comparing the numbers against each other, because the gap between two data sources is usually where the truth is hiding.

That comparison gave us our first real clue. And it pointed us in exactly the wrong direction.

We stopped looking at any single dashboard and started lining up the data sources side by side, because no source lies in isolation. They lie in the gaps between each other.

So we put three of them next to one another: the data from their custom tracking, the registration backend that recorded who actually signed up for the webinar, and Facebook's own ad-level numbers, which we pulled straight from its API to see the per-ad breakdown.

We could line all of it up ad by ad because their tracking tagged every conversion with the ad's name through its UTM parameters, the same ad names Facebook reports against.

The tracking data matched the registration backend almost perfectly. Same people, same totals, same numbers the business could verify against its own records. That is the part you want to see.

But when we held that data up against Facebook ad by ad, the breakdown did not line up. The totals were close. The per-ad attribution was not.

Facebook was crediting purchases to ads in a pattern that the backend simply did not agree with.

That is a strange kind of mismatch, and it is the kind that is very hard to see.

Matching the backend total to the per-ad breakdown only works if you can look at the data at the level of every individual ad, independent of click order and timeframe.

Facebook runs last-click attribution and hands the whole sale to whichever ad happened to be clicked last, even when two earlier ads did the real work to get there.

Most advertisers can see a campaign total, but they cannot see whether ad number four is being credited for sales that ad number seven actually produced.

Pulling that comparison from API by hand takes real attribution expertise, though. You have to know how to get ad-level data out of Facebook's API and reconcile it against your real conversions, which most advertisers neither know how to do nor should have to.

That is the part TrueMetriks does for you automatically, showing how much each individual ad actually contributed instead of just a campaign total.

The numbers matched the backend perfectly and still disagreed with Facebook ad by ad, and that single granular discrepancy was the only honest signal the whole investigation produced.

The red herring

Naturally, we assumed it was CAPI, because a per-ad gap against the platform is exactly what a broken CAPI connection looks like.

So we tested it, and then we tested it again. And that is where the case nearly died.

A lot of advertisers treat a healthy CAPI connection as proof that tracking is working. The match rate is high, the events are flowing, the status is green, so the conclusion is that the data must be correct.

It is a reasonable belief. It is also exactly the belief this account quietly broke.

We re-ran the CAPI checks repeatedly. The match rates stayed solid. The totals stayed right. Events were arriving the way they were supposed to.

By every accepted measure of CAPI health, the connection was fine. And the symptoms were intermittent on top of all that, flaring up and settling down, which is what dragged the diagnosis out for so long.

There was nothing steady to grab onto. Every test we ran pointed at a healthy connection, and a healthy connection does not explain a bleeding account.

The only reason we had any signal at all was the ad-level comparison we obtained by using Facebook's API.

Without lining up the real conversions against Facebook ad by ad, there is nothing to check the platform against, and the symptom never appears on any screen.

It is not that the discrepancy was hard to find, it was hard to figure out where to look in the first place.

And what this account proved is the thing the pixel and CAPI firing green never tell you. A green status confirms the connection is alive and the data is moving.

It says nothing about whether the data moving through it is correct. You can have a perfectly healthy pipe carrying contaminated water, and every gauge on that pipe will read normal.

CAPI was healthy by every measure we could throw at it, which forced the uncomfortable conclusion. The data going into it was already wrong before CAPI ever touched it.

The reveal

A browser at yourfunnel.com slash landing-page with a red price tag reading UTM_SOURCE equals ad_123, UTM_MEDIUM equals cpc, UTM_CAMPAIGN equals sale frozen onto the cached page
The cached page carried someone else's UTMs, frozen into the HTML before any tool saw the click

So if CAPI was passing clean data through a healthy connection and the numbers were still wrong, then the corruption had to be happening before the data was ever captured.

Which meant going back to the one place nobody had thought to look. The page itself.

The funnel's landing pages were being served through a CDN. That is completely normal.

A CDN caches your pages and serves them from a location close to the visitor so they load fast, and for almost everything, faster pages are a good thing.

Nobody looks at a CDN and thinks tracking problem. It is plumbing. It is supposed to be invisible.

But these cached pages had Facebook UTMs baked directly into the HTML. The tracking parameters, the ones that tell the system which ad a visitor came from, were frozen into the version of the page the CDN had saved.

So when a new visitor clicked an ad and landed on the funnel, the CDN did exactly what it is built to do. It served them the cached page.

And that cached page came carrying someone else's UTMs, not the ones from the ad they actually clicked.

In plain English, every new click could be tagged with the wrong ad's identity.

The data was not getting corrupted in transit, and it was not getting corrupted by CAPI. It was wrong at the moment of capture, before any tracking tool ever saw it.

The system was faithfully recording an identity that had already been swapped.

And this is the part that turns a reporting glitch into lost money. Wrong source data does not just sit on a dashboard looking wrong. It gets sent back to Meta.

That is how the algorithm learns which ads to scale and which to shut off. So once the click data is mislabeled, the algorithm optimizes against the wrong ads.

It reads the contaminated signal, draws the wrong conclusion, and acts on it with your budget.

Picture what that actually does over a few weeks. An ad gets credited for conversions it never produced, so Meta marks it a winner and pours more spend into it.

Meanwhile the ad that was quietly carrying the whole account gets credited for less than it earned, so Meta marks it a loser and starves it.

You end up scaling something that was never working and killing the one thing that was. From the outside, it just looks like the account is getting worse for no reason.

The CDN was caching the pages with one advertiser's UTMs frozen into the HTML, so every new click was being credited to the wrong ad before any tracking tool ever saw it.

The validation

A theory that explains the symptom is not the same as a confirmed cause, and on a client's account you do not get to rebuild anything on a hunch.

So before touching the funnel, we proved it the simplest way possible.

Here is the actual confirming test, and it is almost embarrassingly simple. You open the live ads, click through the preview links, and watch the URL you land on.

Then you compare two things: the UTMs that ad should have fired, and the UTMs that actually showed up in the address bar after the page loaded.

They did not match. The cached page was overwriting the real UTMs with stale ones, swapping the correct ad identity for a frozen one, exactly as the theory predicted.

We were not inferring it from a chart anymore. We were watching the wrong parameters load in front of us, on demand, every single time.

So sit with the gap between how hard this was to find and how easy it was to confirm. The entire mystery came down to a check anyone could run in two minutes once they knew where to look.

The hard part was never the test. The hard part was knowing the symptom existed at all, because nothing in the standard process ever sends you to that page to look.

Clicking the live ad and watching the wrong UTMs load in the URL confirmed it in under two minutes, and the only reason it took weeks to get there was that nothing in the standard playbook ever points at the page.

The fix

Confirming the cause is satisfying, but it does not get the client's money back, so the last job was a fix that would hold.

And the cleanest-sounding fix was not the one the client could actually use.

What worked was rebuilding the funnel on a different funnel builder, keeping the exact same URLs, and repointing the domain at the new build.

The moment that went live, tracking corrected. The per-ad numbers fell back into agreement with the backend, and the account stopped bleeding into ads that had never deserved the spend.

This is now part of our standard troubleshooting protocol, because once you have seen this trap you stop assuming the page is innocent.

The rebuild was the blunt instrument, though, and it is worth being honest about that. Cleaner fixes exist in principle.

You can configure the cache to bypass itself whenever a query string is present, so any URL carrying UTMs gets served fresh instead of from the frozen copy.

Better still, you can read the UTMs client-side from the live URL instead of baking them into server-rendered HTML that then gets cached.

Reading the UTMs client-side is the architecturally correct fix, the one that removes the whole class of problem instead of patching one instance of it.

So why the blunt instrument? Because the right fix was unavailable. The funnel was locked down on a platform that did not give us that level of control over caching or how the parameters were read.

The clean solution existed; the platform simply would not let anyone reach it. That is why the client had to swap builders entirely.

And it is worth being clear that this is not about one bad platform. Any cache sitting in front of any funnel that bakes parameters into the HTML can do this. The trap is the architecture, not the brand name.

The moment the funnel served live UTMs instead of cached ones, the tracking corrected on its own, which is the surest sign you ever get that you found the real cause and not just another symptom.

What actually broke

A left-to-right flow of flat icons: an ad, a frozen CDN cache, a document marked Wrong UTMs, a green-check CAPI server, and the Meta algorithm optimizing the wrong ads, with scattered ad tiles falling away
The wrong ad identity was baked in at the CDN, then passed cleanly through a healthy CAPI to Meta

So go back to the question the account opened with. CAPI checked out. The pixel fired green. The totals matched the backend.

And the budget was draining anyway into ads that were never winning, because the answer to what could possibly be draining the budget lived a layer below everything anyone thought to check.

It was the cached page, swapping one click's identity for another's before any tool ever saw it.

The thing to carry out of this is not the CDN, or the UTMs, or the specific platform.

It is that a green CAPI status and matching totals can both be true while an account quietly loses money, because correctness is not decided at the level of the summary. It is decided at the level of the individual click.

The advertiser who can only see totals does not just struggle to fix this symptom. They never even know it exists.

And that is the uncomfortable truth about tracking. It is invisible until it costs you.

These things happen, and they happen to careful people running real setups, because all it takes is one small thing nobody thought to question and suddenly you are pouring budget into ads with no real idea which ones are working.

The entire job of tracking is to tell you where your money actually goes. When it quietly breaks, you are flying blind while believing you can see, and you keep paying for the privilege.

That is the whole case for getting tracking right from the start instead of discovering months later that you never had it.

This client had a custom stack with serious work behind it, and it still took an outside audit and weeks of digging to surface a problem that was costing real money the entire time.

That is exactly the gap TrueMetriks is built to close. Accurate tracking out of the gate, ad by ad, so you can see where every dollar is actually working before it ever turns into the kind of slow bleed nobody can explain.

Fahir Mehovic

Fahir Mehovic

Founder of TrueMetriks. Ten-plus years running paid ads and building tooling that survives platform measurement gaps. More about Fahir.