Self-serve proxy (ad-blocker bypass)
Ad blockers block requests to known analytics domains, which can hide up to ~30% of real traffic.
Serving the tracker script and the collect endpoint from your own domain makes both requests
first-party, so blocklists targeting didthey.click no longer apply.
This is the recommended setup
Proxying isn't a fallback for edge cases — it's how we recommend everyone install didthey.click. No SDK changes are needed: the script accepts a `data-endpoint` attribute pointing at any URL, and everything else works the same.How it works
You proxy two paths on your domain to didthey.click:
GET /dtc/tracker.js→https://www.didthey.click/sdk/tracker.jsPOST /dtc/collect→https://www.didthey.click/api/collect
Then update your snippet to load the script from your own domain and point events at your proxied collect path:
Proxied snippet
<script
src="https://yoursite.com/dtc/tracker.js"
data-website-id="YOUR_WEBSITE_ID"
data-endpoint="https://yoursite.com/dtc/collect"
></script>data-endpoint is required here
Without it, the script derives the endpoint from its own page origin by appending `/api/collect`, which would collide with your site's own `/api` routes./dtc/is a suggestion — any neutral prefix works. Avoid words likeanalytics,trackorstatsin the path: ad blockers also match URL patterns, not just domains.- Your proxy must forward the visitor’s IP in
X-Forwarded-For, otherwise geo/country resolution silently reports your proxy’s location instead of the visitor’s. Vercel, Netlify and Caddy do this by default; nginx needs it set explicitly (see below).
Vercel
vercel.json
{
"rewrites": [
{ "source": "/dtc/tracker.js", "destination": "https://www.didthey.click/sdk/tracker.js" },
{ "source": "/dtc/collect", "destination": "https://www.didthey.click/api/collect" }
]
}Netlify
Add to public/_redirects (or _redirects in your publish directory):
_redirects
/dtc/tracker.js https://www.didthey.click/sdk/tracker.js 200
/dtc/collect https://www.didthey.click/api/collect 200The 200 status makes it a proxy rewrite rather than a redirect — redirects would drop the POST
body and re-expose the didthey.click domain to blockers.
Caddy
Caddyfile
yoursite.com {
handle /dtc/tracker.js {
rewrite * /sdk/tracker.js
reverse_proxy https://www.didthey.click {
header_up Host www.didthey.click
}
}
handle /dtc/collect {
rewrite * /api/collect
reverse_proxy https://www.didthey.click {
header_up Host www.didthey.click
}
}
}nginx
nginx.conf
location = /dtc/tracker.js {
proxy_pass https://www.didthey.click/sdk/tracker.js;
proxy_set_header Host www.didthey.click;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_ssl_server_name on;
}
location = /dtc/collect {
proxy_pass https://www.didthey.click/api/collect;
proxy_set_header Host www.didthey.click;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_ssl_server_name on;
}SvelteKit / Next.js (app-level proxy)
If you can’t touch the platform config, a tiny pass-through route works too. SvelteKit example, src/routes/dtc/collect/+server.ts:
src/routes/dtc/collect/+server.ts
export async function POST({ request, getClientAddress }) {
const body = await request.arrayBuffer();
return fetch('https://www.didthey.click/api/collect', {
method: 'POST',
headers: {
'content-type': request.headers.get('content-type') ?? 'text/plain',
'user-agent': request.headers.get('user-agent') ?? '',
'x-forwarded-for': getClientAddress()
},
body
});
}Forwarding user-agent and x-forwarded-for matters: they drive device breakdowns, bot
detection and geo.
Verifying it works
- Load your site with the new snippet and an ad blocker (e.g. uBlock Origin) enabled.
- In devtools → Network, confirm
/dtc/tracker.jsloads and/dtc/collectreturns 200. - Check the didthey.click dashboard: events should arrive with the correct country (not your hosting provider’s), which confirms the IP is forwarded properly.