GA4 server-side tracking: how it works, what breaks, and how to set it up
29 Oct 2026 · 6 min read · Neill Brookman
GA4 server-side tracking means your servers, not the visitor’s browser, send event data to Google Analytics 4. Done well, it fixes the three things that quietly erode GA4 numbers: ad blockers that stop the Google tag from loading, Safari’s 7-day limit on cookies set by JavaScript, and the weight of the tag itself on every page.
Done badly, it produces a GA4 property full of one-page sessions, "(not set)" locations and users counted twice. This guide covers the three ways teams send GA4 data server-side, what each one gets right and wrong, and the checklist that decides whether your reports still make sense afterwards.
Three ways to send GA4 data server-side
### 1. Measurement Protocol from your own backend
GA4's Measurement Protocol is an HTTP API. Your server POSTs JSON to Google with your measurement ID, an API secret and the visitor’s client_id:
POST https://www.google-analytics.com/mp/collect?measurement_id=G-XXXXXXXXXX&api_secret=YOUR_SECRET{ "client_id": "1234567890.1713355200", "events": [{ "name": "purchase", "params": { "session_id": "1713355200", "engagement_time_msec": 100, "transaction_id": "ord_A9F3B2", "currency": "GBP", "value": 142.50 } }] } ```
It is the right tool for events the browser never sees: a subscription renewal, a refund, an offline sale. It is the wrong tool for replacing the Google tag on its own, for three reasons:
- GA4 reserves the events that build sessions.
session_start,first_visitanduser_engagementare rejected by the Measurement Protocol, because the Google tag normally creates them. Send page views without them and GA4 cannot assemble proper sessions or engagement metrics. - You inherit the `client_id` problem. The events only join up with a visitor’s browsing if you send the same
client_idthe browser has. If that ID still lives in a JavaScript cookie, Safari deletes it after 7 days and the returning visitor becomes a new user. - Location and device are blank unless you send them. GA4 derives country and device from the request it receives. A request from your server describes your server, so the visitor’s IP address and user agent have to be forwarded explicitly.
### 2. A server-side tag manager container
The second approach keeps the Google tag in the browser but points it at a container running on your own subdomain, which forwards the hits to GA4. Because the hits now go to your domain, the container can set cookies from the server and strip or enrich data before it reaches Google.
The trade-off is that the browser half never goes away. The Google tag still loads on every page, so the page weight stays and ad blockers that recognise the script or its requests can still stop it. You also run, scale and monitor the container infrastructure, and each vendor beyond GA4 needs its own configuration inside it.
### 3. First-party collection with no Google JavaScript
The third approach removes the Google tag entirely. One first-party collector on your own domain sends events to your own collection endpoint, and the platform behind that endpoint delivers them to GA4 and every other destination, server to server. This is how GA4 server-side tracking works in Datafly Signal:
- The server generates the GA4
client_idin the format GA4 expects and stores it in a first-party cookie set by your own server, so it lasts up to 400 days. - Sessions are assigned on your collection domain. Datafly Signal emits
session_startandfirst_visitonce per session, withsession_idandsession_numberon every event and GA4's 30-minute inactivity window by default. - Page views, engagement and session events go to GA4 in the same format the Google tag uses, so GA4 accepts the reserved names. Conversions go through the Measurement Protocol with Enhanced Conversions data, hashed with SHA-256 inside your own infrastructure.
- The visitor’s IP address and user agent are forwarded, so location and device reports populate as they would with the Google tag.
- Scroll depth, outbound clicks, file downloads, video engagement and form submissions are collected first-party and sent under GA4's standard event names, so they land in the same reports as Enhanced Measurement.
The checklist: what has to be right
Whichever approach you choose, these decide whether GA4 still tells the truth.
A stable `client_id`. Every event for a visitor must carry the same client_id, from the first visit to the conversion weeks later. Check returning-user rates for Safari visitors before and after: if they drop, the ID is not surviving.
Real sessions. Events need session_id and engagement_time_msec, and something has to emit session_start and first_visit. Without them, GA4 shows inflated users, short sessions and engagement rates that look broken.
Location and device. Forward the visitor’s IP address and user agent with every event. A spike in "(not set)" countries, or every visitor appearing in the city where your servers are, means this is missing.
Consent. GA4's server-side consent signals are ad_user_data and ad_personalization. The Measurement Protocol does not honour analytics_storage or ad_storage, so consent has to be enforced before the event is sent, not described inside it. Datafly Signal evaluates consent per event and keeps an audit trail of each decision; see Consent Mode v2 server-side.
No double counting. GA4 does not deduplicate events sent by both the Google tag and your server, apart from purchases that share a transaction_id. Validate against a separate GA4 property or data stream, then switch the browser tag off one event at a time as each server-side event is proven.
Clean traffic. Bots and scrapers inflate GA4 users and distort conversion rates. Filtering them on the server before delivery keeps them out of GA4 and every other destination; see server-side bot filtering.
The Safari detail most guides miss
Moving cookies to the server is what lets a GA4 client_id outlive Safari’s 7-day limit, but only if the collection endpoint is served from the same place as your website. Since Safari 16.4, a cookie is still capped at 7 days when the server that sets it does not share the first half of its IP address with the server that delivered the page. That rule exists to catch tracking subdomains pointed at third-party infrastructure.
The practical rule: serve your collection subdomain (for example signal.yourdomain.com) from the same CDN or edge as www. Get this right and server-set cookies last; get it wrong and you are back to 7 days. The Safari ITP page covers the cookie side in more depth.
Setting up GA4 server-side tracking with Datafly Signal
1. In GA4, create or choose a property and web data stream, note the Measurement ID (G-XXXXXXXXXX), and create a Measurement Protocol API secret under the data stream settings.
2. In Datafly Signal, add the Google Analytics 4 integration to your pipeline, enter the Measurement ID and API secret, and choose a preset: Standard for page views and sessions, or Retail, Travel, B2B / SaaS or Automotive for conversions too.
3. On your site, add the Datafly.js collector directly to the page, served from your collection subdomain. Do not load it inside a tag manager: if the tag manager is blocked, the collector would be too.
4. Validate by pointing Datafly Signal at a separate GA4 property and comparing page views, users and conversions against your existing property until they line up.
5. Cut over one event at a time, switching off the Google tag for each event as the server-side version takes over. If your site already pushes events to a dataLayer, the collector can forward them during the transition, so you can go live before re-instrumenting everything.
The full configuration reference is in the GA4 integration docs.
Which approach fits
If you only need a handful of backend events in GA4, the Measurement Protocol from your own server is enough. If GA4 is your main destination and you are happy to keep the Google tag in the page, a server-side container gets you first-party cookies.
If GA4 is one of many destinations, the case for a first-party platform is everything around the delivery: one collector instead of a tag per vendor, identity that lasts 400 days across every destination, consent enforced per event with an audit trail, bots removed before any vendor sees them, and delivery that is queued and retried rather than lost when a vendor API is slow. Datafly Signal is single-tenant and can run in your own cloud, so event data stays in infrastructure you control.
See GA4 server-side tracking in Datafly Signal, or request a demo to see it running against your own GA4 property.
Want more posts like this?
No spam newsletter, no drip campaigns. If you want technical posts on server-side data infrastructure, bookmark /blog or follow the RSS feed.