1
10 Comments

Your affiliate tracking loses 30% of EU sales

If your affiliate or referral programme runs on browser cookies, you're probably not paying partners for a chunk of the sales they actually drove. In the EU, industry estimates put the miss as high as 30%.

Here's where it goes.

Safari deletes the cookie. Safari's tracking prevention caps or clears client-side cookies within a day or two. A visitor clicks a partner link on Monday, buys on Thursday, and the cookie's already gone. No attribution, no commission.

Ad blockers never let the script load. A big share of technical audiences run uBlock or similar. Most trackers ship a third-party script those lists block outright, so the click is invisible from the start.

Consent banners lose the rest. Under the ePrivacy directive a tracking cookie needs consent before it's set. Every visitor who ignores or rejects the banner is a referral you can't credit. And you're legally required to ask.

The uncomfortable part: your dashboard doesn't show any of this. It reports the conversions it did catch, so the programme looks healthy while a third of it leaks.

Move attribution to the server. Instead of a cookie in the browser, you pass a click ID through your own domain and match it on your backend when the sale closes. Nothing for a blocker to catch, nothing for Safari to clear, and a first-party ID tied to a purchase sits on much firmer consent footing than a marketing cookie.

It's more work than dropping in a script, and you need control of your checkout (Stripe makes this easy). But it's the difference between paying partners for real numbers and paying them for whatever survived three layers of loss.

We hit all of this building a tracker for EU SaaS, which is why we went server-side from the start. But you don't need our tool for it, you need to stop trusting the cookie.

If you run an affiliate or referral programme: have you ever checked how much of your attribution survives Safari and ad blockers? Curious whether anyone's actually measured their own leak.

on July 16, 2026
  1. 1

    The leak is real, but I'd be careful treating server-side click IDs as consent-free by default; the compliance question depends on purpose and jurisdiction, not only where the ID lives. A useful test is to run browser and server attribution in parallel for 30 days, then publish the delta by Safari, blocker presence, and conversion lag. That turns the 'up to 30%' claim into a number partners can trust.

    1. 1

      You're right, and I should've been sharper about it in the post. Moving the ID server-side doesn't make consent evaporate; what changes is the basis you rely on. A cookie triggers ePrivacy because it's storage on the device, full stop. A first-party ID you generate to fulfil a purchase you're already processing can sit on contract or legitimate interest instead. That's firmer footing, but it's a purpose-and-DPIA argument, not a "it lives on the server so it's free" one, and your jurisdiction point stands.

      On the parallel run: that's the honest way to turn "up to 30%" into a number anyone should trust, and I'll say plainly that 30% is an industry estimate, not something I've measured on a live programme yet. If I ran it, the cut I'd watch is conversion lag — Safari clears the client cookie in a day or two, so the gap should widen with every day between click and sale, which is exactly where B2B trials sit. Worth a follow-up post once there's real data behind it.

      1. 1

        That distinction is much stronger, especially naming 30% as an estimate. For the parallel run, I'd publish the denominator too: attributed conversions by browser isn't enough unless you also know total checkout starts or purchases for each segment. Otherwise Safari can look worse simply because its traffic mix has longer purchase cycles.

        1. 1

          Agreed, without the denominator you're measuring traffic mix as much as attribution loss. The cleaner design that sidesteps it: stop comparing Safari's attributed conversions against Chrome's, and measure the delta on the same set of known purchases instead. Fire both the cookie method and the server-side match for every checkout, then count how many real sales the cookie missed that the server side caught. Same denominator by construction, so a longer Safari purchase cycle can't make it look worse, it either recovered that specific sale or it didn't. Cross-segment rates are still worth publishing, but as context, not the headline.

          1. 1

            Same-denominator matching fixes the comparison. I'd publish three counts: both methods matched, server-only matched, and cookie-only matched; the server-only share is the actual recovery claim.

            1. 1

              Those are the three I'd publish, and the one I'd watch hardest is cookie-only, because it should trend to zero. Server-side is meant to be a superset of the cookie, so a sale the cookie caught but the server missed isn't traffic mix or Safari, it's a hole in your own click-ID handoff, a checkout path where the ID didn't propagate. That bucket doubles as QA on the implementation: a clean run is a healthy "both", a meaningful "server-only", and "cookie-only" near zero. If it isn't near zero, you fix that before you trust the recovery number.

              1. 1

                That turns cookie-only into a release gate, not a reporting metric. I would break it down by checkout path and require it to stay below a small threshold before publishing the recovery claim; otherwise the headline is measuring an incomplete server handoff.

                1. 1

                  Release gate is the right label. The one thing I'd change is gating on a bare threshold: a flat "under 2%" can hide a single broken path that happens to sit beneath it. These failures cluster rather than spread: it's almost never uniform loss, it's one flow where the ID doesn't survive, usually an off-domain hop like a hosted checkout or a payment redirect. So I'd gate on "every cookie-only sale has a named cause", not a number. Zero is the target, but a handful that all trace to one known race is shippable; a handful across paths you can't explain isn't, even under the same percentage.

                  1. 1

                    Agreed. The gate should be two-dimensional: zero unexplained cookie-only sales, and every explained one attached to a path, owner, reproduction, and expiry date. A known hosted-checkout race can ship behind a flag; an unexplained single sale cannot, because you do not know how large a population it represents.

                    1. 1

                      The unknown-population point is the one that makes it non-negotiable: a single unexplained cookie-only sale isn't one lost sale, it's a path you haven't sized, and it could be 1 or 1,000. That's the whole case for the gate in one line. Owner, reproduction, and expiry per exception is what keeps it from rotting into a rubber stamp. This basically became the methodology for the follow-up, so thanks for pushing on it. When I run it for real I'll publish the three counts with the denominator, and tag you.