Skip to content

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.

When your sGTM server runs at data.yoursite.com:

  • Cookies are first-party. The browser treats cookies set at data.yoursite.com as belonging to yoursite.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 to data.yoursite.com does 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.

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.

  1. Blend with your existing subdomains. If your site uses app.yoursite.com and cdn.yoursite.com, choose something that fits that pattern. A subdomain that looks like your other infrastructure is invisible to filter lists.
  2. Avoid anything tracking-related. Filter lists pattern-match on keywords. Any subdomain containing gtm, sgtm, tag, track, analytics, pixel, stats, collect, or beacon is a target — today or in the near future.
  3. Don’t use your root domain. Never point your bare yoursite.com at sGTM — you will overwrite your website.
  4. 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.
  5. 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.

These blend well with typical web infrastructure and are not on common filter lists:

SubdomainWhy it works
web.yoursite.comGeneric, could be anything
data.yoursite.comMany legitimate uses (data APIs, data services)
load.yoursite.comSounds like a CDN or load balancer
edge.yoursite.comSounds like an edge computing service
io.yoursite.comGeneric, tech-sounding
hub.yoursite.comCould be any internal service
pipe.yoursite.comSounds 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.

SubdomainWhy to avoid
gtm.yoursite.comDirectly references Google Tag Manager
sgtm.yoursite.comKnown sGTM convention, increasingly blocked
tagging.yoursite.comObvious tracking purpose
analytics.yoursite.comOn nearly every filter list
data.yoursite.comIncreasingly recognized as an sGTM convention
collection.yoursite.comSame problem as collect
metrics.yoursite.comBorderline — on some lists, consider alternatives first
tracker.yoursite.comObvious purpose
pixel.yoursite.comCommon block list pattern
stats.yoursite.comOn several filter lists
tag.yoursite.comPattern-matched by lists
beacon.yoursite.comPattern-matched by lists
sst.yoursite.comKnown Stape convention, increasingly recognized

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.

The DNS configuration depends on your hosting provider.

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.com

Get the exact record by going to: Cloud Run → your service → Manage Custom DomainsAdd Mapping.

Stape provides a CNAME target in their dashboard under DomainsAdd Domain:

data.yoursite.com CNAME cname.stape.io

Point to your ALB’s DNS name:

data.yoursite.com CNAME sgtm-alb-xxxxxxxxx.region.elb.amazonaws.com

Or 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.com

Point directly to your server’s IP:

data.yoursite.com A YOUR_SERVER_IP
  1. Log in to Cloudflare → select your domain → DNSRecords

  2. Click Add Record:

    • Type: CNAME
    • Name: collect (Cloudflare appends .yoursite.com automatically)
    • Target: ghs.googlehosted.com (or your provider’s target)
    • Proxy status: DNS only (grey cloud) — this is critical
  3. Save the record

  4. Verify:

    Terminal window
    dig data.yoursite.com
    # Should return CNAME pointing to your provider's target

DNS changes propagate at the speed of your TTL setting — typically 5 minutes to 24 hours. Verify propagation before proceeding:

Terminal window
# Check from multiple locations
dig 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:

Terminal window
dig data.yoursite.com @8.8.8.8 # Google
dig data.yoursite.com @1.1.1.1 # Cloudflare
dig data.yoursite.com @9.9.9.9 # Quad9

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 RunManage 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:

Terminal window
certbot certonly --standalone -d data.yoursite.com
# Certbot auto-renewal handles certificate refresh every 90 days

Once DNS has propagated and SSL is provisioned, verify:

Terminal window
# Health check
curl -v https://data.yoursite.com/healthz
# Expected: HTTP 200, body: ok
# Check SSL certificate
curl -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 configured

With the endpoint verified, update your client-side GA4 tag:

  1. Open your client-side GTM container
  2. Find your GA4 Configuration tag (or Google Tag)
  3. Set Tagging Server URL to:
    https://data.yoursite.com
  4. Preview the change — network tab should show requests going to data.yoursite.com/g/collect
  5. Publish when verified

After updating the client-side tag, confirm first-party behavior in the browser:

  1. Open DevTools → ApplicationCookiesyoursite.com
  2. Trigger a pageview
  3. You should see a _ga cookie (and FPID if enabled) with:
    • Domain: .yoursite.com
    • Expires: full duration (400 days, not the 7-day ITP cap)
    • SameSite: None or Lax (depending on sGTM configuration)

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.

If you run sGTM across multiple domains, you have two options:

Separate subdomain per domain (recommended):

collect.site-a.com → sGTM server
collect.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.

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.

  1. Open your server-side GTM container and navigate to the Web Container Client (or GA4 client, depending on your version).

  2. Add your web container ID (GTM-XXXXXXX) to the Container ID Allowlist.

  3. 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.com or google-analytics.com.

  4. Enable “Compress HTTP Response” if you are on Cloud Run (App Engine handles this automatically).

  5. 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>
  6. If you use gtag.js directly (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>
  • No requests to Google domains. The browser never contacts googletagmanager.com or google-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.

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.