How Do I Configure Cloudflare To Proxy Both My Website And My SGTM Domain?

How to use Cloudflare to proxy your server-side Google Tag Manager subdomain to cope with WebKit’s truncation of first-party cookie lifetime.

The question we’re going to be looking at today is inspired by our course, Server-side Tagging In Google Tag Manager.

How do I proxy my server-side GTM setup through Cloudflare, so that it would share the IP address range with my website?

The WebKit browser engine, running Safari and iOS/iPadOS browser apps, has a tracking prevention mechanism called CNAME Cloaking defense

When a website communicates with another site, the WebKit browser checks the DNS records of both sites. If the DNS records point to significantly different addresses (either canonical names or IP address subnets), WebKit restricts the lifetime of cookies set in the HTTP response from the second site to a maximum of 7 days.

This means that deploying a service like server-side Google Tag Manager in Google Cloud Platform, for example, will no longer guarantee an extended lifetime for first-party cookies set through the service.

In this article, I’ll share with you a workaround for how to help WebKit consider the website and the service to be first-party to each other.

Huge thanks to Vladyslav Iukhnovych for working with me on this one in the Simmer Community.

Video walkthrough

If you prefer this walkthrough in video format, you can check out the video below.

Don’t forget to subscribe to the Simmer YouTube channel for more content like this.

video
play-rounded-fill

When are server-set cookies restricted?

You can use the Online Dig tool to check the DNS records for any given domain.

For example, let’s say you are browsing a website like www.site.example. Let’s say you manage its DNS records through Cloudflare, because you want to make use of Cloudflare’s super fast edge caching capabilities to improve the performance of your website.

In this case, the DNS records of this domain would point to Cloudflare’s network, for example to something like 188.114.X.X.

On this site, you are running requests through server-side Google Tag Manager. One of the use cases for deploying server-side GTM is to rewrite the site’s first-party cookies through HTTP responses to ensure a longer lifetime for them. 

You’ve deployed server-side GTM in the Google Cloud Platform, and you’ve mapped the custom domain sst.site.example to GCP’s servers. Thus, the subdomain resolves to a bunch of IP addresses all within the 216.239.X.X subnet.

In this case, WebKit would actually consider sst.example.com to be “third-party” to site.example.com, even though they are subdomains of the same naked domain.

Why? Because the IP address subnets that cover the first half of the address (the first two octets) are different.

Any cookies you try to set in the HTTP response from sst.example.com would be restricted to a maximum lifetime of 7 days, even though technically they are first-party cookies.

Make the IP address subnets match

To force WebKit to grant longer expiration times for the cookies set in the HTTP response from sst.example.com, you have to somehow make site.example.com and sst.example.com both resolve to the same IP address subnet.

In this article, I’ll share with you how to do this using Cloudflare. The main caveat is that you need to delegate your server-side GTM DNS records to Cloudflare first, because that’s the only way you can setup the proxy.

If you’re already pointing the main website’s DNS records to Cloudflare’s name servers, you’re probably hosting your server-side GTM DNS records in Cloudflare, too.

To route the server-side GTM DNS traffic through Cloudflare’s proxy (instead of just hosting the DNS records), you need to go to the DNS -> Records configuration in the Cloudflare dashboard, search for all the A/AAAA records for your server-side GTM subdomain name, and edit each to toggle Proxy status to Proxied.

Once you’ve done this, the list of 8 records for Google Cloud Platform should look like this:

Finally, visit the Dig tool again to make sure that the subnet range for your subdomain now matches that of the main domain:

Subnet match

Remember that just the first half of the IP address needs to match between the two domains.

Bypass cache for the SGTM subdomain

In the case of server-side Google Tag Manager, it’s important that Cloudflare doesn’t cache the responses, which it defaults to when you proxy traffic through the service.

There are certain processes within Google Tag Manager, especially in Preview mode, which can break if the responses from the service are cached.

To prevent Cloudflare from caching SGTM responses, you need to go to Caching -> Cache Rules in the Cloudflare admin view to create a new bypass cache rule for your server-side GTM subdomain like this:

Cache rules

Once you’ve done all this, your setup should be ready. Remember to test carefully to make sure nothing is broken. Working with DNS records is always a bit tricky, so if you’re overwhelmed make sure you have someone from your DevOps team to help you out.

Summary

I’m always torn when writing articles like this.

I genuinely do not believe it’s worth the time and effort to always jump through hoops to make services like server-side Google Tag Manager resilient to browsers’ tracking preventions.

Relying on first-party cookies for identity persistence has been a bad idea for a long, long time, even before the dreaded ITP 2.1 came and took our cookie lifetimes away.

That being said, if you’re already hosting your DNS in Cloudflare, setting up this proxy is very easy, and there might even be additional benefits to doing so.

Cloudflare has an impressive toolkit of things like WorkersFirewalls, and Bot Management that could help make your proxied services even more reliable.

Toggling the DNS settings from DNS Only to Proxied is such a simple yet powerful move. It’s much more elegant than building your own reverse proxy on the edge, for example, especially since reverse proxies would have a hard time forwarding cookie headers among other things.

In summary: give this solution a try, but don’t spend an enormous amount of time and resources to migrate your entire domain architecture to Cloudflare just for the sake of getting first-party cookie lifetimes back for a while.

It seems pretty likely that WebKit is moving towards an end-game state where all first-party storage is restricted in expiration unless the user opts in to allow for longer storage. In this case, there’s nothing you would be able to do with service configuration.

4 Responses

  1. Hi,

    thanks for this helpful tutorial. Since we have already been on Cloudflare, this was quite easy to implement for us as well. Once more question: If you use Cloudflare as a proxy, it looks like all external requests are coming from the same IP adress to the origin server (from the Cloudflare IP that is tunnelling all the requests). That means, when the browser makes the request to the SGTM, it will always look like the request is coming from Cloudflare. The Request IP will always look the same for Google. Do you think this can have an impact on the tracking capabilities? I would assume that the IP is a important part when tracking a device…

    Looking forward to your response!

    1. Hi

      It mainly has an impact on region-based serving (for example Google Signals, region-based consent mode) and the user’s geolocation in GA4. None of the IP-based features are critical for measurement, but if you do want them then you need to stop proxying the DNS and do a pass-through instead (so choose DNS Only instead of Proxy).

  2. Hi Simo,

    Thanks for this excellent tip. We were already using CloudFlare so this was super easy to implement. I do have a question: Around the time I put this update in place the Debug Mode (Preview) of my sever side container stopped displaying any information. Could this be related? Cheers!

    1. Yes, there can be some weird side effects with debug mode due to how it funnels hits from known IPs within the cloud network. In my case, disabling the cache for the server-side domain did the trick.

Thoughts? Comment Below 👇

Your email address will not be published. Required fields are marked *

More from the Simmer Blog

The Array.reduce() method is one of the most flexible ways for converting data structures in JavaScript. This article shows you how it works.
How to set up Cloud Monitoring policies in GCP to get alerted when there are issues with the server-side Google Tag Manager setup.
How to assign a static IP address to a subset of outgoing requests from a server container. This is useful if a vendor needs to allowlist the IP addresses of incoming requests.
Hide picture