Quick answer: GA4 server-side tracking sends Google Analytics 4 events through a server you control before they reach Google. The common setup keeps the Google tag in the browser but points it at a Google Tag Manager server container on your own subdomain. Your backend can also send events directly with the GA4 Measurement Protocol.
How GA4 server-side tracking works
By default, the Google tag in the browser sends each GA4 event straight to Google:
Browser -> google-analytics.com -> GA4
With server-side tracking, the Google tag sends the same request to a subdomain of your site instead. A Google Tag Manager server container behind that subdomain receives it, processes it, and forwards it to GA4:
Browser -> metrics.example.com -> GTM server container -> GA4
Inside the server container, the built-in Google Analytics client claims incoming GA4 requests and turns them into event data. A server-side Google Analytics: GA4 tag forwards that event data to your property. Between the two, you can inspect, change, or drop any parameter.
The browser still decides which events exist and what the page measures. The server decides where those events go and which fields they carry.
What changes when GA4 goes server-side
| Client-side GA4 | Server-side GA4 | |
|---|---|---|
| Collection endpoint | Google's domain | Your first-party subdomain |
| Blocked by privacy lists | Often | Less often |
| Client ID cookie | _ga, set with JavaScript | _ga, or a server-managed FPID cookie set in an HTTP response |
| Cookie lifetime in Safari | Capped at seven days | Standard HTTP cookie rules when served from your own infrastructure |
| Parameters Google receives | Everything the tag sends | Only what the server tag forwards |
| IP address | Sent to Google | You can drop or truncate it before forwarding |
| Other destinations | Separate browser tags | The same event can feed other server tags |
What does not change: your event names, triggers, and measurement plan; the consent choice collected by your consent management platform; and GA4's own processing, attribution, and thresholds once the data arrives.
Three ways to run GA4 server-side
1. Server-side Google Tag Manager
This is the most common route. The browser keeps the Google tag, and a server container on your domain forwards events to GA4 and any other destination. It suits teams that already run GTM and want page views and interactions to go through a first-party endpoint.
2. GA4 Measurement Protocol
Your backend sends events to GA4 over HTTP, with no browser involved:
POST https://www.google-analytics.com/mp/collect?measurement_id=G-XXXXXXX&api_secret=YOUR_SECRET
{
"client_id": "123456789.1700000000",
"events": [
{
"name": "purchase",
"params": {
"session_id": "1700000123",
"transaction_id": "T-10293",
"currency": "EUR",
"value": 129.9
}
}
]
}
Use it for events the browser never sees: completed orders confirmed by a payment provider, refunds, subscription renewals, and offline conversions. Create the API secret in GA4 under Admin > Data streams > your stream > Measurement Protocol API secrets.
Two rules keep these events useful. Send the client_id from the visitor's _ga cookie so GA4 ties the event to the right user, and send session_id so it joins a session instead of arriving unattributed. Test payloads against /debug/mp/collect first, because the production endpoint accepts malformed events without reporting an error.
3. A first-party data platform
A platform such as Hardal collects events once on your first-party endpoint, then forwards them to GA4 alongside Meta, TikTok, Google Ads, and your warehouse. You skip running the container and maintaining each vendor tag. See what server-side tracking is for how the approaches compare.
How to set up GA4 server-side tracking with server GTM
1. Create the server container
In Google Tag Manager, create a new container and choose Server as the target platform. GTM gives you a container config string for the deployment.
2. Deploy the container
Run the container on Google Cloud Run, another cloud, or a managed host. For production, run more than one instance so a single failure does not drop events. Server-side hosting is Hardal's managed option.
3. Map a first-party subdomain
Point a subdomain such as metrics.example.com at the container and serve it over HTTPS. Serve it from infrastructure your site controls where possible. Safari caps cookies from endpoints it identifies as third-party infrastructure behind a CNAME or a mismatched IP address. The Safari ITP guide explains the rules.
4. Configure the Google Analytics client
Open Clients in the server container. The Google Analytics client is there by default and claims requests on GA4 paths such as /g/collect. Under cookie settings, choose between the JavaScript-managed _ga cookie and a server-managed FPID cookie. The server-managed cookie is set in an HTTP response, which is what gives it a longer life in Safari.
5. Add the GA4 tag
Create a Google Analytics: GA4 tag in the server container. It inherits the measurement ID and parameters from the incoming request. Add a trigger where Client Name equals your Google Analytics client, so only GA4 requests fire it.
6. Point the web container at the server
In your web container, open the Google tag and add a configuration parameter:
server_container_url = https://metrics.example.com
If you are migrating a live property, do not change the production tag yet. Copy it, point the copy at a separate test property, and compare both. The GA4 dual-tagging guide covers that migration step by step.
7. Verify the full path
Open Preview mode in both containers and load your site in a private window. Check that:
- The Google tag fires in the web container.
- The browser's network tab shows the request going to your subdomain, not
google-analytics.com. - The server container's Preview shows the request claimed by the Google Analytics client.
- The GA4 tag fires once.
- The event appears in GA4 DebugView.
Repeat with consent denied. The server should still receive the request, and GA4 should get a cookieless ping, not a full event with identifiers. Cookieless GA4 with server GTM explains the consent side.
8. Publish
Publish the server container first, then the web container.
Common GA4 server-side problems
- Double page views. A
page_viewfrom the Google tag plus one from an event tag. Each property should get one page view per page load. - Events arrive without a session. Usually Measurement Protocol events sent without
session_id, or with aclient_idthat does not match the browser's cookie. - Consent ignored. The web container must pass the consent state with each request. The server cannot infer it.
- Requests still going to Google. The Google tag is missing
server_container_url, or another hard-coded gtag snippet on the page bypasses GTM. - Short-lived client IDs in Safari. The subdomain resolves to third-party infrastructure, or the client still uses the JavaScript-managed cookie.
- Duplicate purchases. The browser and the backend both send the same purchase to one property. Pick one source per event, or deduplicate on
transaction_id. - Rising hosting bills. Request volume drives the cost of a self-hosted container. See how to cut server-side tagging costs.
Run GA4 server-side with Hardal
Hardal gives you two ways to move GA4 server-side. Use Hardal's first-party endpoint to send events to GA4 through the Measurement Protocol and route the same events to unlimited destinations, with analytics included. Or run your own server GTM container on Hardal-managed hosting in the US, UK, EU, EMEA, or Asia.
Keep your current GA4 setup live while Hardal runs beside it. Compare the data, fix any gaps, and switch only when the server-side path is ready. Plans start at $249 per month for 5M events. See pricing or book a demo with the team.