The problem nobody talks about
You ship a product. You add Google Analytics. You add Amplitude. Maybe PostHog. You check your dashboard after a week and the numbers look off.
Not slightly off. Way off.
Turns out, 30-40% of your users run adblockers. And adblockers do not care if you are a billion-dollar ad company or a side project with 12 users. They block requests to known analytics domains. All of them.
Your analytics SDK loads fine. It fires events fine. But those events never reach the server because the request to www.google-analytics.com gets killed before it leaves the browser.
You are making decisions based on 60% of your data. That is not analytics. That is guessing.
What I tried first
I looked at existing solutions. Most of them fall into two camps.
Camp one: paid services that proxy analytics for you. They work, but you are paying someone to run Nginx. That felt wrong.
Camp two: custom server-side setups. Write your own proxy, handle headers, manage CORS, deal with path rewrites. Doable, but annoying. I did not want to maintain a Node.js server just to forward requests.
I wanted something dumber. Something that just works.
So I built Saki
Saki is a self-hosted Nginx reverse proxy. You run it as a Docker container on your domain. It forwards analytics requests through your infrastructure instead of directly to the analytics provider.
Here is what that means in practice.
Your website loads a script from www.googletagmanager.com. Adblockers block it. But if that same script loads from your-domain.com/tg/script.js, adblockers have no idea it is an analytics request. It looks like a first-party resource.
That is the whole trick. Route through your own domain, and adblockers leave it alone.
docker run -d -p 8765:80 rajnandan1/saki
One command. No config files. No environment variables required. It comes with sane defaults out of the box.
What it supports
Saki ships with pre-configured routes for the services most teams actually use:
- Google Tag Manager (
/tg/) - Google Analytics (
/an/) - Amplitude - both CDN and API (
/acdn/,/aapi/) - Mixpanel - both CDN and API (
/mxc/,/mxa/) - Microsoft Clarity (
/cla/) - PostHog - JS and API (
/phj/,/pha/)
Each route has a short, non-obvious path. /tg/ does not scream "this is Google Tag Manager." That is by design.
And if you use something not on the list, you add a new Nginx location block. If it has a domain, Saki can proxy it.
How you use it
The change on your website is one line. Replace the analytics domain with your Saki proxy URL.
Before:
<script src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXX"></script>
After:
<script src="https://your-domain.com/tg/script.js?id=G-XXXXXXXX"></script>
No SDK changes. No config rewrites. Same script, different hostname.
Saki forwards all headers - User-Agent, cookies, IP address, language, referrer. The analytics provider sees a normal request. It has no idea it went through a proxy.
Deployment
For production, point a subdomain at it with HTTPS. Something like s.yourdomain.com. Works on Railway, Render, Fly.io, a VPS, or bare metal. Anywhere you can run a Docker container.
Here is a minimal docker-compose.yml:
services:
saki:
image: rajnandan1/saki:latest
container_name: saki
ports:
- "8765:80"
restart: unless-stopped
Want to customize route paths? Set environment variables like ROUTE_GTM, ROUTE_GA, ROUTE_CLARITY, and so on.
Why I did not just write a blog post about Nginx config
Fair question. You could set this up yourself with a few Nginx location blocks.
But here is the thing. You would have to figure out the right proxy headers, handle path rewrites for each service, keep up with domain changes from analytics providers, and test it across browsers. Then do that for every project.
Saki packages all of that into one container. Pull the image, run it, point your scripts at it. Done.
I am lazy. I built this so I could be lazy faster.
What Saki is not
It is not a privacy tool. It does not anonymize data or block tracking. It is the opposite, actually. It makes sure analytics requests go through successfully.
If your users run adblockers because they do not want to be tracked, Saki bypasses that. You should think about the ethics of that for your use case. I built it because I needed accurate numbers for my own projects, and I was tired of making decisions on incomplete data.
Try it
The repo is open source, MIT licensed.
- Website: saki.rajnandan.com
- GitHub: github.com/rajnandan1/saki
- Docker Hub: hub.docker.com/r/rajnandan1/saki
If you have questions or want to add support for another service, open an issue. PRs welcome.
I build tools for developers. Previously built Kener, an open-source status page. Find me at rajnandan.com.

Top comments (0)