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 (recommended)
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.