[OpenPanel](https://openpanel.dev/)

[OpenPanel](https://openpanel.dev/)

Search

⌘K

Documentation

Guides and references

Introduction

[What is OpenPanel?](https://openpanel.dev/docs)

Get started

[Install OpenPanel](https://openpanel.dev/docs/get-started/install-openpanel)
[Track Events](https://openpanel.dev/docs/get-started/track-events)
[Identify Users](https://openpanel.dev/docs/get-started/identify-users)
[Groups](https://openpanel.dev/docs/get-started/groups)

Tracking

[SDKs](https://openpanel.dev/docs/sdks)

[Script Tag](https://openpanel.dev/docs/sdks/script)
[Javascript (Web)](https://openpanel.dev/docs/sdks/web)
[Javascript (Node / Generic)](https://openpanel.dev/docs/sdks/javascript)
[Next.js](https://openpanel.dev/docs/sdks/nextjs)
[React](https://openpanel.dev/docs/sdks/react)
[Vue](https://openpanel.dev/docs/sdks/vue)
[Astro](https://openpanel.dev/docs/sdks/astro)
[Remix](https://openpanel.dev/docs/sdks/remix)
[Express](https://openpanel.dev/docs/sdks/express)
[Python](https://openpanel.dev/docs/sdks/python)
[Rust](https://openpanel.dev/docs/sdks/rust)
[Ruby](https://openpanel.dev/docs/sdks/ruby)
[Java](https://openpanel.dev/docs/sdks/java)
[React Native](https://openpanel.dev/docs/sdks/react-native)
[Swift](https://openpanel.dev/docs/sdks/swift)
[Kotlin / Android](https://openpanel.dev/docs/sdks/kotlin)
[Nuxt](https://openpanel.dev/docs/sdks/nuxt)

[How it works](https://openpanel.dev/docs/how-it-works)
[Session Replay](https://openpanel.dev/docs/session-replay)
[Consent management](https://openpanel.dev/docs/consent-management)
[Avoid adblockers with proxy](https://openpanel.dev/docs/adblockers)
[Revenue tracking](https://openpanel.dev/docs/revenue-tracking)

API

[Authentication](https://openpanel.dev/docs/api/authentication)
[Track](https://openpanel.dev/docs/api/track)
[Export](https://openpanel.dev/docs/api/export)
[Insights](https://openpanel.dev/docs/api/insights)

[Manage](https://openpanel.dev/docs/api/manage)

MCP

[MCP Server](https://openpanel.dev/docs/mcp)

Dashboard

[Understand the overview](https://openpanel.dev/docs/dashboard/understand-the-overview)
[How to set up notifications and integrations](https://openpanel.dev/docs/dashboard/notifications-and-integrations)

Self-hosting

[Get started](https://openpanel.dev/docs/self-hosting/self-hosting)
[Deploy with Docker Compose](https://openpanel.dev/docs/self-hosting/deploy-docker-compose)
[Deploy with Coolify](https://openpanel.dev/docs/self-hosting/deploy-coolify)
[Deploy with Dokploy](https://openpanel.dev/docs/self-hosting/deploy-dokploy)
[Deploy on Kubernetes](https://openpanel.dev/docs/self-hosting/deploy-kubernetes)
[Reverse proxy setup](https://openpanel.dev/docs/self-hosting/reverse-proxy)
[Environment Variables](https://openpanel.dev/docs/self-hosting/environment-variables)
[High volume setup](https://openpanel.dev/docs/self-hosting/high-volume)
[Latest Docker Images](https://openpanel.dev/docs/self-hosting/supporter-access-latest-docker-images)
[Changelog for self-hosting](https://openpanel.dev/docs/self-hosting/changelog)

Migration

[Beta to V1](https://openpanel.dev/docs/migration/beta-v1)
[Migration from v1 to v2](https://openpanel.dev/docs/migration/migrate-v1-to-v2)

Next.js

[SDKs](https://openpanel.dev/docs/sdks)

Next.js
=======

Looking for a step-by-step tutorial? Check out the [Next.js analytics guide](https://openpanel.dev/guides/nextjs-analytics)
.

[Good to know](https://openpanel.dev/docs/sdks/nextjs#good-to-know)

--------------------------------------------------------------------

Keep in mind that all tracking here happens on the client!

Read more about server side tracking in the [Server Side Tracking](https://openpanel.dev/docs/sdks/nextjs#track-server-events)
 section.

[Installation](https://openpanel.dev/docs/sdks/nextjs#installation)

--------------------------------------------------------------------

### [Install dependencies](https://openpanel.dev/docs/sdks/nextjs#install-dependencies)

    pnpm install @openpanel/nextjs

### [Initialize](https://openpanel.dev/docs/sdks/nextjs#initialize)

Add `OpenPanelComponent` to your root layout component.

    import { OpenPanelComponent } from '@openpanel/nextjs';
    
    export default function RootLayout({ children }) {
      return (
        <>
          <OpenPanelComponent
            clientId="your-client-id"
            trackScreenViews={true}
            // trackAttributes={true}
            // trackOutgoingLinks={true}
            // If you have a user id, you can pass it here to identify the user
            // profileId={'123'}
          />
          {children}
        </>
      )
    }

#### [Options](https://openpanel.dev/docs/sdks/nextjs#options)

##### Common options

*   `apiUrl` - The url of the openpanel API or your self-hosted instance
*   `clientId` - The client id of your application
*   `clientSecret` - The client secret of your application (**only required for server-side events**)
*   `filter` - A function that will be called before sending an event. If it returns false, the event will not be sent
*   `disabled` - If true, the library will not send any events

##### Web options

*   `trackScreenViews` - If true, the library will automatically track screen views (default: false)
*   `trackOutgoingLinks` - If true, the library will automatically track outgoing links (default: false)
*   `trackAttributes` - If true, you can trigger events by using html attributes (`<button type="button" data-track="your_event" />`) (default: false)
*   `sessionReplay` - Session replay configuration object (default: disabled). See [session replay docs](https://openpanel.dev/docs/session-replay)
     for full options.
    *   `enabled` - Enable session replay recording (default: false)
    *   `maskAllInputs` - Mask all input field values (default: true)
    *   `maskTextSelector` - CSS selector for text elements to mask (default: `[data-openpanel-replay-mask]`)
    *   `blockSelector` - CSS selector for elements to replace with a placeholder (default: `[data-openpanel-replay-block]`)
    *   `blockClass` - Class name that blocks elements from being recorded
    *   `ignoreSelector` - CSS selector for elements excluded from interaction tracking
    *   `flushIntervalMs` - How often (ms) recorded events are sent to the server (default: 10000)
    *   `maxEventsPerChunk` - Maximum events per payload chunk (default: 200)
    *   `maxPayloadBytes` - Maximum payload size in bytes (default: 1048576)
    *   `scriptUrl` - Custom URL for the replay script (script-tag builds only)

##### [NextJS options](https://openpanel.dev/docs/sdks/nextjs#nextjs-options)

*   `profileId` - If you have a user id, you can pass it here to identify the user
*   `cdnUrl` (deprecated) - The url to the OpenPanel SDK (default: `https://openpanel.dev/op1.js`)
*   `scriptUrl` - The url to the OpenPanel SDK (default: `https://openpanel.dev/op1.js`)
*   `filter` - This is a function that will be called before tracking an event. If it returns false the event will not be tracked. [Read more](https://openpanel.dev/docs/sdks/nextjs#filter)
    
*   `globalProperties` - This is an object of properties that will be sent with every event.

##### [`filter`](https://openpanel.dev/docs/sdks/nextjs#filter)

This options needs to be a stringified function and cannot access any variables outside of the function.

    <OpenPanelComponent
      clientId="your-client-id"
      filter={`
        function filter(event) {
          return event.name !== 'my_event';
        }
      `}
    />

To take advantage of typescript you can do the following. _Note `toString`_

    import { type TrackHandlerPayload } from '@openpanel/nextjs';
    
    const opFilter = ((event: TrackHandlerPayload) => {
      return event.type === 'track' && event.payload.name === 'my_event';
    }).toString();
    
    <OpenPanelComponent
      clientId="your-client-id"
      filter={opFilter}
    />

[Usage](https://openpanel.dev/docs/sdks/nextjs#usage)

------------------------------------------------------

### [Client components](https://openpanel.dev/docs/sdks/nextjs#client-components)

For client components you can just use the `useOpenPanel` hook.

    import { useOpenPanel } from '@openpanel/nextjs';
    
    function YourComponent() {
      const op = useOpenPanel();
    
      return <button type="button" onClick={() => op.track('my_event', { foo: 'bar' })}>Trigger event</button>
    }

### [Server components](https://openpanel.dev/docs/sdks/nextjs#server-components)

Since you can't use hooks in server components, you need to create an instance of the SDK. This is exported from `@openpanel/nextjs`.

Remember, your client secret is exposed here so do not use this on client side.

utils/op.ts

    import { OpenPanel } from '@openpanel/nextjs';
    
    export const op = new OpenPanel({
      clientId: 'your-client-id',
      clientSecret: 'your-client-secret',
    });
    
    // Now you can use `op` to track events
    op.track('my_event', { foo: 'bar' });

Refer to the [Javascript SDK](https://openpanel.dev/docs/sdks/javascript#usage)
 for usage instructions.

### [Tracking Events](https://openpanel.dev/docs/sdks/nextjs#tracking-events)

You can track events with two different methods: by calling the `op.track( directly or by adding` data-track\` attributes to your HTML elements.

index.ts

    useOpenPanel().track('my_event', { foo: 'bar' });

### [Identifying Users](https://openpanel.dev/docs/sdks/nextjs#identifying-users)

To identify a user, call the \`op.identify( method with a unique identifier.

index.js

    useOpenPanel().identify({
      profileId: '123', // Required
      firstName: 'Joe',
      lastName: 'Doe',
      email: 'joe@doe.com',
      properties: {
        tier: 'premium',
      },
    });

#### [For server components](https://openpanel.dev/docs/sdks/nextjs#for-server-components)

For server components you can use the `IdentifyComponent` component which is exported from `@openpanel/nextjs`.

> This component is great if you have the user data available on the server side.

app/nested/layout.tsx

    import { IdentifyComponent } from '@openpanel/nextjs';
    
    export default function Layout({ children }) {
      const user = await getCurrentUser()
    
      return (
        <>
          <IdentifyComponent
            profileId={user.id}
            firstName={user.firstName}
            lastName={user.lastName}
            email={user.email}
            properties={{
              tier: 'premium',
            }}
          />
          {children}
        </>
      )
    }

### [Setting Global Properties](https://openpanel.dev/docs/sdks/nextjs#setting-global-properties)

To set properties that will be sent with every event:

index.js

    useOpenPanel().setGlobalProperties({
      app_version: '1.0.2',
      environment: 'production',
    });

### [Incrementing Properties](https://openpanel.dev/docs/sdks/nextjs#incrementing-properties)

To increment a numeric property on a user profile.

*   `value` is the amount to increment the property by. If not provided, the property will be incremented by 1.

index.js

    useOpenPanel().increment({
      profileId: '1',
      property: 'visits',
      value: 1 // optional
    });

### [Decrementing Properties](https://openpanel.dev/docs/sdks/nextjs#decrementing-properties)

To decrement a numeric property on a user profile.

*   `value` is the amount to decrement the property by. If not provided, the property will be decremented by 1.

index.js

    useOpenPanel().decrement({
      profileId: '1',
      property: 'visits',
      value: 1 // optional
    });

### [Working with Groups](https://openpanel.dev/docs/sdks/nextjs#working-with-groups)

Groups let you track analytics at the account or company level. See the [Groups guide](https://openpanel.dev/docs/get-started/groups)
 for the full walkthrough.

**Create or update a group:**

app/login/page.tsx

    useOpenPanel().upsertGroup({
      id: 'org_acme',
      type: 'company',
      name: 'Acme Inc',
      properties: { plan: 'enterprise' },
    });

**Assign the current user to a group** (call after `identify`):

app/login/page.tsx

    useOpenPanel().setGroup('org_acme');

Once set, all subsequent `track()` calls will automatically include the group IDs.

### [Clearing User Data](https://openpanel.dev/docs/sdks/nextjs#clearing-user-data)

To clear the current user's data (including groups):

index.js

    useOpenPanel().clear()

[Server side](https://openpanel.dev/docs/sdks/nextjs#server-side)

------------------------------------------------------------------

If you want to track server-side events, you should create an instance of our Javascript SDK. It's exported from `@openpanel/nextjs`

When using server events it's important that you use a secret to authenticate the request. This is to prevent unauthorized requests since we cannot use cors headers.

You can use the same clientId but you should pass the associated client secret to the SDK.

    import { OpenpanelSdk } from '@openpanel/nextjs';
    
    const opServer = new OpenpanelSdk({
      clientId: '{YOUR_CLIENT_ID}',
      clientSecret: '{YOUR_CLIENT_SECRET}',
    });
    
    opServer.event('my_server_event', { ok: '✅' });
    
    // Pass `profileId` to track events for a specific user
    opServer.event('my_server_event', { profileId: '123', ok: '✅' });

### [Serverless & Vercel](https://openpanel.dev/docs/sdks/nextjs#serverless--vercel)

If you log events in a serverless environment like Vercel, you can use `waitUntil` to ensure the event is logged before the function is done.

Otherwise your function might close before the event is logged. Read more about it [here](https://vercel.com/docs/functions/functions-api-reference#waituntil)
.

    import { waitUntil } from '@vercel/functions';
    import { opServer } from 'path/to/your-sdk-instance';
    
    export function GET() {
      // Returns a response immediately while keeping the function alive
      waitUntil(opServer.event('my_server_event', { foo: 'bar' }));
      return new Response(`You're event has been logged!`);
    }

### [Proxy events](https://openpanel.dev/docs/sdks/nextjs#proxy-events)

With `createRouteHandler` you can proxy your events through your server, this will ensure all events are tracked since there is a lot of adblockers that block requests to third party domains. The handler automatically routes requests based on the path, supporting both API endpoints (like `/track` and `/track/device-id`) and the tracking script (`/op1.js`).

/app/api/\[...op\]/route.ts

    import { createRouteHandler } from '@openpanel/nextjs/server';
    
    export const { GET, POST } = createRouteHandler();

Remember to change the `apiUrl` and `scriptUrl` in the `OpenPanelComponent` to your own server.

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

[Javascript (Node / Generic)\
\
The OpenPanel Web SDK allows you to track user behavior on your website using a simple script tag. This guide provides instructions for installing and using the Web SDK in your project.](https://openpanel.dev/docs/sdks/javascript)
[React\
\
Next Page](https://openpanel.dev/docs/sdks/react)

### On this page

[Good to know](https://openpanel.dev/docs/sdks/nextjs#good-to-know)
[Installation](https://openpanel.dev/docs/sdks/nextjs#installation)
[Install dependencies](https://openpanel.dev/docs/sdks/nextjs#install-dependencies)
[Initialize](https://openpanel.dev/docs/sdks/nextjs#initialize)
[Options](https://openpanel.dev/docs/sdks/nextjs#options)
[NextJS options](https://openpanel.dev/docs/sdks/nextjs#nextjs-options)
[`filter`](https://openpanel.dev/docs/sdks/nextjs#filter)
[Usage](https://openpanel.dev/docs/sdks/nextjs#usage)
[Client components](https://openpanel.dev/docs/sdks/nextjs#client-components)
[Server components](https://openpanel.dev/docs/sdks/nextjs#server-components)
[Tracking Events](https://openpanel.dev/docs/sdks/nextjs#tracking-events)
[Identifying Users](https://openpanel.dev/docs/sdks/nextjs#identifying-users)
[For server components](https://openpanel.dev/docs/sdks/nextjs#for-server-components)
[Setting Global Properties](https://openpanel.dev/docs/sdks/nextjs#setting-global-properties)
[Incrementing Properties](https://openpanel.dev/docs/sdks/nextjs#incrementing-properties)
[Decrementing Properties](https://openpanel.dev/docs/sdks/nextjs#decrementing-properties)
[Working with Groups](https://openpanel.dev/docs/sdks/nextjs#working-with-groups)
[Clearing User Data](https://openpanel.dev/docs/sdks/nextjs#clearing-user-data)
[Server side](https://openpanel.dev/docs/sdks/nextjs#server-side)
[Serverless & Vercel](https://openpanel.dev/docs/sdks/nextjs#serverless--vercel)
[Proxy events](https://openpanel.dev/docs/sdks/nextjs#proxy-events)