Ad Attribution Tracking: the Complete Stack | Metrikia
Ad tracking and analytics
Tracking & Attribution16 minJul 1, 2026Updated Aug 7, 2026
BN

Baptiste Noel

Growth and co-founder of Metrikia

  • Master en neurosciences et neuropsychologies cliniques
  • Master en entraînement et optimisation de la performance
  • Créateur SaaS et de contenu, 20 000+ abonnés LinkedIn

Co-founder of Metrikia, Baptiste is building a SaaS from scratch and shares the growth journey unfiltered. A former clinical-neuroscience researcher and physical-performance coach, he built then left a coaching business generating over 70,000 EUR per month before focusing on product. He writes about growth strategy, acquisition and scaling.

LinkedIn

How to Build Ad Attribution Tracking That Actually Works: The Complete Stack, Layer by Layer

Build ad attribution tracking layer by layer: UTMs, pixel, platform links, CAPI, Stripe and CRM reconciliation, MMM. So your data finally agrees.

Partager

A company that spends seriously on advertising almost always has the same problem. Meta reports a 5x ROAS. Google claims another. TikTok a third. And when the founder adds up all three dashboards, they get more sales than the store ever collected. The data is everywhere, and yet nobody in the company knows which number is true.

This is not a tool problem. It is an architecture problem. Good tracking is not a piece of software you install, it is a stack of layers you build in the right order, from the foundation up to strategic measurement. Each layer solves one precise problem, and each one only holds if the one below it is clean. This article is the blueprint for that stack. By the end, you will know exactly what to connect, in what order, and why.

On the menu:

  • The foundation 90% of companies botch, and why everything collapses on top of it.
  • Why your pixel went half-blind in 2021.
  • Pixel plus CAPI deduplication explained exactly, the mistake almost everyone makes.
  • How to send your actually-collected Stripe sales back to the platforms.
  • The strategic layer, MMM and incrementality, and the measured gap between reported ROAS and causal truth.

The mental model: two layers, not one

Before the technical detail, one idea that organizes everything else. A measurement system does two very different things, and most companies conflate them.

The first is delivering the signal: capturing events on your site and sending them to the platforms so they can optimize. The pixel, the Conversions API, server-side, all of it serves this. It is plumbing. It moves the data, it does not judge it.

The second is verifying, independently, what those platforms claim. Reconciling their assertions against what you actually collected, deduplicating across channels, and measuring what the ad truly caused. That is accounting and science, not plumbing.

The classic trap is believing that improving the first layer improves the second. Connecting the CAPI recovers more events, but those events are still graded by the party selling the ads. The CAPI fixes what the platform sees, not what actually works. Keep this distinction in mind: layers 1 to 4 deliver the signal, layers 5 to 7 verify it.

Vertical diagram of the seven layers of the tracking stack, from UTM naming at the base to MMM and incrementality at the top, numbered and colored from foundation to strategic layer.
The seven layers, in the order you build them: clarity increases from foundation to top.

Layer 1: naming and UTMs, the foundation everyone botches

Everything starts with how you name things. UTM parameters are five bits of text appended to your links that your analytics reads to know where a visitor came from: utm_source (the platform, e.g. meta or google), utm_medium (the channel type, cpc, social, email), utm_campaign (the campaign), and two optional ones, utm_content (to tell two creatives apart) and utm_term (originally the keyword, today often the audience).

It sounds trivial, and yet this is where 90% of systems break, silently. Three rules prevent the chaos. First, everything lowercase, no exceptions, because your analytics is case-sensitive and Google and google become two different sources that fragment your reports. Second, hyphens between words, never spaces, so you do not see %20 appear in your data. Third, a single documented taxonomy, a spreadsheet that fixes the allowed vocabulary and that the whole team respects, ideally via a UTM builder that only accepts approved values.

One technical trap is worth knowing. Never manually tag your Google Ads final URLs with UTMs. Google uses its own mechanism, auto-tagging, which appends a gclid identifier to the link. Adding your UTMs on top can overwrite that gclid and break conversion import between Google Ads and your analytics. Let auto-tagging do its job on Google, and reserve manual UTMs for the channels that have none, like email, organic social, or partners. A readable campaign naming convention on top, of the platform-objective-audience kind, makes your reports legible with no effort. This naming discipline is the bedrock of everything that follows, and it maps to the first of the three levels of attribution a company must climb.

Layer 2: the pixel, and why the browser went blind

The pixel is a piece of JavaScript that loads in the visitor's browser. On page load it fires a base event, the PageView, then standard events when the user acts: ViewContent, AddToCart, InitiateCheckout, Purchase with value and currency. It reads and sets first-party cookies, and transmits those events to the platform from the browser.

The problem is that this channel has eroded, and you need to understand why to grasp everything else. Four forces made it partially blind. The best known is Apple's App Tracking Transparency, which arrived with iOS 14.5 on April 26, 2021: when a user clicks a Meta ad inside the iOS app and declines tracking, the link between ad exposure and the conversion on your site is severed. The second is Safari's anti-tracking protection, which caps JavaScript-set cookies at seven days, so identifiers expire fast. The third is ad blockers, which simply stop the script from loading or firing. The fourth is consent: a user who refuses cookies gates the pixel.

The net result is that the pixel systematically under-counts and under-matches. There is no reliable universal loss rate, so be wary of the round numbers vendors quote. What matters is the principle: the browser alone is no longer enough, and that is exactly why the server layer exists. We detailed this shift in our article on server-side versus the pixel.

Layer 3: platform connections and click identifiers

Platforms know your spend natively, since it is their billing. What they do not see are your conversions, which happen on your side. To bridge that, each platform stamps every click with an identifier it can later match against a conversion you send back.

At Google, auto-tagging appends a gclid to the landing URL, stored in a first-party cookie, which Google reads back at conversion time to tie the exact click. The gclid is case-sensitive, and on iOS where it is unavailable, Google uses gbraid and wbraid. At Meta, three identifiers matter: the fbclid appended to the URL on click, the _fbp cookie that identifies every visitor's browser, and the _fbc cookie built from the fbclid. That _fbc must never be hashed or fabricated: you only create it from a real fbclid.

These identifiers enable a deterministic match between your conversion and the originating click, far more reliable than the probabilistic modeling the platform falls back on when they are missing. This layer is also where a major source of confusion plays out: each platform applies its own attribution window.

PlatformDefault windowNote
Meta7-day click, 1-day viewThe 7- and 28-day view options were removed in January 2026
Google Ads30-day clickData-driven attribution by default, last click the only alternative
TikTok7-day click, 1-day viewEvents API dedup on event_id plus event_name

These different windows explain a good part of the numbers that do not match from one dashboard to the next, a topic we dig into in the conversion deduplication guide.

Layer 4: server-side and the Conversions API

This is the layer that repairs the pixel's erosion. Instead of firing the event from the browser, your server sends it directly to the platform, server to server. Because it does not run in the browser, it bypasses ad blockers, Safari's cookie cap, and much of the loss tied to ATT.

Meta's official recommendation is to send the same event from both sides at once, through the pixel and through the Conversions API. This redundancy maximizes the match rate. But it creates an obvious risk: counting the same sale twice. This is where deduplication comes in, and you need to understand it exactly, because it is the most common mistake in the field.

Flow diagram showing the browser pixel and the Conversions API sending the same event with a shared event_id to Meta, which deduplicates on event_id plus event_name within 48 hours and keeps only one event.
You send the same event from both sides; dedup runs on event_id + event_name, not on fbp/fbc.

Dedup runs on two things: a unique event_id you generate for each action and send identically from the pixel and from the CAPI, and the event_name. If Meta receives two events with the same event_id and the same event_name within a 48-hour window, it treats them as one action and keeps only one. The event_id must match to the character, and a misspelled event_name, Purchase versus purchase, breaks dedup and doubles the count. The crucial point almost everyone gets wrong: the fbp and fbc identifiers are not used for deduplication. They are for matching, that is, tying the event to a user and a click. Dedup itself runs solely on event_id plus event_name. A bad server-side install is worse than none, because it fails silently.

A practical signal to watch on this layer is Meta's Event Match Quality, a 1-to-10 score measuring how well your events tie to Meta accounts. Server-side raises it mechanically by carrying richer identifiers at checkout. But keep a level head: it is a proxy for match rate, not a guarantee of performance or truth.

The other platforms follow the same logic. Google offers Enhanced Conversions, which send SHA-256-hashed first-party data at conversion time, and offline conversion import. For lead and long-sale journeys, Google now recommends Enhanced Conversions for Leads, which capture hashed data at form submission then tie the downstream signed deal without storing the gclid. Note for new builds: starting June 15, 2026, these imports migrate to Google's Data Manager API and will no longer go through the legacy API. TikTok has its Events API, with the same dedup on event_id plus event_name within 48 hours. And Google's Consent Mode handles consent by modeling conversions lost when the user declines. One last honesty point, developed in our article on offline conversions: recovering more events is not the same as measuring the incremental. Server-side reports more conversions, but some would have happened anyway.

Layer 5: revenue truth, from Stripe and the CRM

The pixel records a Purchase value at checkout. But that value is a purchase intent, not collected cash. The real revenue lives elsewhere: in Stripe and in your CRM. Trials that convert, subscriptions that renew, installment plans, payments that fail then succeed, refunds, defaults. Sending the platforms the revenue actually collected, rather than the value displayed at checkout, changes everything, because their bidding algorithms start optimizing for real value.

The mechanics come down to four moves. First, capture the match keys at checkout and store them durably: the fbc and fbp, the gclid, and the hashed email, in Stripe's customer metadata and in the CRM. This is the linchpin of everything, because you can only match a future Stripe payment to an ad if you kept those keys at acquisition time. Second, listen to the Stripe webhooks that signal real money: checkout.session.completed, invoice.paid at each installment, charge.refunded for refunds. Third, on each webhook, push a server conversion to Meta and Google with the actually-collected value and the timestamp of the real payment. Fourth, handle refunds by sending conversion adjustments, which lets you claw back from reported ROAS the money that was returned.

This is also where two numbers you should always show side by side diverge: the signed deal value, useful for forecasting, and the cash actually collected, which is reality. A 6,000-euro deal in six installments reads as 6,000 in most tools the moment it is signed, while only 1,000 has hit the bank. The same caution applies to lifetime value. Take two customers: one signed 4,500 euros paid in three installments, all received, the other 3,000 euros in six, of which two installments collected. Promised LTV is 7,500 euros, realized LTV is 5,500. On a Meta acquisition at 800 euros, that gives a promised ROAS of 9.4 versus a real ROAS of 6.9. Steering on the first number means scaling on money that is not yet in the bank. This is the whole point of our article on installment payments. Be honest about the difficulty: match keys have a limited lifespan, and a sale collected 60 or 90 days after the click often falls outside the platform's attribution window, even with perfect matching. Long-payment revenue is structurally under-credited by the platforms, and that is precisely why the next layer exists.

Layer 6: reconciliation, your independent source of truth

We now enter the second layer of the model, the one that verifies instead of delivering. The principle is simple: your source of truth is not the platforms, it is your CRM and your bank account.

The need is obvious with an example. A single 500-euro sale in your CRM can be claimed at the same time by Meta in its view window, by Google in its 30-day click window, and by TikTok. Each counts it for itself, and you end up with 1,500 euros reported for 500 collected, a ROAS divided by three. This is not a bug, it is the platforms' business model: each grades its own copy and ignores the others. At the scale of a 10,000-euro budget, Meta may declare 25,000 euros, Google 18,000, and TikTok 12,000, so 55,000 reported for maybe 25,000 actually collected.

No platform can solve this, because none knows the others' claims. Only an independent source can, and that source is the revenue collected in your CRM. Reconciling means starting from each real sale, tying it to the campaign that sourced it, and deduplicating across channels so one order stays one order. This is also where you choose an attribution model to split credit across touchpoints, among the nine classic models, from last click to data-driven. The result is the gap between the ROAS the platform claims and the ROAS computed on cash, the only one you can steer a budget on without lying to yourself.

Layer 7: MMM and incrementality, strategic measurement

The first six layers give you a number faithful to your bank account, day to day. The seventh answers a question even reconciliation does not settle: what did the ad actually cause? A reconciled sale is still a sale that might have happened anyway.

Two complementary methods live here. Marketing mix modeling estimates each channel's contribution from two numbers you own, spend and revenue, on aggregate totals, never touching an individual identifier. It is therefore immune to ATT and cookie loss, which is why Meta and Google open-sourced their own MMM tools, Robyn and Meridian, right after 2021. We explain it end to end in our marketing mix modeling guide. Incrementality is the causal arbiter: by comparing an exposed group to a deliberately unexposed control group, an incrementality test measures real lift, the sales the ad actually created.

The gap between what attribution declares and what incrementality measures is enormous, and it is documented. In a landmark study across fifteen randomized experiments at Facebook, the authors show that in half the cases attribution is off by a factor of three, and in one extreme case estimates an effect of 1,306 percent where the experiment measures only 2.4 (Gordon et al., 2019). Attribution always overstates in the same direction, and the worst of it plays out bottom-funnel, on retargeting. The practical lesson: the best-run stacks run attribution daily, MMM to set the budget quarterly, and a regular incrementality test to keep the whole thing honest.

The reference architecture

Put end to end, these layers form a closed loop. Spend goes out to the platforms, the click is stamped, your site captures the event via pixel and server with a shared event_id, real revenue is collected in Stripe and the CRM, everything is reconciled into a single number, then the collected conversions are sent back to the platforms so they optimize on real cash. It is this cycle that turns scattered data into clarity.

Closed-loop architecture diagram: ad platforms, your site with pixel and server, reconciliation, and real Stripe/CRM revenue, with collected conversions sent back to the platforms.
The closed loop: spend goes in, real revenue is captured and reconciled, then sent back to the platforms.

Two ideas are enough to never get lost in this diagram. First, layers 1 to 4 deliver the signal, layers 5 to 7 verify it. Second, each platform grades its own copy, so the only impartial judge is your collected revenue. A company that holds these two ideas stops adding up dashboards that contradict each other and starts steering on a number it can defend.

The mistakes that break everything, as a checklist

Most systems do not fail loudly, they drift silently. Here are the faults that recur most. An inconsistent event_name between pixel and CAPI, which doubles the count. An event_id not shared, which prevents any dedup. UTMs tagged by hand on Google Ads, which overwrite the gclid. Match keys never stored at acquisition, which make it impossible to reconcile Stripe revenue later. Dashboards added up as if the platforms did not overlap. And the total absence of an incrementality test, which lets you believe in a ROAS the ad did not produce. Each of these mistakes is invisible until you go and look at the cash.

Where clarity actually arrives

Building this stack by hand is entirely possible, and many technical teams do it. It requires a server-side container, flawless discipline on event_ids, durable storage of match keys, Stripe webhook logic, a reconciliation layer that deduplicates across channels, and the means to run MMM. It is an ongoing engineering project, not a checkbox.

This is exactly the work Metrikia operationalizes, on layer 2 of the model, the verification layer. It connects your spend and your collected revenue, ties each real sale to its source, deduplicates across channels, and lays an AI analysis layer on top, Diana, which reads that reconciled data and surfaces what changed and why. It does not replace the pixel or the CAPI, the signal-delivery layer stays with the platforms. It provides what the platforms cannot: a single number, anchored to the cash you actually banked, across every channel. If you are weighing the tools that exist for this layer, we reviewed them all in our honest comparison of ad attribution tools.

Frequently asked questions

Where do I start if my tracking is a mess? At the bottom of the stack, always. Clean up naming and UTMs first, because no layer above holds on a dirty foundation. Then check that your pixel and CAPI really share one event_id per event, to stop double-counting. These are the two settings that unlock the most clarity for the least effort.

Do I need server-side, or is the pixel enough? The pixel alone under-counts since iOS 14.5, ad blockers, and Safari's cookie limits. Server-side recovers part of that lost signal and improves the match rate. But remember that it delivers the signal better without making it truer: you need the reconciliation layer on top to know what you actually collected.

How do I send my Stripe sales back to the platforms? By storing the match keys (fbc, fbp, gclid, hashed email) at checkout, then listening to Stripe webhooks to push a server conversion on each real payment, with the true collected value. Refunds are handled with conversion adjustments. The real difficulty is not technical, it is the window: a sale collected too late falls outside the platform's attribution window.

Why do my three dashboards report more sales than my bank? Because each platform grades its own copy on its own window, and none knows the others' claims. The same sale is counted by Meta, Google, and TikTok at once. The only way to count it once is to start from the revenue collected in your CRM and deduplicate across channels.

Are MMM and incrementality only for big companies? MMM needs history and a significant budget, so it becomes relevant at a certain scale. Incrementality, on the other hand, is accessible earlier: a geo-lift test, which compares exposed regions to control regions, sets up without any individual identifier and answers the only question that truly matters, what the ad actually caused.

References

Apple. (2021). App Tracking Transparency [Developer documentation]. https://developer.apple.com/documentation/apptrackingtransparency

Google. (n.d.). About auto-tagging. Google Ads Help. https://support.google.com/google-ads/answer/3095550

Google. (n.d.). About enhanced conversions. Google Ads Help. https://support.google.com/google-ads/answer/9888656

Google. (n.d.). Import offline conversions with GCLID. Google Ads Help. https://support.google.com/google-ads/answer/7012522

Gordon, B. R., Zettelmeyer, F., Bhargava, N., & Chapsky, D. (2019). A comparison of approaches to advertising measurement: Evidence from big field experiments at Facebook. Marketing Science, 38(2), 193-225. https://doi.org/10.1287/mksc.2018.1135

Meta for Developers. (n.d.). Conversions API. https://developers.facebook.com/docs/marketing-api/conversions-api/

Meta for Developers. (n.d.). Handling duplicate pixel and server events. https://developers.facebook.com/docs/marketing-api/conversions-api/deduplicate-pixel-and-server-events/

Meta for Developers. (n.d.). fbp and fbc parameters. https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc

TikTok for Business. (n.d.). About Events API. https://ads.tiktok.com/help/article/events-api

About the author: Baptiste Noel, co-founder of Metrikia. MSc in Clinical Neuroscience and MSc in High Performance.

Ready to measure your true advertising ROI?

Connect your ad accounts and CRM in 5 minutes.