# Serve analytics from your own domain.

> Relay the Virent browser script and events through your own domain under /_vr, with the headers Virent needs, for Next.js, nginx, Cloudflare Workers and other reverse proxies.

Canonical: https://stage.virent.app/docs/installation/first-party
Last updated: 2026-10-26

Ad blockers and privacy tools block known third-party analytics hosts, which silently drops visits. Relaying the script and events through your domain recovers most of them.

## Two options

| Option | Where | How Virent trusts the visitor's network |
| --- | --- | --- |
| Relay (recommended) | Next.js `proxy.ts`, nginx, a Cloudflare Worker or any reverse proxy | Forwarded headers, authenticated with the website's server secret |
| SDK route | A Next.js route handler with `createVirentAnalyticsProxy` (`/vt/*`) | The same headers and secret, set by the SDK |

Each [framework guide](/docs#installation) has a "First-party (recommended)" section with copy-paste code, and the dashboard's **Connect analytics** dialog has the same snippets under **Install manually** → **First-party (recommended)**.

## Relay contract

- Relay only two paths under `/_vr` on your domain: `/_vr/js/script.js` to `https://app.virent.app/js/script.js`, and `/_vr/v1/*` to `https://app.virent.app/v1/*`.
- Forward only the `accept-language`, `content-type`, `origin` and `user-agent` request headers.
- Add `x-virent-forwarded-for` with the visitor's IP as your relay sees it, and `x-virent-forwarded-country` with the ISO country code when your host provides it.
- Add `x-virent-proxy-key` with your website's server secret (`vha_sk_…`). Virent ignores the forwarded headers without it, and refuses a secret that belongs to another website. Keep the secret in your relay's configuration or environment, never in browser code.
- Never forward cookies or authorization headers.

Then load the script from your domain:

```html
<script defer src="/_vr/js/script.js" data-api="/_vr" data-write-key="vha_pk_..."></script>
```

With the browser SDK, pass `endpoint: "/_vr/v1/ingest/batch"`, `identifyEndpoint: "/_vr/v1/identify"` and `goalEndpoint: "/_vr/v1/track/goal"` to `initVirent`. SDK 0.3.1 does not derive the identify and goal URLs from a relative `endpoint`.

## Why plain rewrites are not enough

Without the forwarded headers and the secret, every visit would arrive with your relay's IP and location: all visitors would look like one person in one country, and they would share one visitor's rate limit. A `rewrites()` entry in `next.config.js` or `vercel.json` can't add request headers, so on Next.js the relay is a rewrite in `proxy.ts`.

## Verify

1. Open your site: With the browser's network panel open.
2. Check the requests: `/_vr/js/script.js` loads from your domain, and pageviews post to `/_vr/v1/ingest/batch`.
3. Check the dashboard: Visits arrive with the right countries, not your server's.
