App Router
Usenext/script with strategy="afterInteractive" in your root layout. This loads the snippet after the page is interactive without blocking hydration.
app/layout.tsx
.env.local:
.env.local
Calling identify (App Router)
Create a client component that reads the authenticated user and callsidentify(). Server Components cannot access window — the identify call must happen in a "use client" component.
components/ZenstepIdentify.tsx
app/(dashboard)/layout.tsx
Pages Router
Add the snippet in_app.tsx:
pages/_app.tsx
TypeScript types
types/global.d.ts
Middleware considerations
If you use Next.js middleware for auth redirects, the snippet is client-side only and is not affected by middleware. Zenstep flows are evaluated in the browser after the page loads.When using Next.js Middleware edge runtime for session management, ensure
NEXT_PUBLIC_ZENSTEP_KEY is set on the client-side environment (prefixed with
NEXT_PUBLIC_). Middleware cannot read NEXT_PUBLIC_ variables at the edge —
use the process.env reference only in client components.