Install — Web
Install AnyReplay in Next.js
Record a Next.js App Router site with AnyReplay: the next/script layout snippet, or a client component using the npm package that waits for consent.
There are two ways to add AnyReplay to a Next.js app using the App Router. The script version is what the dashboard's Next.js tab gives you and needs no dependency. The client component version uses the npm package and fits naturally with a consent banner. Both record route changes automatically. Masking and consent tips for this stack are collected in session replay for Next.js.
Option 1: next/script in the root layout
import Script from 'next/script';
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Script id="anyreplay-init" strategy="afterInteractive">{`
window.anyreplay = window.anyreplay || function () {
(window.anyreplay.q = window.anyreplay.q || []).push(arguments);
};
anyreplay('init', {
projectKey: 'YOUR_PROJECT_KEY',
ingestUrl: 'https://in.anyreplay.com',
// Stop recording after this many sessions in a calendar month.
// maxSessionsPerMonth: 10000,
// Form fields are masked: what visitors type replays as asterisks.
// Passwords, one-time codes and card fields are masked either way.
// Uncomment the first line to record what visitors type, or the
// second to hide rich-text editors too.
// maskAllInputs: false,
// maskAllTyping: true
});
`}</Script>
<Script src="https://cdn.anyreplay.com/v1/ar.min.js?k=YOUR_PROJECT_KEY" strategy="afterInteractive" />
</body>
</html>
);
}The first Script defines the queue and calls init; the second loads the recorder. Both use strategy="afterInteractive", so they run once the page is interactive and survive client-side navigation without running again.
Option 2: a client component with consent
npm install @anyreplay/browserpnpm add @anyreplay/browseryarn add @anyreplay/browser'use client';
import { useEffect } from 'react';
import type { RecorderHandle } from '@anyreplay/browser';
let starting: Promise<RecorderHandle> | null = null;
/** Creates the recorder once per page load, however often it is asked for. */
export function getRecorder(): Promise<RecorderHandle> {
starting ??= import('@anyreplay/browser').then(({ createRecorder }) =>
createRecorder({
projectKey: process.env.NEXT_PUBLIC_ANYREPLAY_KEY!,
requireConsent: true,
}),
);
return starting;
}
/** Call from your consent banner. */
export async function setRecordingConsent(granted: boolean): Promise<void> {
(await getRecorder()).consent(granted);
}
export function AnyReplayRecorder(): null {
useEffect(() => {
void getRecorder();
}, []);
return null;
}import { AnyReplayRecorder } from './anyreplay';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<AnyReplayRecorder />
</body>
</html>
);
}Three details make this safe. The dynamic import() inside an effect keeps the recorder out of server rendering. The module-level promise means React Strict Mode's double effects in development — or the component mounting twice — still create exactly one recorder. And requireConsent: true records nothing until your banner calls setRecordingConsent(true).
import { setRecordingConsent } from '@/app/anyreplay';
<button onClick={() => { saveChoice('accepted'); void setRecordingConsent(true); }}>Accept</button>Consent is remembered by your site, not by AnyReplay: on each full page load, call setRecordingConsent(true) again if the visitor has already accepted. More patterns are in consent.
Environment variables
The project key is public, so exposing it as a NEXT_PUBLIC_ variable is fine — the name above is only a suggestion. Values prefixed with NEXT_PUBLIC_ are inlined at build time, so rebuild after changing them.
Route changes and the Pages Router
Next.js navigates with the History API, so every client-side route change is recorded as a page view with a $navigate marker — no router events needed. With the Pages Router, put the same Script tags in pages/_app.tsx, or mount the client component there. See single-page apps for what counts as a navigation.