Same-origin proxy
Send events through your own domain. It is the difference between a seven-day cookie and a 400-day one, and between being blocked and being ordinary.
Why
Two separate problems, one fix.
Safari. A cookie written by JavaScript is capped at seven days, no matter what expiry you ask for. A returning visitor then looks new after a week, and revenue attribution beyond a week breaks. A cookie set by your own server, in a response header, is kept for as long as you say — trckable asks for 400 days.
Blocking. Extensions block requests to known analytics hosts and paths. A
request to /api/e on your own domain, from a script that is part of your own
bundle, looks like your app talking to itself, because that is what it is.
trckable does not claim to be unblockable. It claims that this is the accurate install, and says so plainly.
Next.js
// app/api/e/route.ts — same-origin: past analytics blocklists, 400-day Safari visitors
export { POST } from 'trckable/next'# .env
TRCKABLE_HOST=https://stats.example.com
TRCKABLE_PROXY_KEY=your-proxy-keyAnything with a fetch handler
import { proxy } from 'trckable/server'
const trckable = proxy({ host: 'https://stats.example.com', proxyKey: process.env.TRCKABLE_PROXY_KEY })
app.post('/api/e', (c) => trckable(c.req.raw))Nginx
# Nginx
location /t.js {
proxy_pass https://stats.example.com/js/tkb_a1b2c3d4.js;
proxy_ssl_server_name on;
}
location /api/e {
proxy_pass https://stats.example.com/api/e;
proxy_ssl_server_name on;
proxy_set_header X-Trckable-Client-IP $remote_addr;
proxy_set_header X-Trckable-Proxy-Key your-proxy-key;
}
<!-- every page, in <head>: the script and its events from your domain -->
<script
defer
data-site="tkb_a1b2c3d4"
data-domain="example.com"
src="/t.js">
</script>Caddy
handle /api/e {
reverse_proxy https://stats.example.com {
header_up Host stats.example.com
header_up X-Trckable-Proxy-Key "your-proxy-key"
header_up X-Real-IP {remote_host}
}
}The proxy key
trckable refuses to believe a forwarded address unless it comes with that site's proxy key. Without this rule, anyone could post events claiming to come from any address in the world, and your country breakdown would be fiction.
The key is per site and shown in Settings → General → For developers, and in the install code. Keep it on your server, never in the browser.
An owner can see it; a viewer cannot.
If your host cannot add headers
Some static hosts rewrite paths but cannot set a request header. Then trckable sees your CDN's address instead of the visitor's, and every visit looks like it came from one city.
The fix is an edge function — a Vercel, Netlify or Cloudflare handler that
forwards the request with the header — and npx trckable doctor detects the
problem and says which one you need.
Checking it
npx trckable doctor https://example.comIt checks that your site is served over HTTPS and that the events endpoint answers a browser's cross-origin check.
npm package
One install with subpath exports for React, Next, any other framework and your server. The tracker is bundled into your own code, so there is no separate file for anything to block.
Landing page and app
A plain HTML landing page on example.com and a Next.js app on app.example.com, as one site: one visitor, one journey, and the sale credited to what brought them.