Skip to Content
First-Party ProxyCloudflare Workers

Cloudflare Workers

A Cloudflare Worker is an excellent choice for both proxy modes. Workers run at the edge, close to your visitors, and Cloudflare sets CF-Connecting-IP to the real client IP, so Full mode with IP forwarding requires no extra infrastructure.

Snow’s Settings → Proxy tab generates the complete Worker code for you. Copy it, paste it, deploy.

Simple mode proxies only the script. Events go straight from the visitor’s browser to the Snow API.

Create a Worker

In the Cloudflare dashboard, go to Workers & Pages → Create application → Create Worker. Name it something neutral, like snow-proxy.

Paste this code

Replace https://api.snowanalytics.app with your actual Snow collector URL.

export default { async fetch(request) { const url = new URL(request.url); const SNOW = "https://api.snowanalytics.app"; if (url.pathname === "/sa/sa.js") { return fetch(SNOW + "/sa.js"); } return new Response("Not found", { status: 404 }); }, };

Add a route

In Workers → your Worker → Settings → Triggers, add the route yourdomain.com/sa/sa.js.

Update your embed

<script defer src="https://yourdomain.com/sa/sa.js" data-site="YOUR_SITE_ID" data-api-url="https://api.snowanalytics.app/api/collect" data-domain="yourdomain.com"></script>

The data-api-url attribute points events directly at the Snow API, so the visitor’s browser posts them without going through your Worker. That’s what keeps locations accurate in Simple mode.


Full mode (script and events)

Full mode proxies both the script and the event endpoint. Everything goes through your domain, nothing third-party.

Because events flow through the Worker, you must forward the real visitor IP. Cloudflare makes this easy: CF-Connecting-IP is the real client IP, set by Cloudflare’s edge before the request reaches your Worker.

For Full mode, enable Secure proxy in Settings → Proxy to get a per-site secret. Your Worker sends this secret alongside the IP so Snow can trust it. See Forwarding the visitor IP for the full explanation.

Enable Secure proxy

In Settings → Proxy, switch to Full mode and enable Secure proxy. Copy the secret. It’s shown once.

Create the Worker

Replace https://api.snowanalytics.app and YOUR_PROXY_SECRET.

export default { async fetch(request) { const url = new URL(request.url); const SNOW = "https://api.snowanalytics.app"; const PROXY_SECRET = "YOUR_PROXY_SECRET"; if (url.pathname === "/sa/sa.js") { return fetch(SNOW + "/sa.js"); } if (url.pathname === "/sa/api/collect") { const ip = request.headers.get("CF-Connecting-IP") || ""; const headers = new Headers(); headers.set("content-type", request.headers.get("content-type") || "text/plain"); headers.set("user-agent", request.headers.get("user-agent") || ""); headers.set("X-Snow-Client-IP", ip); headers.set("X-Forwarded-For", ip); headers.set("X-Snow-Proxy-Secret", PROXY_SECRET); return fetch(SNOW + "/api/collect", { method: "POST", headers, body: await request.text(), }); } return new Response("Not found", { status: 404 }); }, };

Notice that this Worker does not forward visitor cookies or auth headers. Only the headers above are sent upstream.

Add a route for both paths

Add yourdomain.com/sa/* as the Worker route so both /sa/sa.js and /sa/api/collect are handled.

Update your embed

<script defer src="https://yourdomain.com/sa/sa.js" data-site="YOUR_SITE_ID" data-api-url="/sa/api/collect" data-domain="yourdomain.com"></script>

data-api-url is now a relative path through your own domain. Nothing goes directly to Snow from the browser.

Verify

Generate some traffic, then check Analytics → Locations. You should see a realistic country distribution, not everything from a single city. See Verify it’s working for details.