
Safari ITP case study: cost per lead down 20% with server-side tracking
In this Safari ITP case study, a US retailer's returning buyers were filed under Direct because Safari cut the life of script-set cookies from 30 days to 7, and to 24 hours after a paid search click. Server-set cookies, server-side tracking and Consent Mode v2 put those leads back under their real sources, and cost per lead fell 20% after the server-side setup.
- Cookie written by
Browser script→The server- Returning buyer
Direct→Original source- Offer
- Tracking Build
Script-set vs server-set: the Safari ITP cookie clock
Pick how a buyer first arrived and when they came back. The clock shows whether the cookie that identifies their browser is still alive at the return, and where GA4 files the visit: with the script-set cookie this retailer started with, and with the server-set cookie it moved to.
Cookie expired after 24 hours. GA4 meets an unknown browser, issues a new client ID and files the return visit, and its lead, under Direct. The stored click ID is gone too, so Google Ads cannot tie the lead to the ad.
The server set this cookie, and the cap on script-set cookies does not shorten it. GA4 sees the same browser and the lead keeps its Google Ads source.
Assumes the return visit carries no campaign tag of its own, such as a typed address or a bookmark. Day 30 marks the cookie life the site had before ITP shortened it.
Why an ad click gets only 24 hours
WebKit cuts script-set cookies to 24 hours when the visitor arrives from a domain it classifies as a tracker and the landing URL carries a query string or fragment. A Google Ads click lands with gclid in the URL, and clicks from other ad networks that decorate their links get the same treatment.
When a server-set cookie gets capped anyway
Since Safari 16.4, WebKit also caps cookies from a server response at 7 days when that server's IP address does not match the website's own. That catches tagging subdomains pointed at a third-party host. A tagging server that shares the site's IP range keeps the expiry it sets.
Documented WebKit behavior. The clock models platform rules and shows no client data.
Why did logged-in buyers show up as Direct?
The retailer knew these buyers were coming back: they logged in and were identified by user ID. GA4 still filed their sessions under Direct, and most of them browsed in Safari. Missing and misattributed data was hurting a business that spends heavily on Google Ads, and it came to us asking for Consent Mode v2 and server-side tracking. Our analysis traced the Direct bucket to two causes.
- 1Safari ITP was shortening cookiesScript-set cookies expired after 7 days, or 24 hours after a paid search visit, and the original source expired with them.
- 2Ad blockers and privacy browsers were hiding visitsRequests to tracking domains never arrived, which fed the Direct bucket and widened the gap in the data.
Results: cost per lead down 20% after the server-side setup
−20%Leads that had been pushed into Direct now sit under their proper sources, Safari included. Traffic that ad blockers and privacy browsers had hidden is measured again, and modeled conversions show in GA4 and in Google Ads.
Offer: Tracking Build| Area | Before | After |
|---|---|---|
| Returning Safari users | Source lost, shown as Direct after login | Attributed to their real source |
| Cookie life | 7 days, or 24 hours for paid search | Server-set cookies that page scripts cannot edit |
| Ad blockers and privacy browsers | Much of that traffic missing | Recovered and measured through the server-side setup |
| Conversions in reports | Only what could be observed | Modeled conversions in GA4 and Google Ads |
| Cost per lead | The period before the server-side setup | −20% |
Five steps to a cookie that page scripts cannot touch
The build covered both things the retailer asked for, Consent Mode v2 and server-side tracking, and used the server to fix Safari. It ran as a Tracking Build in five parts.
// runs in the browser, inside the tag library document.cookie = "_ga=GA1.1.…; max-age=…; path=/"
Any cookie written through document.cookie gets Safari's 7-day ceiling, whatever expiry the script asks for.
HTTP/1.1 200 OK Set-Cookie: <id>=…; Max-Age=…; Path=/; Secure; HttpOnly
What escapes the 7-day cap is the Set-Cookie header from a server on the site’s own IP range. HttpOnly only stops page scripts from reading the cookie.
Both snippets are simplified to show where each cookie is written.
- 1
Consent Mode v2
Set up first, as the retailer asked. Each visitor's choice now reaches GA4 and Google Ads before any tag decides what to store. Our Consent Mode v2 setup page shows the wiring.
- 2
Server-side tracking
Tags send to a tagging server first. The same route measures visits that ad blockers and privacy browsers had been dropping. The server-side tracking page covers the architecture.
- 3
Server-set cookies
The Safari fix: browser identifiers written by the server, which client-side scripts cannot edit.
- 4
Behavior modeling
Switched on in GA4, with modeled conversions now visible in Google Ads as well, where the retailer spends heavily.
- 5
Attribution check
Leads that used to fall into Direct were confirmed under their proper sources, Safari leads included.
Before you blame Safari ITP for your Direct traffic
Four questions retail teams ask once they have seen the cookie clock, answered with what this case showed.
What is Safari ITP?
How does Safari ITP affect Google Ads conversions?
Does server-side tracking fix Safari ITP?
Can server-side tracking bypass cookie consent?
Check your own Safari split in GA4
Before anyone sets up a tagging server, compare how Safari and Chrome attribute the same site. One free-form exploration in GA4 shows whether you have this retailer's problem.
- Rows
BrowserNew / returning- Columns
Session default channel group- Values
SessionsKey events- Filter
Browser matches regex Safari|Chrome- Date range
Several weeks with paid traffic
- Safari's Direct share runs well above Chrome'sCookie expiry is the first suspect. That was the pattern here.
- Safari counts far more new users than ChromeExpired cookies turn returning buyers into new ones. The New / returning row shows it.
- Direct is high in every browserLook for missing UTM tags, or a redirect that strips gclid from the landing URL, before blaming Safari.
- Safari sits close to ChromeITP is probably not your main leak. Check whether tags wait for Consent Mode v2 and how much ad blockers remove.
Send us your Safari split
Paste the two Direct shares from the exploration, Safari and Chrome, with the site they came from. We reply within one business day with what is most likely filing your buyers under Direct, and what it would take to stop it.
- Two numbers are enough to start the conversation
- If the split points away from Safari, we say so
