Cloudflare
Snowplow Cloudflare Integration
Integrating Snowplow with a Cloudflare worker allows you to create a Snowplow collector firing on the same domain as your website, on a random path, thus bypassing the Safari ITP IP address limitation. See Safari ITP.
Download Safari Technology Preview to observe Intelligent Tracking Prevention (ITP) in action.
WITHOUT Cloudflare Worker (below) even though the domain is the same as the website (sp.snowcatcloud.com) the cookie is set to expire in 7 days (March 27th 2023).

WITH Cloudflare worker (below) the cookie is set to expire in 1 year (March 19th 2024).

Step 1: Create a CNAME for your Snowplow collector
Cloudflare worker needs a CNAME configured to your Snowplow collector; if you reference your collector hostname directly, it won't work; you'll get an HTTP error 530.
Configure a CNAME with a name like worker-prod-collector
and content to your Snowplow collector e.g., sp.yourdomain.com
.
Step 2: Create a Cloudflare worker
- Log into your Cloudflare account
- Click Workers
- Create a Service
- Name the service
snowplow-collector
, select HTTP router, click Create service - Click Quick edit
- Add the code below to the code editor
- Edit COLLECTORPATH and YOURSITE.COM, where collector path is the path that will receive the Snowplow events, and NEWCNAME is a CNAME record for your collector.
Cloudflare Worker JS code
// Cloudflare HTTP Router, Replace forward URL with your CNAME collector.
// And adjust pathname so a path that doesn't currently exist (this will be your Snowplow collector)
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const url = new URL(request.url)
const { pathname } = url
// Change the path to what you want your collector to be.
if (pathname.startsWith('/COLLECTORPATH')) {
const forwardUrl = 'https://worker-prod-collector.YOURSITE.COM/com.snowplowanalytics.snowplow/tp2'
const headers = new Headers(request.headers)
// Remove Cloudflare specific headers that should not be forwarded
headers.delete('CF-Connecting-IP')
headers.delete('CF-IPCountry')
headers.delete('CF-Ray')
headers.delete('CF-Visitor')
headers.delete('CF-Request-ID')
const forwardRequest = new Request(forwardUrl, {
method: request.method,
headers: headers,
body: request.body,
redirect: 'manual',
})
const forwardResponse = await fetch(forwardRequest)
// Copy the response headers from the forwarded response
const responseHeaders = new Headers(forwardResponse.headers)
responseHeaders.delete('content-security-policy-report-only')
responseHeaders.delete('content-security-policy')
// Modify the Cache-Control header to add max-age=0
responseHeaders.set('Cache-Control', 'max-age=0, ' + headers.get('Cache-Control'))
// Return the forwarded response with its original headers
return new Response(forwardResponse.body, {
status: forwardResponse.status,
statusText: forwardResponse.statusText,
headers: responseHeaders,
})
} else {
const response = await fetch(request)
return response
}
}
Step 3: Add a Worker Route
Now we'll go to the domain in Cloudflare and configure a path that will receive the Snowplow requests from the tracker, thus embedding the Snowplow collector into our website path.
- Go to the domain in Cloudflare account (YOURSITE.COM)
- Click Workers Routes
- Click Add route and configure it with the following parameters:
- Route:
YOURSITE.COM/COLLECTORPATH*
(not the asterisk) - Service: (The service you just created in the previous step)
- Environment: production
- Route:
Step 4: Configure your JS Tracker
In your Snowplow initialization script, configure the collector
and postPath
to reflect the new collector URL and path.
// Note how it points to www.yoursite.com
snowplow("newTracker", "spc", "www.YOURSITE.COM", {
appId: "aid",
discoverRootDomain: true,
postPath: '/COLLECTORPATH', // Collector must be configured
cookieSameSite: "Lax", // Recommended
eventMethod: "post",
bufferSize: 1,
cookieLifetime: 63072000,
stateStorageStrategy: "cookieAndLocalStorage",
contexts: {
webPage: true,
performanceTiming: true,
},
});
Go to www.YOURSITE.COM, while using the Snowplow Chrome Debugger and observe the Snowplow hit, it should return 200 and you should see the cookies set with one year expiration date, even when using Safari Technology Preview.
If you would like to see a working example, go to SnowcatCloud and look for polarbear
in the Network tab.