# Next.js

> Set up cookieless analytics in Next.js App Router or Pages Router, verify your first pageview and event, and replace an existing tracker without duplicate events.


import { Card, Cards } from "@/components/docs";

Databuddy works with both the App Router and Pages Router. Add it once near the root of your app; page views and client-side route changes are tracked automatically.

Start with pageviews and one custom event, then use the same data for goals and funnels. The Free plan includes 10,000 events per month; error tracking starts on Hobby. See [current plans and limits](/pricing).

## Before you start

1. [Create a free account](https://app.databuddy.cc/register) and add your website in Databuddy.
2. Copy that website's Client ID from its tracking setup. This is a public identifier; keep server API keys out of browser code.
3. Add the Client ID to `.env.local` at your Next.js project root, then restart your dev server:

```bash
NEXT_PUBLIC_DATABUDDY_CLIENT_ID=your-client-id
```

## Install

```bash
bun add @databuddy/sdk
```

You can also install with npm or yarn:

```bash
npm install @databuddy/sdk
yarn add @databuddy/sdk
```

## App Router

Add `<Databuddy />` to `app/layout.tsx`:

```tsx
import { Databuddy } from "@databuddy/sdk/react";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <Databuddy
          clientId={process.env.NEXT_PUBLIC_DATABUDDY_CLIENT_ID!}
        />
        {children}
      </body>
    </html>
  );
}
```

The SDK's React entry point includes the client boundary, so your root layout can stay a Server Component. Custom event handlers belong in a Client Component, as shown below.

## Pages Router

Add `<Databuddy />` to `pages/_app.tsx`:

```tsx
import { Databuddy } from "@databuddy/sdk/react";
import type { AppProps } from "next/app";

export default function MyApp({ Component, pageProps }: AppProps) {
  return (
    <>
      <Databuddy
        clientId={process.env.NEXT_PUBLIC_DATABUDDY_CLIENT_ID!}
      />
      <Component {...pageProps} />
    </>
  );
}
```

Databuddy sends the first page view when it loads and listens for route changes. Do not add your own `router.events` or `usePathname` screen-view tracking unless you intentionally disabled Databuddy's automatic route tracking.

## Script Tag Setup

If you prefer not to use the React component, add the script in `pages/_document.tsx`:

```tsx
import { Head, Html, Main, NextScript } from "next/document";

export default function Document() {
  return (
    <Html lang="en">
      <Head>
        <script
          async
          crossOrigin="anonymous"
          data-client-id={process.env.NEXT_PUBLIC_DATABUDDY_CLIENT_ID}
          src="https://cdn.databuddy.cc/databuddy.js"
        />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}
```

Use either the React component or the script tag, not both.

## Optional errors and Web Vitals

Add `trackWebVitals` to the React component to collect performance measurements. Add `trackErrors` if your plan includes error tracking. Both are off by default, and the collected measurements count toward your event allowance.

```tsx
<Databuddy
  clientId={process.env.NEXT_PUBLIC_DATABUDDY_CLIENT_ID!}
  trackWebVitals
  trackErrors
/>
```

For the script tag, the equivalent attributes are `data-track-web-vitals` and `data-track-errors`.

## Track Custom Events

Use the SDK helper from client components:

```tsx
"use client";

import { track } from "@databuddy/sdk";

export function SubscribeButton() {
  return (
    <button
      onClick={() =>
        track("subscribe_clicked", {
          location: "header",
        })
      }
      type="button"
    >
      Subscribe
    </button>
  );
}
```

This records a click, not a completed subscription. Record outcomes such as account creation or payment after the backend confirms success, using the [Node SDK](/docs/sdk/node). Send each completed outcome from one place so a browser call and server call do not double-count it.

Use stable event names and small properties such as the button location. Do not send emails, passwords, tokens, or entire form values.

## Verify your first events

Verify on your deployed site. For a local test, the standard tracker skips localhost: temporarily add `debug` to `<Databuddy />` to load the debug bundle, or use `https://cdn.databuddy.cc/databuddy-debug.js` in your script tag. Use a separate Databuddy website and Client ID for local test data, and remove debug mode before deploying.

1. Open your site and use a client-side link to visit a second page.
2. In the browser Network tab, confirm the Databuddy script loads from `cdn.databuddy.cc` and requests reach `basket.databuddy.cc`. Events are batched, so allow a few seconds for delivery.
3. Open that website in Databuddy and check for your two pageviews. Check the same date range and website as your test.
4. Trigger the custom event once and confirm its name appears on the Events page. A successful pageview does not prove your custom event is instrumented.

[Databuddy DevTools](/docs/sdk/devtools) can help inspect the tracker and custom events while you develop.

## Production Setup

Add `NEXT_PUBLIC_DATABUDDY_CLIENT_ID` to your deployment provider before building. On Vercel, choose the deployment environments that should collect data. Next.js embeds public environment variables at build time, so rebuild and redeploy after changing the Client ID.

To avoid test data, disable tracking outside production:

```tsx
<Databuddy
  clientId={process.env.NEXT_PUBLIC_DATABUDDY_CLIENT_ID!}
  disabled={process.env.NODE_ENV !== "production"}
/>
```

`NODE_ENV` is also `production` for many preview deployments. If previews should stay out of production analytics, use your deployment provider's environment indicator for `disabled`, or give previews a separate Databuddy website and Client ID.

## Replace an existing tracker

1. Install Databuddy once and verify pageviews and one important event before removing the old tracker.
2. Write down what each existing conversion means. Keep a button click separate from a completed signup, and send the completed event only after success.
3. Recreate the goals and funnels you need in Databuddy. Confirm that their paths and event names match the events you just verified.
4. Remove the old provider's script and manual route listeners when you are ready to switch. Remove any duplicate Databuddy script added through a tag manager or another layout.

If you briefly run both providers, compare the same dates and definitions. Different session, consent, and bot-filtering rules can produce different totals; an exact count match is not a setup requirement.

## Troubleshooting

**No data in the dashboard**

1. Confirm `NEXT_PUBLIC_DATABUDDY_CLIENT_ID` is set and matches the website in Databuddy.
2. Check the browser Network tab for requests to `basket.databuddy.cc`.
3. Make sure the component or script is included only once.
4. If `disabled` is set, confirm it is `false` in the environment you are testing.
5. Check your site's Content Security Policy and blockers. Allow scripts from `https://cdn.databuddy.cc` and connections to `https://basket.databuddy.cc`.
6. For local tests, use the debug bundle as described above. For deployment tests, rebuild after setting the public Client ID.

**Pageviews work, but an outcome is missing**

Confirm the event call runs after the actual outcome, uses the same website, and is not skipped by an error or redirect. If you send it from a serverless route handler, flush the Node SDK before the handler exits. Check the [custom event helpers](/docs/sdk/tracker) and [server event setup](/docs/sdk/node).

## Related

<Cards>
  <Card title="React SDK" href="/docs/sdk/react">
    React component props, hooks, and examples.
  </Card>
  <Card title="SDK Configuration" href="/docs/sdk/configuration">
    All tracking options across supported SDKs.
  </Card>
  <Card title="Tracker Helpers" href="/docs/sdk/tracker">
    Helper methods for custom events and identity.
  </Card>
  <Card title="Node SDK" href="/docs/sdk/node">
    Server-side event tracking for API routes and jobs.
  </Card>
</Cards>
