You’ve read the arguments for why server-side tracking matters. Browser restrictions are eating your data, ad blockers are stripping your pixels, and every major ad platform now expects server-to-server signals. The question now is how to implement it.
This guide covers the full GTM Server-Side implementation: how the architecture works, how to deploy it on Cloud Run, and how to configure the three integrations most setups need (GA4, Meta CAPI, Google Ads).
How data flows through a server-side container
Client-side GTM puts your tracking tags directly in the browser. GTM Server-Side adds an intermediary: a server you control that sits between the browser and third-party endpoints.
Here’s how it works in practice:
- The browser loads your GTM web container as usual
- Instead of sending hits directly to Google, Meta, or other vendors, the web container sends HTTP requests to your server container URL (e.g.,
gtm.yourdomain.com) - The server container receives these requests, processes them, and forwards data to vendor endpoints
- The server sends an HTTP response back to the browser, which can include
Set-Cookieheaders for first-party cookies
This intermediary step is what makes everything else possible. Your server controls what data goes where, can enrich or strip information before forwarding, and sets cookies as a genuine first-party server rather than a third-party script.
A single incoming request can trigger multiple outgoing requests to different vendors. One GA4 hit from the browser can simultaneously forward data to GA4 servers, Meta’s Conversions API, Google Ads, and TikTok’s Events API. This multiplexing is one of the core architectural benefits.
The four building blocks
GTM Server-Side uses four component types, similar in concept to web GTM but with important differences.
Clients
Clients are unique to server-side GTM. They act as gatekeepers that listen for incoming HTTP requests on specific paths. The GA4 Client, pre-installed by default, listens on the /g/collect path for GA4 Measurement Protocol requests.
When a Client claims a request, it parses the raw HTTP data into a standardized Event Data object that the rest of the container works with. Clients operate on a priority order: the first Client to recognize and claim a request becomes active. Community templates like Stape’s Data Client provide vendor-agnostic alternatives.
Tags
Tags in server-side GTM receive parsed event data and compile outgoing HTTP requests to vendor endpoints. Built-in tags cover GA4, Google Ads Conversion Tracking, Google Ads Remarketing, and a generic HTTP Request tag. The Community Template Gallery provides tags for Meta CAPI, TikTok Events API, LinkedIn CAPI, Snapchat, Pinterest, and more.
Triggers
Triggers work similarly to web GTM but with different event types. The Custom trigger, which fires when “a request was sent to the GTM server container,” is the most commonly used. One critical detail: the Client Name condition is case-sensitive. If you named your client “ga4” but the trigger checks for “GA4,” nothing fires. This causes more debugging headaches than you’d expect.
Variables and Transformations
Variables include Event Data (retrieves values using key paths like page_location or user_data.email_address), Query Parameter, Cookie, Request Header, and Constant types.
Transformations are a newer resource type that sits between Clients and Tags. They let you include, exclude, or modify parameters in the event data before tags access it. Useful for enriching data from external sources or stripping PII before forwarding to specific vendors.
Prerequisites and custom domain configuration
Before deploying, you need:
- A Google Cloud account with billing enabled
- A custom subdomain pointed at your server container
The custom domain is non-negotiable. Without it, cookies are set in a third-party context and you get none of the first-party benefits that make server-side tracking worthwhile.
Two approaches exist:
Subdomain approach (most common): Create a CNAME record pointing gtm.yourdomain.com to your Cloud Run service URL. Google handles SSL automatically via managed certificates, though provisioning can take up to 24 hours.
Same-origin approach (advanced): Use a CDN or Cloud Load Balancer with path-based routing (e.g., /metrics/* → Cloud Run). This gives the strongest first-party cookie treatment since the server shares the exact same origin as your website.
Deploying to Cloud Run
Google Cloud Run replaced App Engine as the recommended deployment platform in October 2023. It runs the official tagging server Docker image as a fully managed serverless container.
Automatic vs. manual provisioning
The automatic provisioning flow inside GTM creates two Cloud Run services for you: a tagging server (handles production traffic) and a preview server (dedicated to GTM debug mode). The downside is that automatic provisioning always deploys to US Central (Iowa).
Manual provisioning is recommended for production. It lets you select a region closer to your users for lower latency and, if you’re serving EU traffic, keeps data within European infrastructure for GDPR compliance.
Production configuration
Google recommends these settings for the tagging server:
Min instances: 2 (eliminates cold starts)Max instances: 10 (handles ~350 req/s)CPU: 1 vCPU, always allocatedMemory: 512 MiBRequest timeout: 60 secondsThe --no-cpu-throttling flag (CPU always allocated) is very important. Without it, Cloud Run throttles CPU between requests, which causes inconsistent performance for a server that needs to process and forward data quickly.
The preview server should run exactly 1 instance.
Verify your deployment by hitting https://gtm.yourdomain.com/healthy, which should return “OK.”
Multi-region setup
For global traffic (see also GCP platform architecture), deploy Cloud Run services across regions (e.g., europe-west1, us-east1), create Serverless Network Endpoint Groups for each, and place them behind a single External Application Load Balancer with a global anycast IP. The load balancer adds about $18/month but gives you Cloud Armor DDoS protection and geographic routing.
Configuring GA4
GA4 is the simplest integration because most of the infrastructure exists out of the box.
In the web container: Set the server_container_url field on your Google Tag configuration to your custom domain (e.g., https://gtm.yourdomain.com). This redirects all GA4 hits through your server instead of directly to Google.
In the server container: The pre-installed GA4 Client requires no modification. Create a single GA4 tag, set the trigger to fire when Client Name equals GA4, and it forwards all events to GA4 servers. That’s it.
Enable “Server Managed Client ID” on the GA4 Client and it sets the FPID cookie (First Party Identifier) via an HTTP Set-Cookie header, flagged as HttpOnly. This server-set cookie bypasses Safari ITP’s 7-day cap on JavaScript cookies, which is one of the primary reasons to run server-side tracking at all.
Configuring Meta Conversions API
Meta CAPI is where server-side tracking gets more involved. You’ll need a Meta Pixel ID and an API Access Token (use system user tokens, which don’t expire when team members leave the Business Manager).
Event deduplication
If you’re running both the Meta Pixel (browser) and CAPI (server), which Meta recommends, you need deduplication. Without it, Meta counts every conversion twice.
Both sources must share the same event_id for each event. To wire this up:
- Import the Unique Event ID variable template in your web container
- Add the generated ID as an event parameter in your GA4 tags (e.g.,
event_id) - In the server container, configure the Meta CAPI tag to read this ID from the Event Data
- Meta matches events within a 48-hour window
When deduplication works correctly, Events Manager shows conversions as “1 event from 2 sources.”
User data mapping
Your Event Match Quality (EMQ) score determines how well Meta can attribute conversions. Target a score of 6.0 or higher. Improve it by mapping user data fields in the CAPI tag:
- Hashed email address (SHA-256)
- Hashed phone number
- First and last name
- City, state, zip code, country
Also make sure the _fbp and _fbc cookies are being forwarded from the browser to the server container. The _fbc cookie captures the fbclid click identifier, which is essential for click-through attribution.
Configuring Google Ads
Google Ads requires two server-side tags working together.
Conversion Linker tag: Fires on every page view. It manages the FPGCLAW cookie (a first-party cookie storing the gclid click identifier) and sends landing page beacons to Google. Without this tag, Google Ads can’t attribute conversions back to ad clicks.
Conversion Tracking tag: Fires on specific conversion events (purchase, lead submission, etc.). Configure it with the Conversion ID and Conversion Label from your Google Ads account.
Enhanced Conversions
For better attribution when cookies fail, set up Enhanced Conversions:
- In the web container, create a User-Provided Data variable mapping form fields (email, phone, name, address)
- Add the
user_dataparameter to both your GA4 Configuration and Event tags - Google hashes this data with SHA-256 and matches it against signed-in Google accounts
Validation takes about 48 hours. Check the Diagnostics tab in Google Ads for “Recording enhanced conversions.” Advertisers running Enhanced Conversions typically see a 5-25% uplift in reported conversions.
First-party cookies and the ITP bypass
Server-set first-party cookies recover lost data from Safari and iOS users.
Safari ITP caps JavaScript-set cookies at 7 days (24 hours if the user arrived via a tracked link with gclid or fbclid parameters). When the GA4 Client has “Server Managed Client ID” enabled, it sets the FPID cookie via the HTTP Set-Cookie response header as HttpOnly. Safari treats HTTP-set cookies from a same-domain server as legitimate first-party cookies with their full intended lifetime.
The IP address caveat
Since Safari 16.4, ITP also checks IP addresses. If gtm.yourdomain.com resolves to a significantly different IP range than yourdomain.com, Safari still caps cookies to 7 days. A standard Cloud Run deployment with CNAME setup hits this problem because Cloud Run’s IP addresses differ from your hosting provider’s.
Three approaches fix this:
First Party Mode (FPM): Google’s own solution, still in beta as of early 2026, routes traffic so the server shares the same IP context as your site.
Reverse proxy: Place both your website and the tagging server behind the same infrastructure (e.g., both behind a Cloudflare proxy) so they share an IP range.
Stape Cookie Keeper: A managed solution that periodically refreshes cookies before Safari would expire them, extending lifetimes to 90 days or 13 months.
Sites with high mobile or younger demographics typically recover 25-35% of lost signals with proper first-party cookie configuration. B2B desktop-heavy sites see a smaller but still meaningful 10-15% recovery.
What it actually costs
Self-hosted Cloud Run
A single always-on Cloud Run instance costs about $49/month. With Google’s recommended minimum of 2 instances, you’re looking at roughly $90/month as a baseline.
| Traffic level | Daily requests | Instances (min/max) | Monthly cost |
|---|---|---|---|
| Small | 10K-100K | 1-2 / 3 | $45-$135 |
| Medium | 100K-1M | 2 / 5-6 | $90-$270 |
| Large | 1M-10M | 3 / 10+ | $135-$450+ |
The hidden cost trap is Cloud Logging. Default settings log every request to the server container. At $0.50 per GiB ingested, this adds $100-$220/month for moderate traffic. Disable detailed request logging immediately after deployment. You’ll save more on logging than you spend on compute.
Managed alternatives
Stape.io is often cheaper than self-hosting due to bulk Cloud Run purchasing (see hosting alternatives compared). Their Pro plan at $20/month includes 500K requests, Cookie Keeper, support, and monitoring. They count only incoming requests (not outgoing forwards to GA4, Meta, etc.), which makes the pricing more generous than it appears.
Addingwell (recently acquired by Didomi) positions as a premium option starting at around €90/month, with 99.99% uptime SLA and real-time tag health monitoring.
Cloudflare Zaraz takes a different approach entirely, processing tracking at Cloudflare’s CDN edge. It’s free for up to 1 million events monthly with near-zero performance impact, though it’s not GTM Server-Side specifically.
Total cost of ownership
Don’t forget the human cost. Initial setup runs 10-40 hours depending on complexity. Ongoing maintenance needs 5-20 hours monthly for monitoring, tag updates, and debugging. If you’re hiring an agency, implementation projects run $2K-$15K with monthly retainers of $1.5K-$5K.
Mistakes that break your setup
After working with GTM Server-Side implementations, these are the failures I see most often:
-
No custom domain configured. Without it, cookies are third-party and you lose the primary benefit.
-
Consent signals not reaching the server container. Server-side GTM doesn’t have built-in Consent Mode. Consent must be configured in the web container first (see Consent Mode v2 implementation), with signals encoded in
gcsandgcdHTTP parameters. Google tags in the server read these automatically, but non-Google tags (Meta, TikTok) need manual consent-based trigger configuration. -
Case-sensitive Client Name in triggers. If your Client is named “GA4” and your trigger condition checks for “ga4,” the trigger never fires. No error, just silent failure.
-
Missing Meta event deduplication. Running Pixel and CAPI without shared
event_idvalues doubles your conversion counts. Meta won’t flag this automatically. -
Cloud Logging left at default settings. The logging costs can exceed your compute costs within days.
-
CPU throttling enabled on Cloud Run. Without the “CPU always allocated” setting, the container throttles between requests, causing timeouts and data loss.
-
Preview server scaled beyond 1 instance. The preview server must run exactly 1 instance. Multiple instances cause debug mode to behave unpredictably.
-
FPID cookies undermined by IP mismatch. Your CNAME setup looks correct, but Safari 16.4+ still caps cookies because the IP ranges don’t match. Test with Safari’s Web Inspector to verify cookie lifetimes.
-
Region-specific consent not configured. Denying consent globally loses non-EEA data. Granting globally violates GDPR. Use region-specific consent defaults.
-
Duplicate tag implementations. Google tags exist both in the site’s HTML header and in GTM, causing consent signals to be missed on the hardcoded tags.
Where to go from here
A working GTM Server-Side setup with GA4, Meta CAPI, and Google Ads covers the core needs for most organizations. Once the foundation is stable, you can layer on additional vendor tags (TikTok, LinkedIn, Pinterest all have Community Template Gallery tags), implement data enrichment via Transformations, and connect server-side events to your GA4 BigQuery export for deeper analysis.
The architecture is an investment in data durability. Browser restrictions will keep tightening, ad platforms will keep shifting toward server-side signals, and consent requirements will keep expanding. A properly configured server container puts you in control of all three.