Hero
Back to all guides

How to add analytics to Next.js

Add privacy-first analytics to your Next.js app in under 5 minutes with OpenPanel.

OpenPanel Team

12/15/2025

Beginner
8 min

How to add analytics to Next.js

This guide walks you through adding OpenPanel to a Next.js application. By the end, you'll have automatic page view tracking, custom event tracking, and user identification working in your app.

OpenPanel works with both the App Router and Pages Router. It uses cookieless tracking by default, so you won't need cookie consent banners for basic analytics. If you're looking for a privacy-focused alternative to Mixpanel or Google Analytics, this is a straightforward setup.

Prerequisites

  • A Next.js project (App Router or Pages Router)
  • An OpenPanel account
  • Your Client ID from the OpenPanel dashboard

Install the SDK

Start by installing the OpenPanel Next.js package. This SDK is a thin wrapper around the core OpenPanel library with Next.js-specific components for easier integration.

npm install @openpanel/nextjs

If you prefer pnpm or yarn, those work too.

Add OpenPanel to your layout

Before tracking anything, you need to add the OpenPanelComponent to your app's root. This loads the tracking script and makes the SDK available throughout your application.

For App Router projects, add the component to your root layout file. The component should be placed inside the body tag, and setting trackScreenViews to true enables automatic page view tracking as users navigate your app.

// app/layout.tsx
import { OpenPanelComponent } from '@openpanel/nextjs';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <OpenPanelComponent
          clientId="your-client-id"
          trackScreenViews={true}
        />
        {children}
      </body>
    </html>
  );
}

For Pages Router projects, the setup is nearly identical. Add the component to your _app.tsx file instead.

// pages/_app.tsx
import { OpenPanelComponent } from '@openpanel/nextjs';
import type { AppProps } from 'next/app';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <OpenPanelComponent
        clientId="your-client-id"
        trackScreenViews={true}
      />
      <Component {...pageProps} />
    </>
  );
}

You can also enable trackOutgoingLinks to automatically track when users click external links, or trackAttributes to track elements with data attributes.

Track custom events

Page views only tell part of the story. To understand how users interact with your product, you'll want to track custom events like button clicks, form submissions, or feature usage.

In client components, use the useOpenPanel hook. This gives you access to the tracking methods anywhere in your component tree.

'use client';

import { useOpenPanel } from '@openpanel/nextjs';

export function SignupButton() {
  const op = useOpenPanel();

  return (
    <button
      type="button"
      onClick={() => op.track('signup_clicked', { location: 'header' })}
    >
      Sign up
    </button>
  );
}

For server-side tracking, you'll need to create an SDK instance with your client secret. This is useful for tracking events in API routes, webhooks, or server actions.

// lib/op.ts
import { OpenPanel } from '@openpanel/nextjs';

export const op = new OpenPanel({
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
});

Never expose your client secret on the client side. Keep it in server-only code.

With the instance created, you can track events from anywhere on the server.

// app/api/webhook/route.ts
import { op } from '@/lib/op';

export async function POST(request: Request) {
  const data = await request.json();

  op.track('webhook_received', {
    source: data.source,
    event_type: data.type,
  });

  return Response.json({ success: true });
}

If you're running on Vercel or another serverless platform, wrap your tracking calls with waitUntil to ensure events are sent before the function terminates.

Identify users

Anonymous tracking is useful, but identifying users unlocks more valuable insights. You can track behavior across sessions, segment users by properties, and build cohort analyses.

In client components, call identify after a user logs in or when you have their information available.

'use client';

import { useOpenPanel } from '@openpanel/nextjs';
import { useEffect } from 'react';

export function UserProfile({ user }) {
  const op = useOpenPanel();

  useEffect(() => {
    op.identify({
      profileId: user.id,
      firstName: user.firstName,
      lastName: user.lastName,
      email: user.email,
      properties: {
        plan: user.plan,
      },
    });
  }, [user]);

  return <div>Welcome, {user.firstName}!</div>;
}

If you already have user data on the server, the IdentifyComponent is a cleaner approach. It renders nothing visible but handles identification when the component mounts.

// app/dashboard/layout.tsx
import { IdentifyComponent } from '@openpanel/nextjs';

export default async function DashboardLayout({ children }) {
  const user = await getCurrentUser();

  return (
    <>
      <IdentifyComponent
        profileId={user.id}
        firstName={user.firstName}
        lastName={user.lastName}
        email={user.email}
        properties={{
          plan: user.plan,
        }}
      />
      {children}
    </>
  );
}

Verify your setup

Open your Next.js app in the browser and navigate between a few pages. Then open your OpenPanel dashboard and check the real-time view. You should see page view events appearing within seconds.

If events aren't showing up, check the browser console for errors. The most common issues are an incorrect client ID or ad blockers intercepting requests. You can solve the ad blocker problem by proxying events through your own server.

To set up a proxy, create a catch-all API route that forwards requests to OpenPanel.

// app/api/[...op]/route.ts
import { createRouteHandler } from '@openpanel/nextjs/server';

export const { GET, POST } = createRouteHandler();

Then update your OpenPanelComponent to use the proxy endpoint.

<OpenPanelComponent
  apiUrl="/api/op"
  cdnUrl="/api/op/op1.js"
  clientId="your-client-id"
  trackScreenViews={true}
/>

This routes all tracking requests through your domain, making them invisible to browser extensions that block third-party analytics.

Next steps

The Next.js SDK reference covers additional features like global properties, event filtering, and incrementing user properties. If you're interested in understanding how OpenPanel handles privacy, read our article on cookieless analytics.

Loved by builders everywhere

From indie hackers to global teams, OpenPanel helps people understand their users effortlessly.

  • Steven Tey
    Steven Tey
    @steventey

    Open-source Mixpanel alternative just dropped → http://git.new/openpanel

    It combines the power of Mixpanel + the ease of use of @PlausibleHQ into a fully open-source product.

    Built by @CarlLindesvard and it’s already tracking 750K+ events 🤩

  • Pontus Abrahamsson - oss/acc
    Pontus Abrahamsson - oss/acc
    @pontusab

    Thanks, OpenPanel is a beast, love it!

  • Piotr Kulpinski
    Piotr Kulpinski
    @piotrkulpinski

    The Overview tab in OpenPanel is great. It has everything I need from my analytics: the stats, the graph, traffic sources, locations, devices, etc.

    The UI is beautiful ✨ Clean, modern look, very pleasing to the eye.

  • greg hodson 🍜
    greg hodson 🍜
    @h0dson

    i second this, openpanel is killing it

  • Jacob 🍀 Build in Public
    Jacob 🍀 Build in Public
    @javayhuwx

    🤯 wow, it's amazing! Just integrate @OpenPanelDev into http://indiehackers.site last night, and now I can see visitors coming from all round the world.

    OpenPanel has a more beautiful UI and much more powerful features when compared to Umami.

    #buildinpublic #indiehackers

  • Lee
    Lee
    @DutchEngIishman

    Day two of marketing.

    I like this upward trend..

    P.S. website went live on Sunday

    P.P.S. Openpanel by @CarlLindesvard is awesome.

Ready to understand your users better?
Start tracking in minutes

Join thousands of companies using OpenPanel. Free 30-day trial, no credit card required. Self-host for free or use our cloud.

Get started now