Custom Domain Setup
The custom domain configuration is the single most important step in your sGTM setup. Without it, you have a working server with no first-party benefits. A custom subdomain on your own domain transforms your sGTM endpoint from a third-party tracking server (subject to browser restrictions) into a first-party data collection endpoint (trusted by browsers like your own API).
This guide covers domain selection, DNS configuration for major providers, SSL setup, and client-side connection.
Why the custom domain matters
Section titled “Why the custom domain matters”When your sGTM server runs at data.yoursite.com:
- Cookies are first-party. The browser treats cookies set at
data.yoursite.comas belonging toyoursite.com— the same origin as your main site. Safari’s ITP 7-day cookie cap applies only to JavaScript-set cookies classified as trackers. Server-set first-party cookies receive the full expiration you configure. - Ad blockers have a harder time. Most ad blockers match against lists of known tracking domains (
google-analytics.com,googletagmanager.com,connect.facebook.net). A request todata.yoursite.comdoes not match any tracking domain list. It looks like a first-party API call. - Browser privacy features apply rules appropriate for first-party context. Requests to your own domain are treated with the trust level your main site has, not the lower trust level for known third-party tracking scripts.
Without a custom domain, your sGTM server at *.a.run.app is recognizable as a Google-hosted endpoint and provides none of these benefits.
Step 1: Choose your subdomain
Section titled “Step 1: Choose your subdomain”The subdomain you pick determines whether ad blockers ignore your sGTM endpoint or flag it immediately. The goal: make it look like it belongs to your regular site infrastructure, not like a tracking endpoint.
Naming principles
Section titled “Naming principles”- Blend with your existing subdomains. If your site uses
app.yoursite.comandcdn.yoursite.com, choose something that fits that pattern. A subdomain that looks like your other infrastructure is invisible to filter lists. - Avoid anything tracking-related. Filter lists pattern-match on keywords. Any subdomain containing
gtm,sgtm,tag,track,analytics,pixel,stats,collect, orbeaconis a target — today or in the near future. - Don’t use your root domain. Never point your bare
yoursite.comat sGTM — you will overwrite your website. - One subdomain per domain. If you run multiple sites, each gets its own subdomain and container. Sharing a single sGTM container across unrelated domains causes debugging headaches and breaks cookie scoping.
- Route through the same CDN as your main site. If your main site uses Cloudflare, your sGTM subdomain should resolve through the same infrastructure. When the IP addresses match, browser heuristics and filter lists have a much harder time distinguishing your sGTM traffic from regular site traffic.
Recommended subdomains
Section titled “Recommended subdomains”These blend well with typical web infrastructure and are not on common filter lists:
| Subdomain | Why it works |
|---|---|
web.yoursite.com | Generic, could be anything |
data.yoursite.com | Many legitimate uses (data APIs, data services) |
load.yoursite.com | Sounds like a CDN or load balancer |
edge.yoursite.com | Sounds like an edge computing service |
io.yoursite.com | Generic, tech-sounding |
hub.yoursite.com | Could be any internal service |
pipe.yoursite.com | Sounds like a data pipeline |
Single-letter subdomains are also effective — m.yoursite.com, s.yoursite.com, t.yoursite.com — they are short, generic, and impossible to pattern-match meaningfully.
Subdomains to avoid
Section titled “Subdomains to avoid”| Subdomain | Why to avoid |
|---|---|
gtm.yoursite.com | Directly references Google Tag Manager |
sgtm.yoursite.com | Known sGTM convention, increasingly blocked |
tagging.yoursite.com | Obvious tracking purpose |
analytics.yoursite.com | On nearly every filter list |
data.yoursite.com | Increasingly recognized as an sGTM convention |
collection.yoursite.com | Same problem as collect |
metrics.yoursite.com | Borderline — on some lists, consider alternatives first |
tracker.yoursite.com | Obvious purpose |
pixel.yoursite.com | Common block list pattern |
stats.yoursite.com | On several filter lists |
tag.yoursite.com | Pattern-matched by lists |
beacon.yoursite.com | Pattern-matched by lists |
sst.yoursite.com | Known Stape convention, increasingly recognized |
The subfolder alternative
Section titled “The subfolder alternative”Instead of a subdomain, you can route sGTM traffic through a path on your main domain: yoursite.com/measure/. This is even more robust against ad blockers because it fully shares the same origin — there is no subdomain to detect. However, it requires a reverse proxy setup (Cloudflare Workers, nginx, etc.). See the same-origin proxy guide for full instructions.
Step 2: Configure DNS
Section titled “Step 2: Configure DNS”The DNS configuration depends on your hosting provider.
Cloud Run (GCP)
Section titled “Cloud Run (GCP)”GCP provides a domain mapping tool that handles both DNS verification and SSL. The result is typically a CNAME record:
data.yoursite.com CNAME ghs.googlehosted.comGet the exact record by going to: Cloud Run → your service → Manage Custom Domains → Add Mapping.
Stape provides a CNAME target in their dashboard under Domains → Add Domain:
data.yoursite.com CNAME cname.stape.ioAWS ALB
Section titled “AWS ALB”Point to your ALB’s DNS name:
data.yoursite.com CNAME sgtm-alb-xxxxxxxxx.region.elb.amazonaws.comOr use an A record via Route 53 Alias if you are managing DNS in Route 53:
data.yoursite.com ALIAS sgtm-alb-xxxxxxxxx.eu-west-1.elb.amazonaws.comSelf-hosted (VPS or other)
Section titled “Self-hosted (VPS or other)”Point directly to your server’s IP:
data.yoursite.com A YOUR_SERVER_IPDNS configuration by provider
Section titled “DNS configuration by provider”-
Log in to Cloudflare → select your domain → DNS → Records
-
Click Add Record:
- Type:
CNAME - Name:
collect(Cloudflare appends.yoursite.comautomatically) - Target:
ghs.googlehosted.com(or your provider’s target) - Proxy status: DNS only (grey cloud) — this is critical
- Type:
-
Save the record
-
Verify:
Terminal window dig data.yoursite.com# Should return CNAME pointing to your provider's target
-
AWS Console → Route 53 → Hosted zones → your domain
-
Create record:
- Record name:
collect - Record type:
CNAME - Value: your provider’s CNAME target (e.g.,
ghs.googlehosted.com) - TTL: 300
- Record name:
-
For AWS ALB targets, use Alias instead of CNAME:
- Record type:
A - Alias: Yes
- Route traffic to: Application and Classic Load Balancer
- Select your ALB
- Record type:
-
Save and verify propagation.
-
Namecheap dashboard → Domain List → Manage → Advanced DNS
-
Add New Record:
- Type:
CNAME Record - Host:
collect - Value: your provider’s CNAME target
- TTL: Automatic
- Type:
-
Save and wait for propagation.
Step 3: Verify DNS propagation
Section titled “Step 3: Verify DNS propagation”DNS changes propagate at the speed of your TTL setting — typically 5 minutes to 24 hours. Verify propagation before proceeding:
# Check from multiple locationsdig data.yoursite.com +short
# Or use online tools# https://dnschecker.org# https://toolbox.googleapps.com/apps/dig/You can also check directly from the command line against multiple DNS resolvers:
dig data.yoursite.com @8.8.8.8 # Googledig data.yoursite.com @1.1.1.1 # Cloudflaredig data.yoursite.com @9.9.9.9 # Quad9Step 4: SSL certificate
Section titled “Step 4: SSL certificate”SSL setup varies by hosting provider:
GCP Cloud Run: Google automatically provisions a managed SSL certificate when DNS resolves correctly. No action required. Certificate appears in Cloud Run → Manage Custom Domains when provisioning is complete (typically 5–30 minutes after DNS propagates).
Stape: Automatic provisioning, same as GCP.
AWS ALB: Use AWS Certificate Manager (ACM). Request a certificate for data.yoursite.com in ACM, validate ownership via DNS CNAME (ACM provides the record to create), then attach the validated certificate to your ALB HTTPS listener.
Self-hosted: Use Let’s Encrypt with Certbot:
certbot certonly --standalone -d data.yoursite.com# Certbot auto-renewal handles certificate refresh every 90 daysStep 5: Verify the endpoint
Section titled “Step 5: Verify the endpoint”Once DNS has propagated and SSL is provisioned, verify:
# Health checkcurl -v https://data.yoursite.com/healthz# Expected: HTTP 200, body: ok
# Check SSL certificatecurl -v https://data.yoursite.com/healthz 2>&1 | grep "SSL connection"# Should show: SSL connection using TLSv1.3
# Check cookies work (test cookie setting)curl -I https://data.yoursite.com/g/collect?v=2&tid=G-XXXXXXXX&...# Response headers should include Set-Cookie if configuredStep 6: Update client-side GTM
Section titled “Step 6: Update client-side GTM”With the endpoint verified, update your client-side GA4 tag:
- Open your client-side GTM container
- Find your GA4 Configuration tag (or Google Tag)
- Set Tagging Server URL to:
https://data.yoursite.com
- Preview the change — network tab should show requests going to
data.yoursite.com/g/collect - Publish when verified
Verifying first-party behavior
Section titled “Verifying first-party behavior”After updating the client-side tag, confirm first-party behavior in the browser:
- Open DevTools → Application → Cookies →
yoursite.com - Trigger a pageview
- You should see a
_gacookie (andFPIDif enabled) with:- Domain:
.yoursite.com - Expires: full duration (400 days, not the 7-day ITP cap)
- SameSite: None or Lax (depending on sGTM configuration)
- Domain:
If the cookie’s expiration is 7 days or less, the cookie is being set by client-side JavaScript rather than the server. Check that your sGTM server tag is processing requests and setting cookies via response headers.
Multi-domain setups
Section titled “Multi-domain setups”If you run sGTM across multiple domains, you have two options:
Separate subdomain per domain (recommended):
collect.site-a.com → sGTM servercollect.site-b.com → sGTM server (same server, different CNAME)Cookies are scoped correctly to each domain. Cross-domain tracking requires explicit session linking.
Single subdomain for all domains (not recommended for cookies):
Using one collect.example.com for multiple unrelated domains prevents first-party cookie benefits on site-b.com. Use this only if you intentionally share a tracking infrastructure across related domains and understand the cookie scoping implications.
Loading Google scripts through your server container
Section titled “Loading Google scripts through your server container”As of mid-2025, the Web Container Client in sGTM can serve Google’s script libraries (gtm.js, gtag.js) directly from your first-party domain. This means the GTM container snippet itself loads from data.yoursite.com instead of googletagmanager.com — a significant improvement for ad blocker resistance and page load control.
How it works
Section titled “How it works”The Web Container Client unifies the previously separate gtm.js and gtag.js clients into a single client that can serve all dependent Google scripts. When a browser requests https://data.yoursite.com/gtm.js?id=GTM-XXXXXXX, your sGTM server fetches the container from Google, and returns it as a first-party response.
Configuration
Section titled “Configuration”-
Open your server-side GTM container and navigate to the Web Container Client (or GA4 client, depending on your version).
-
Add your web container ID (
GTM-XXXXXXX) to the Container ID Allowlist. -
Enable “Automatically serve all dependent Google scripts”. This ensures that any Google Tags loaded through the web container also route through the server — no separate requests to
googletagmanager.comorgoogle-analytics.com. -
Enable “Compress HTTP Response” if you are on Cloud Run (App Engine handles this automatically).
-
Update your client-side GTM snippet to load from your server domain:
<!-- Load GTM from your first-party domain --><script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://data.yoursite.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-XXXXXXX');</script> -
If you use
gtag.jsdirectly (without GTM), update the script source:<script async src="https://data.yoursite.com/gtag/js?id=G-XXXXXXXX"></script><script>window.dataLayer = window.dataLayer || [];function gtag(){ dataLayer.push(arguments); }gtag('js', new Date());gtag('config', 'G-XXXXXXXX', {server_container_url: 'https://data.yoursite.com'});</script>
Benefits
Section titled “Benefits”- No requests to Google domains. The browser never contacts
googletagmanager.comorgoogle-analytics.com. Every request goes to your first-party domain. - Ad blocker resistance. Block lists target Google’s domains. Your domain is not on those lists.
- Single point of control. All script loading and data collection flows through your server, giving you one place to monitor, debug, and control.
Common mistakes
Section titled “Common mistakes”Proxying through Cloudflare. Orange cloud mode breaks cookie setting. Use grey cloud (DNS only) exclusively.
Choosing a subdomain that appears on filter lists. analytics.yoursite.com is blocked by uBlock Origin and others regardless of being first-party. Choose a subdomain that could plausibly be a generic API endpoint.
Not waiting for SSL provisioning. A domain mapped in Cloud Run but without a valid SSL certificate returns SSL errors to browsers. Wait for certificate provisioning to complete before switching GA4 traffic.
Forgetting to update the client-side GA4 tag. DNS configured, server running, SSL valid — but if your client-side GA4 tag still points at www.google-analytics.com, none of this matters. The client-side tag update is the final activation step.