Adblockers and proxying
Serve the tracker first-party so content blockers cannot filter it.
Client-side analytics can be blocked. Serving the tracker from your own domain fixes that for almost everyone. This page shows the one rule you need per platform.
Why blockers win by default
A visitor on Brave with Shields up, or anyone running uBlock Origin whose filter lists include the analytics domain or the /api/track path, is simply never counted. This is true of every script-based analytics tool, Google Analytics included.
The fix used by every privacy-first analytics tool is first-party proxying: serve the tracker script and receive its events from your own domain, so the browser only ever makes same-origin requests. A network filter cannot tell them apart from your site's own assets, so it cannot block them. This lifts capture to nearly all traffic, including most blocker users.
It cannot defeat a visitor with JavaScript disabled. Nothing script-based can. That residual blind spot is unavoidable and tiny.
How the tracker resolves URLs
Two facts about t.js make proxying a one-rule change:
- The ingest endpoint is the
data-apiattribute if set, otherwise the origin the script was served from plus/api/track. - The lazy chunk
t-x.js(Web Vitals and error capture) is loaded relative to the script's own URL.
So if you serve t.js from your own domain under a path prefix and point data-api at that same prefix, the script, its lazy chunk, and the event stream are all first-party. One proxy rule covers all three.
The recipe
Proxy a single neutral path prefix on your domain to the WebSight origin. Use a bland name such as /stats, /s, or /insights, and avoid /analytics, /track, or /tracker, which some cosmetic filter lists flag by name alone.
Map yourdomain.com/stats/* to https://websight.srexrg.me/*. That single rule routes:
| Request on your domain | Proxied to |
|---|---|
/stats/t.js | https://websight.srexrg.me/t.js |
/stats/t-x.js (vitals/errors) | https://websight.srexrg.me/t-x.js |
/stats/api/track (events) | https://websight.srexrg.me/api/track |
Then point the snippet at the prefix:
<script
defer
src="https://yourdomain.com/stats/t.js"
data-site="yourdomain.com"
data-api="/stats/api/track"
data-vitals
data-errors
></script>data-api is a same-origin relative path, so events post to your own domain. data-vitals and data-errors are optional; include them to load t-x.js, or drop them to stay at the core.
Platform rules
Pick the one matching where your site is hosted. All map /stats/* to the WebSight origin.
In next.config.js or next.config.ts:
async rewrites() {
return [
{ source: "/stats/:path*", destination: "https://websight.srexrg.me/:path*" },
];
}Runs on the Next server or edge. Note that output: "export" (static export) has no server to proxy through, so use your CDN's rule instead.
In vercel.json:
{
"rewrites": [
{ "source": "/stats/:path*", "destination": "https://websight.srexrg.me/:path*" }
]
}In netlify.toml:
[[redirects]]
from = "/stats/*"
to = "https://websight.srexrg.me/:splat"
status = 200
force = trueA Worker:
export default {
async fetch(request) {
const url = new URL(request.url);
if (url.pathname.startsWith("/stats/")) {
const target =
"https://websight.srexrg.me/" +
url.pathname.slice("/stats/".length) +
url.search;
return fetch(target, request);
}
return fetch(request);
},
};Or use a Cloudflare Origin Rule pointing /stats/* at the WebSight host if you prefer no Worker.
location /stats/ {
proxy_pass https://websight.srexrg.me/;
proxy_set_header Host websight.srexrg.me;
proxy_ssl_server_name on;
}The trailing slash on both location and proxy_pass strips the /stats/ prefix before forwarding, so /stats/t.js becomes /t.js upstream.
handle_path /stats/* {
reverse_proxy https://websight.srexrg.me {
header_up Host websight.srexrg.me
}
}Verify it works
After deploying the rule and updating the snippet:
- Open your site and go to DevTools, Network.
- Confirm
stats/t.jsreturns 200 from your own domain, not fromwebsight.srexrg.me. - Navigate a page and confirm the POST to
/stats/api/trackreturns 202. - Check that the WebSight Realtime screen shows the visit.
- Turn on Brave Shields or uBlock and repeat. The requests should still go through, because they are same-origin.
Caveats
Proxy the whole prefix, not just t.js. If you only proxy the one file, t-x.js and the event POST fall back to third-party and get blocked again. The /stats/* prefix rule covers all of them.
- Do not cache the event endpoint.
t.jsandt-x.jsare cacheable and a CDN in front of them is fine, but/api/trackis a POST, so make sure no rule caches it. - Keep the destination current. If WebSight later moves off
websight.srexrg.me, update the one rewrite rule. - If you self-host WebSight, replace
websight.srexrg.mewith your own instance's origin everywhere above.