Skip to main content

Set up the Triggerbee proxy with a Cloudflare Worker

If your website runs through Cloudflare, a Cloudflare Worker is the easiest way to set up the proxy for server-side cookies. The Worker forwards everything under https://yourdomain.com/tb/ to Triggerbee and passes the visitor's IP address and your hostname along.

This guide covers Step 1 of First-party and server-side cookies with Triggerbee. Read that article first.

Before you start

  • Your website's domain must be on Cloudflare.

  • You need access to Workers in your Cloudflare account.

Tip: We recommend a static IP for the Worker. This is usually included in Cloudflare's Enterprise plan.

Set up the Worker

  1. In Cloudflare, create a new Worker.

  2. Replace the Worker's code with the script below.

  3. If you don't want to use /tb, change PREFIX at the top of the script. Nothing else needs to change.

  4. Deploy the Worker and add it as a route on your domain, for example yourdomain.com/tb/*.

Javascript

// Serves Triggerbee from your own domain, forwarding only Triggerbee's own cookies and the headers it reads
// Set PREFIX to where you want it mounted. Nothing else in this file needs changes
const PREFIX = '/tb';
const UPSTREAM = 'https://t.myvisitors.se';

const EVENT_PATHS = /^\/((3\/|4\/)?t)$/;
const FORWARDED_HEADERS = new Set([
'accept', 'accept-encoding', 'accept-language', 'content-length', 'content-type', 'origin', 'referer', 'user-agent',
'access-control-request-headers', 'access-control-request-method', 'if-modified-since', 'if-none-match', 'x-application-id',
]);
const FORWARDED_HEADER_PREFIX = 'x-triggerbee-';
const FORWARDED_COOKIES = new Set(['_smtruid', '_mtruid']);
const FORWARDED_COOKIE_PREFIX = 'triggerbee';
const DROPPED_RESPONSE_HEADERS = ['nel', 'report-to', 'set-cookie'];

function isTriggerbeeCookie(pair) {
const name = pair.split('=', 1)[0].trim();
return FORWARDED_COOKIES.has(name) || name.startsWith(FORWARDED_COOKIE_PREFIX);
}

function triggerbeeCookies(header) {
return (header ?? '')
.split(';')
.map(pair => pair.trim())
.filter(isTriggerbeeCookie)
.join('; ');
}

export default {
async fetch(request) {
const url = new URL(request.url);

if (!url.pathname.startsWith(`${PREFIX}/`)) {
return fetch(request);
}
const path = url.pathname.slice(PREFIX.length);

const headers = new Headers();
for (const [name, value] of request.headers) {
const lowerName = name.toLowerCase();
if (FORWARDED_HEADERS.has(lowerName) || lowerName.startsWith(FORWARDED_HEADER_PREFIX)) {
headers.set(name, value);
}
}
const cookies = triggerbeeCookies(request.headers.get('cookie'));
if (cookies) {
headers.set('Cookie', cookies);
}
headers.set('X-Forwarded-Host', url.host);
headers.set('X-Client-IP', request.headers.get('CF-Connecting-IP') ?? '');

// Appended rather than resolved: resolving would read /tb//other.example/x as a request for another host
const upstream = UPSTREAM + path + url.search;
let response;
try {
response = await fetch(upstream, {
method: request.method,
headers,
body: request.method === 'GET' || request.method === 'HEAD' ? undefined : request.body,
redirect: 'manual',
});
} catch {
return new Response('', { status: 502 });
}

const out = new Headers(response.headers);
for (const name of DROPPED_RESPONSE_HEADERS) {
out.delete(name);
}
for (const cookie of response.headers.getSetCookie()) {
out.append('set-cookie', cookie);
}
// This answer is on your own origin, so a page from Triggerbee must not run as your site; scripts and JSON ignore it
out.set('content-security-policy', 'sandbox');
if (EVENT_PATHS.test(path)) {
out.set('cache-control', 'no-store');
}

return new Response(response.body, { status: response.status, headers: out });
},
};

What the script does

  • Forwards requests under /tb/ to https://t.myvisitors.se.

  • Sends the visitor's IP address (from Cloudflare's CF-Connecting-IP) in X-Client-IP, and your host and protocol in X-Forwarded-Host and X-Forwarded-Proto.

  • Returns Triggerbee's Set-Cookie headers to the browser so the cookies are set on your domain.

  • Makes sure tracking events are never cached.

  • Returns an error for the tracking request only if Triggerbee can't be reached. Your website keeps working as usual.

Test the Worker

Open https://yourdomain.com/tb/js?site_id=YOUR_SITE_ID. If you see JavaScript code, the Worker works.

Troubleshooting

The test URL shows your website's 404 page. The Worker route isn't active on that path. Check that the route matches your domain exactly, including www, and ends with /tb/* (or your own prefix).

The test URL shows a 502 error. The Worker couldn't reach Triggerbee. Try again in a minute. If it continues, contact [email protected].

Did this answer your question?