Public
Serves Umami analytics from your own origin to dodge ad blockers
analyticsblogproxyumami
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.

Umami proxy

Proxies a Umami instance through this val's origin, so the browser never requests a hostname ad-block filter lists match on.

Rendering mermaid diagram...

Setup

1. Point it at your Umami instance. UMAMI_HOST defaults to Umami Cloud.

šŸ‘‰ Add UMAMI_HOST here: https://www.val.town/x/wallaby/anal/environment-variables?key=UMAMI_HOST

2. Change your script tag. data-host-url is required — the tracker does not infer its host from the script's own src, it falls back to https://gateway.umami.is, which is the hostname you're trying to avoid:

<script defer src="https://wallaby-assets.val.run/u.js" data-website-id="YOUR-WEBSITE-ID" data-host-url="https://wallaby-assets.val.run" ></script>

3. Check it works. Load your blog with the network tab open. POST https://wallaby-assets.val.run/api/send should return 200 with a {"beep":"boop"} body. If events aren't arriving, data-host-url is the first thing to check.

Notes

  • No CORS code needed. Val Town answers the beacon's preflight itself, echoing back the x-umami-* headers the tracker sends. Nothing in this val has to handle OPTIONS.
  • /api/send is proxied, not renamed. The hostname is the main thing filter lists key on. If you also want the path disguised, string-replace /api/send in the served script and forward that new path upstream instead.
  • Any path is proxied. / returns Umami's own homepage, since everything that isn't a .js file is forwarded upstream. Harmless, but worth a guard if it bothers you.
  • The visitor's IP goes upstream as x-client-ip. Umami hashes the address into its session id, so without it every visitor sharing a user agent collapses into a single session. Whether it actually lands depends on the upstream's own proxy layer: Umami reads cf-connecting-ip first, and a CDN sitting in front of Umami overwrites that at its edge.

A note on what this is doing

Ad blockers are a privacy signal. This bypasses it for visitors who installed one on purpose, so it's worth being deliberate in return:

  • Umami is cookieless and stores no personal data, which makes it a reasonable thing to measure with — but the visitor's stated preference still loses.
  • The tracker already skips browsers sending DNT/GPC (navigator.doNotTrack). Leave it on.
  • x-client-ip is the one place visitor data crosses a boundary. Delete that line if you'd rather trade accurate geography for less data.