[Docs](https://userjourney.dev/docs/) · Install

# Add UserJourney to a Next.js app

For the App Router. With the Pages Router, the snippet goes in `pages/_app.tsx` the same way.

## 1. The snippet

In your root layout, with `next/script`. Your key is on the Setup page of the dashboard.

```
// app/layout.tsx
import Script from "next/script";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script src="https://userjourney.dev/uj.js" data-key="pk_…" strategy="afterInteractive" />
      </body>
    </html>
  );
}
```

Route changes count as page views by themselves.

## 2. A small helper

So you can call it from your components, even before the script has loaded:

```
// lib/uj.ts
type Method = "identify" | "reset" | "step" | "activated" | "track" | "search";

/** Calls UserJourney's snippet; before it has loaded, the call waits in its queue. */
export function uj(method: Method, ...args: unknown[]) {
  if (typeof window === "undefined") return;
  const w = window as unknown as { uj?: Record<string, unknown> & { q?: unknown[][] } };
  const fn = w.uj?.[method];
  if (typeof fn === "function") fn(...args);
  else ((w.uj ??= { q: [] }).q ??= []).push([method, ...args]);
}
```

## 3. Identify

Wherever your app knows who is signed in, for example a client component in your app's layout. The first call for someone is their sign-up.

```
// app/(app)/identify.tsx
"use client";
import { useEffect } from "react";
import { uj } from "@/lib/uj";

export function Identify({ user }: { user: { id: string; email: string; name?: string } | null }) {
  useEffect(() => {
    if (user) uj("identify", String(user.id), { email: user.email, name: user.name });
  }, [user?.id]);
  return null;
}
```

And when they sign out, before your auth library's sign-out:

```
uj("reset")
```

## Onboarding steps

Pages under `/onboarding/<step>`, `/setup/<step>`, `/welcome/<step>` or `/get-started/<step>` count as steps by themselves. Otherwise, one call when each step is done, and optionally the moment they first get value:

```
uj("step", "connect_repo")
uj("activated")
```

## Payments

Connect [Stripe](https://userjourney.dev/docs/stripe/) or [Paddle](https://userjourney.dev/docs/paddle/) in the dashboard, and each payment, trial and cancellation lands on the person who made it.

## Check it works

Open your site in a private window: you show up on Traffic within a few seconds. Sign up with a test account and it appears on People, with the visit that brought it. Your own team is left out once you sign in; for your visits before that, open any page once with `?uj=off` ([more](https://userjourney.dev/docs/#leave-out)).

If your app sends a Content Security Policy, add `https://userjourney.dev` to `script-src` and `connect-src`.

[Everything else is in the docs →](https://userjourney.dev/docs/)

## See where your users go

Free for your first 250 users. One script and one line of code.

[Start for free](https://userjourney.dev/app)[Read the quickstart](https://userjourney.dev/docs/)
