A preview URL is a real browser visit
A pull request preview can look like production to an analytics tracker. If both deployments load the same site ID, a teammate refreshing a feature branch may create page views, sessions, and goal events in the live website's reports. A test checkout or signup can also look like a real conversion if it reaches the same configured success signal.
Decide first whether preview traffic should be collected at all. For routine review, the safest default is to omit the production tracker from preview and local builds. If you need end-to-end analytics testing, route it to a separate WhoVisited website so its sessions and goals are reported separately.
WhoVisited validates the page origin against the website's allowlist and associates events with a site ID. A random preview hostname is a different origin from your production domain. Origin permission and report separation are two separate choices: allowing a preview host to send events to the production site does not make those events disappear from production reports.
Conditionally render the production tracker in Next.js
In the App Router, a layout is a Server Component unless you mark it with `use client`. You can decide whether to render the tracker on the server using the deployment environment. On Vercel, `VERCEL_ENV` is `production`, `preview`, or `development`; enable access to Vercel system environment variables for the deployment.
import Script from "next/script";
const siteId =
process.env.VERCEL_ENV === "production"
? process.env.WHOVISITED_SITE_ID
: undefined;
export default function RootLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
return (
<html lang="en">
<body>
{siteId ? (
<Script
src="https://whovisited.net/tracker.js"
data-site-id={siteId}
strategy="afterInteractive"
/>
) : null}
{children}
</body>
</html>
);
}In Vercel project settings, make `WHOVISITED_SITE_ID` available only in the Production environment. The site ID is visible in rendered HTML because the browser needs it; it is an identifier, not an authentication secret. Keeping it out of Preview still makes the rendering decision explicit and avoids accidentally copying the production snippet into a preview-only component.
For deployments outside Vercel, use a server-side environment variable your host sets separately for production and preview. Do not use `NODE_ENV === "production"` as the deployment test: production-optimized builds also run for preview deployments. If your project uses a statically exported layout, check the built HTML for both environment targets because the condition is evaluated during the build.
If you need tracked previews, isolate them
For a real collection test, create a separate WhoVisited website for a stable staging origin you control, such as `https://staging.example.com`, and configure the staging deployment to use that site's ID. Do not allowlist every generated preview URL or add a broad wildcard: WhoVisited accepts explicit origins, and the main HTTPS host also matches its `www` version. Its current workspace limit is two websites, so use the second slot only when a distinct staging report is worth it.
A separate site keeps the events in different site reports, but it does not create a separate workspace quota. Accepted events from both sites contribute to the workspace's monthly event usage. Keep test runs short and intentional, and remove or disable the staging installation when the test is over.
If a stable staging host is not available, leave analytics disabled on generated previews and use your app's ordinary tests for UI behavior. WhoVisited's in-product sandbox can send real test activity for the selected website; do not use it as a harmless mock, because those events appear in that site's data.
Verify the production boundary
- Open the deployed production page and inspect its HTML or Network panel. Confirm `tracker.js` is requested and that it uses the production site's ID.
- Open a Preview deployment in a fresh private window. Confirm there is no WhoVisited tracker request and no bootstrap or event request.
- If staging collection is intentional, confirm the preview sends events to the staging site ID and that its exact HTTPS origin appears in that site's allowlist.
- Perform one controlled test action, then check the matching website's Visitors or goal report. Verify the event appears in the intended site only.
- Repeat after changing the build configuration. Preview protection is based on the environment used for that deployment; test the actual deployed artifact, not only a local development server.
Consent rules and browser privacy signals still apply in every environment. A missing request may be caused by consent, Global Privacy Control, Do Not Track, a blocker, or CSP; it does not by itself prove your environment condition worked. Inspect the rendered page and Network panel together.
Keep test results out of product conclusions
Preview deployments can require authentication, use different origins, and connect to test backends. A staging conversion validates your measurement wiring; it is not a customer conversion and should not be combined with production funnel rates. A separate site also shares workspace-level event quota, so isolation improves interpretation rather than making test traffic free.
Next.js documents the [Script component](https://nextjs.org/docs/app/api-reference/components/script) and explains that layouts are Server Components by default. Vercel documents [system environment variables](https://vercel.com/docs/environment-variables/system-environment-variables), including `VERCEL_ENV` and the option to expose them to deployments. For origin failures, see the WhoVisited guide to [debugging a tracker that loads but sends no events](/blog/analytics-tracker-loads-but-no-events). The practical rule is simple: disable previews by default, and collect test events on a deliberately separate site when you truly need them.