How to Make Your Server-Side GTM Accessible for Free via Cloudflare on Your Main Domain and Bypass ITP

Justus

Justus

owntag Founder

published November 22, 2024

The tracking restrictions imposed by WebKit, the browser engine behind Safari, make reliable tracking challenging, particularly by significantly limiting the lifespan of cookies, sometimes to just 24 hours.
This makes it impossible to reliably measure longer customer journeys, meaning a user’s traffic source cannot be correlated with their later conversion. Ultimately, it becomes difficult to decide which channels are worth investing in.

Setting cookies via HTTP headers, as enabled by server-side GTM, only works under specific conditions: the HTTP request setting the cookie must originate from the same IP address as the first request that delivers the website’s HTML code.
More precisely, it suffices if the two IP addresses match halfway.

Expensive: Cloudflare Enterprise

If your company has a (costly) Cloudflare Enterprise account, you can implement a solution using Origin Rules without relying on Workers.
Google provides a guide that, while focusing on the “First Party Mode” rather than server-side GTM, might still be an excellent source of inspiration.

Free: Cloudflare Workers

Cloudflare Workers are small “serverless” functions written in JavaScript that run on Cloudflare’s platform whenever a user accesses a URL matching a pattern you define.

100,000 worker executions—and therefore HTTP requests to the SGTM—are included per day (!) in the free plan, which is often sufficient for small to medium-sized websites.

Step-by-Step Guide

I assume your website already uses Cloudflare as a CDN. I do not recommend setting up Cloudflare solely to circumvent tracking restrictions. Using a CDN affects all parts and functionalities of the website and should therefore only be done in coordination with all company stakeholders.

  1. Create a new Worker:
Create Cloudflare Worker

Name your worker as you like; I chose sgtm-proxy.

Name Cloudflare Worker

Click “Edit Code” to open the worker’s code editor.

Edit Cloudflare Worker Code

Now, copy the code below and paste it into the editor, replacing the existing code entirely (1).

Deploy Cloudflare Worker

Review lines 5 (destinationUrl) and 8 (directoryName) and adjust the URLs to suit your setup.

javascript
export default {
  // Configuration object
  config: {
    // The path to your SGTM, no trailing slash
    destinationUrl: 'https://37c6a336-5346-4075-8886-c8862d8f459c.owndn.eu',
    // The folder where your GTM dataLayer variables are stored
    // E. g. 'data' if you want to use https://yourdomain.com/data/*
    directoryName: 'data'
  },

  async fetch(request, env, ctx) {
    // Clone the original request
    let newRequest = new Request(request);

    // Create a new URL object from the original request URL
    let url = new URL(request.url);

    // Remove the configured folder from the path
    const pathParts = url.pathname.split('/');
    const folderIndex = pathParts.indexOf(this.config.directoryName);
    if (folderIndex !== -1) {
      pathParts.splice(folderIndex, 1);
    }
    const newPath = pathParts.join('/');

    // Construct the new URL by combining the destination URL and the modified path + query
    const newUrl = this.config.destinationUrl + newPath + url.search;

    // Create new headers object
    let newHeaders = new Headers(request.headers);

    // Modify the Host header
    newHeaders.set('Host', new URL(this.config.destinationUrl).host);

    // Create the new request to send to the destination
    newRequest = new Request(newUrl, {
      method: request.method,
      headers: newHeaders,
      body: request.body,
      redirect: 'manual'
    });

    // Fetch the response from the destination
    const response = await fetch(newRequest);

    // Return the response without modification
    return response;
  },
};
Show all code

As an owntag user, you should enter the default hostname of your container, which ends in .owndn.eu.
The value of directoryName is the path under which your server-side GTM will be accessible. For example, if you want to send data to https://yourwebsite.com/data/, the value here is data.
To test your setup, append /healthy (2) to the URL shown in the editor and click “Send” (3). If everything is configured correctly, ok (4) should appear in the window below.

The path you choose must not be used for any other purpose. If unsure, ask your colleagues whether the path can be used without issues. /data/ is just an example; more specific alternatives like /metrics/ or /insights/ are also possible.

If that works, you can deploy the worker live with a single click on “Deploy” (5).

Next, ensure the worker is executed when the special URL path is called.

Add Cloudflare Worker Route
Select Cloudflare Worker Route

In the “Zone” field, select the domain for which you created the worker.

In the “Route” field below, enter the URL path where the worker should execute.
The appropriate pattern for this is:

*.yourwebsite.com	/data/*

Again, adjust data to match the value you defined in directoryName in the worker code.

That’s it!
Now you can test your new setup by calling the URL of your worker with /healthy appended:

https://yourwebsite.com/data/healthy

The worker will forward the request to the server-side GTM, meaning in our example, the URL https://37c6a336-5346-4075-8886-c8862d8f459c.owndn.eu/healthy will be called.
The /healthy endpoint is a standard feature of the server-side GTM and returns “ok” if everything is working as expected.

Adjust GTM Container Snippet

You can now adjust your GTM container snippet so that data is transmitted to your tracking system as usual.

Adjust GTM Container Snippet

If you haven’t done so yet, set up a client in your server-side GTM container that delivers the gtm.js file for your web container:

Set up client for gtm.js

If you also change the filename `gtm.js`, you can bypass simple ad blockers that block loading the GTM web container based on this filename. Use the GTM Loader Template by Simo Ahava.
Make sure to update the filename in your GTM container snippet accordingly.

Set server_container_url

Finally, you must set the server_container_url parameter in your GTM web container to point to your worker’s URL. This ensures your GA4 tags send data to your Cloudflare worker instead of directly to google-analytics.com:

Set GTM Web Container server_container_url

When you preview these changes, you should see that outgoing requests containing GA4’s characteristic collect URL send data to your website’s main domain:

Outgoing requests yourwebsite.com

Congratulations!

You’ve now set up a first-party and same-origin configuration that—at least for now—bypasses ITP.

Become a Server Side Tagging Pro with owntag

Take control of your digital data collection with Server Side Tagging and Server Side GTM – easily hosted with owntag.

App screenshot