---
title: "Next.js"
description: "Keep initialization in a small Client Component and render it from the root layout. The rest of the layout can remain a Server Component."
documentation: "https://tracwell.app/docs/frameworks/nextjs"
markdown: "https://tracwell.app/docs/frameworks/nextjs.md"
---

# Next.js

> Keep initialization in a small Client Component and render it from the root layout. The rest of the layout can remain a Server Component.

## Initialize Tracwell

```ts
"use client";

import { useEffect } from "react";
import { createTracwell, type TracwellClient } from "tracwell";

let analytics: TracwellClient | undefined;

export function TracwellAnalytics() {
  useEffect(() => {
    analytics ??= createTracwell({
      collectionMode: "product",
      projectKey: "tw_live_...",
    });
  }, []);

  return null;
}

// Render <TracwellAnalytics /> once inside app/layout.tsx.
// Pages Router apps can render it from pages/_app.tsx instead.
```

Do not call page() from usePathname. Next.js link and router navigation update browser history, which the SDK already observes.

## Track an event

Keep the initialized client available to the component or service that owns the successful product outcome. Call `track()` only after that outcome completes.

```ts
const eventId = analytics.track("signup_completed", {
  plan: "starter",
  source: "pricing",
});

if (!eventId) {
  // Collection is blocked or the event did not pass validation.
}
```

See the [custom events guide](https://tracwell.app/docs/events.md) for naming, property limits, and verification.
