Reverse Proxy
Route Human Behavior traffic through your own domain to bypass ad blockers and keep tracking first-party.
By default the SDK sends events to https://ingest.humanbehavior.co. A growing share of browsers (Brave, Safari ITP, DuckDuckGo) and extensions (uBlock Origin, AdGuard) block requests to known analytics domains. This silently drops sessions from your most privacy-conscious users.
The fix is a reverse proxy: point the SDK at a path on your own domain, and have your infrastructure forward those requests to https://ingest.humanbehavior.co. From the browser's perspective the traffic is first-party and is not filtered.
How it works
- Pick a path on your domain to dedicate to ingestion, e.g.
/hb. - Configure your infrastructure to forward
yourdomain.com/hb/*→https://ingest.humanbehavior.co/*. - Tell the SDK to use your domain by passing
ingestionUrl.
const tracker = HumanBehaviorTracker.init('your-api-key', {
ingestionUrl: 'https://yourdomain.com/hb'
});The SDK appends /api/ingestion/... to whatever ingestionUrl you provide, so the final requests look like https://yourdomain.com/hb/api/ingestion/events. Your proxy should strip the /hb prefix before forwarding.
Endpoints to forward
Your proxy only needs to handle paths under /api/ingestion/. These are all of them:
| Method | Path | Purpose |
|---|---|---|
| POST | /api/ingestion/init | Session initialization |
| POST | /api/ingestion/events | Session replay events (highest volume) |
| POST | /api/ingestion/customEvent | Custom events |
| POST | /api/ingestion/customEvent/batch | Batched custom events |
| POST | /api/ingestion/user | User identification |
| POST | /api/ingestion/user/auth | Authenticated user linking |
| POST | /api/ingestion/ip-info | IP metadata |
| POST | /api/ingestion/logs | Console log forwarding |
| POST | /api/ingestion/network | Network error forwarding |
A catch-all rule under /api/ingestion/* is the simplest configuration.
Next.js (App Router or Pages Router)
Add a rewrite in next.config.js (or next.config.mjs):
/** @type {import('next').NextConfig} */
const nextConfig = {
async rewrites() {
return [
{
source: '/hb/:path*',
destination: 'https://ingest.humanbehavior.co/:path*',
},
];
},
};
module.exports = nextConfig;Then initialize the SDK:
HumanBehaviorTracker.init('your-api-key', {
ingestionUrl: '/hb' // relative URL is fine — resolves against your site's origin
});Vercel
If you're not using Next.js, use vercel.json:
{
"rewrites": [
{
"source": "/hb/:path*",
"destination": "https://ingest.humanbehavior.co/:path*"
}
]
}Vercel rewrites are free on Hobby, but a high-traffic site will hit the Edge Requests quota. For large volumes prefer Cloudflare Workers (below) to keep the proxy off your Vercel bill.
Cloudflare Workers
Recommended for high traffic — free tier covers 100k requests/day and runs on the edge.
export default {
async fetch(request) {
const url = new URL(request.url);
// Only proxy /hb/* — everything else falls through to your origin.
if (!url.pathname.startsWith('/hb/')) {
return fetch(request);
}
const upstream = new URL(
url.pathname.replace(/^\/hb/, '') + url.search,
'https://ingest.humanbehavior.co'
);
return fetch(upstream, {
method: request.method,
headers: request.headers,
body: request.body,
redirect: 'manual',
});
},
};Bind the Worker to a route like yourdomain.com/hb/* in the Cloudflare dashboard.
nginx
location /hb/ {
proxy_pass https://ingest.humanbehavior.co/;
proxy_set_header Host ingest.humanbehavior.co;
proxy_ssl_server_name on;
proxy_http_version 1.1;
proxy_set_header Connection "";
# Session replay events can be several hundred KB — raise the body limit.
client_max_body_size 10m;
proxy_read_timeout 60s;
}Note the trailing slash on proxy_pass: it tells nginx to strip the /hb/ prefix before forwarding.
Cloudflare (Rules, no Worker)
If you're already behind Cloudflare, you can use an Origin Rule instead of a Worker — no JS required:
- Rules → Origin Rules → Create rule.
- Match:
URI Path starts with /hb/. - Action: override the Host Header to
ingest.humanbehavior.coand Resolved Address toingest.humanbehavior.co. - Add a URL Rewrite rule that strips the
/hbprefix:Rewrite path to http.request.uri.path | replace | /hb(/.*) → $1.
Caddy
yourdomain.com {
handle_path /hb/* {
reverse_proxy https://ingest.humanbehavior.co {
header_up Host ingest.humanbehavior.co
}
}
# ...rest of your site config
}handle_path automatically strips the matched prefix.
Verifying it works
- Deploy the proxy change.
- Update the SDK
ingestionUrland deploy the frontend. - Open your site in a browser, open DevTools → Network, and filter by your domain (e.g.
yourdomain.com/hb). - You should see
POSTrequests to/hb/api/ingestion/events,/hb/api/ingestion/init, etc., all returning200. - Enable an ad blocker and reload. The requests should still succeed — no entries should show
blockedorERR_BLOCKED_BY_CLIENT. - Confirm the session appears in your Human Behavior dashboard.
Common gotcha: if you forget the trailing / in nginx's proxy_pass (or the equivalent prefix-strip in other proxies), requests will hit https://ingest.humanbehavior.co/hb/api/ingestion/events and return 404. Check the upstream path, not just the response code.