# 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. > **Tip: 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.js` - `POST /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: ```html ``` > **Note: 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 like `analytics`, `track` or `stats` in 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 ```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): ```text /dtc/tracker.js https://www.didthey.click/sdk/tracker.js 200 /dtc/collect https://www.didthey.click/api/collect 200 ``` The `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 ```text 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 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`: ```typescript 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 1. Load your site with the new snippet and an ad blocker (e.g. uBlock Origin) enabled. 2. In devtools → Network, confirm `/dtc/tracker.js` loads and `/dtc/collect` returns 200. 3. Check the didthey.click dashboard: events should arrive with the correct country (not your hosting provider's), which confirms the IP is forwarded properly.