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

  1. Pick a path on your domain to dedicate to ingestion, e.g. /hb.
  2. Configure your infrastructure to forward yourdomain.com/hb/*https://ingest.humanbehavior.co/*.
  3. 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:

MethodPathPurpose
POST/api/ingestion/initSession initialization
POST/api/ingestion/eventsSession replay events (highest volume)
POST/api/ingestion/customEventCustom events
POST/api/ingestion/customEvent/batchBatched custom events
POST/api/ingestion/userUser identification
POST/api/ingestion/user/authAuthenticated user linking
POST/api/ingestion/ip-infoIP metadata
POST/api/ingestion/logsConsole log forwarding
POST/api/ingestion/networkNetwork 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):

next.config.js
/** @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:

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.

worker.js
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

nginx.conf
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:

  1. Rules → Origin Rules → Create rule.
  2. Match: URI Path starts with /hb/.
  3. Action: override the Host Header to ingest.humanbehavior.co and Resolved Address to ingest.humanbehavior.co.
  4. Add a URL Rewrite rule that strips the /hb prefix: Rewrite path to http.request.uri.path | replace | /hb(/.*) → $1.

Caddy

Caddyfile
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

  1. Deploy the proxy change.
  2. Update the SDK ingestionUrl and deploy the frontend.
  3. Open your site in a browser, open DevTools → Network, and filter by your domain (e.g. yourdomain.com/hb).
  4. You should see POST requests to /hb/api/ingestion/events, /hb/api/ingestion/init, etc., all returning 200.
  5. Enable an ad blocker and reload. The requests should still succeed — no entries should show blocked or ERR_BLOCKED_BY_CLIENT.
  6. 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.