Skip to main content
Add DATALYR to your Next.js app (App Router or Pages Router) using the @datalyr/web SDK for TypeScript support and advanced tracking.

Use Cases

SaaS Applications Track signups, feature usage, and subscription conversions with full TypeScript support. E-commerce Track product views, cart interactions, and purchases with server-side rendering support. Marketing Sites Monitor landing page performance, form submissions, and ad campaign attribution. Web Apps Track user behavior, feature adoption, and custom events with full control.

Before You Start

  • You have a DATALYR account
  • You’ve created a workspace
  • You have a Next.js project (App Router or Pages Router)
  • Node.js 14+ installed

Installation Method

Choose between SDK (recommended) or Script tag: Full TypeScript support, type-safe events, and programmatic control.

Method 2: Using Script Tag

Simple HTML script in your layout file. No npm install needed.

Method 1: Install @datalyr/web SDK

Step 1: Install the Package

npm install @datalyr/web
# or
yarn add @datalyr/web
# or
pnpm add @datalyr/web

Step 2: Initialize in App Router (Next.js 13+)

Create a client component for DATALYR initialization: app/providers/datalyr-provider.tsx
'use client'

import { useEffect } from 'react'
import { datalyr } from '@datalyr/web'

export function DatalyrProvider({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    // Initialize DATALYR
    datalyr.init({
      workspaceId: process.env.NEXT_PUBLIC_DATALYR_WORKSPACE_ID!,
      debug: process.env.NODE_ENV === 'development',
      trackSessions: true,
    })

    // Track initial page view
    datalyr.page()
  }, [])

  return <>{children}</>
}
Add to your root layout: app/layout.tsx
import { DatalyrProvider } from './providers/datalyr-provider'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <DatalyrProvider>
          {children}
        </DatalyrProvider>
      </body>
    </html>
  )
}

Step 3: Initialize in Pages Router (Next.js 12 and below)

Add to pages/_app.tsx:
import { useEffect } from 'react'
import { useRouter } from 'next/router'
import { datalyr } from '@datalyr/web'
import type { AppProps } from 'next/app'

function MyApp({ Component, pageProps }: AppProps) {
  const router = useRouter()

  useEffect(() => {
    // Initialize DATALYR
    datalyr.init({
      workspaceId: process.env.NEXT_PUBLIC_DATALYR_WORKSPACE_ID!,
      debug: process.env.NODE_ENV === 'development',
      trackSessions: true,
    })

    // Track initial page view
    datalyr.page()

    // Track route changes
    const handleRouteChange = (url: string) => {
      datalyr.page({ path: url })
    }

    router.events.on('routeChangeComplete', handleRouteChange)
    return () => router.events.off('routeChangeComplete', handleRouteChange)
  }, [router.events])

  return <Component {...pageProps} />
}

export default MyApp

Step 4: Add Environment Variable

.env.local
NEXT_PUBLIC_DATALYR_WORKSPACE_ID=your_workspace_id_here
Get your workspace ID from DATALYR Dashboard → Settings → Tracking.

Method 2: Using Script Tag

App Router (Next.js 13+)

Add to app/layout.tsx:
import Script from 'next/script'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <Script
          src="https://track.datalyr.com/dl.js"
          data-workspace-id={process.env.NEXT_PUBLIC_DATALYR_WORKSPACE_ID}
          strategy="afterInteractive"
        />
      </head>
      <body>{children}</body>
    </html>
  )
}

Pages Router

Add to pages/_document.tsx:
import { Html, Head, Main, NextScript } from 'next/document'
import Script from 'next/script'

export default function Document() {
  return (
    <Html>
      <Head>
        <Script
          src="https://track.datalyr.com/dl.js"
          data-workspace-id={process.env.NEXT_PUBLIC_DATALYR_WORKSPACE_ID}
          strategy="afterInteractive"
        />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

Track Custom Events

Using @datalyr/web SDK

import { datalyr } from '@datalyr/web'

// Track button click
function handleClick() {
  datalyr.track('button_clicked', {
    button_name: 'Sign Up',
    location: 'hero_section'
  })
}

// Track form submission
function handleFormSubmit(email: string) {
  datalyr.track('form_submission', {
    form_type: 'newsletter',
    email: email
  })
}

// Track purchase
function handlePurchase(orderId: string, amount: number) {
  datalyr.track('purchase', {
    order_id: orderId,
    revenue: amount,
    currency: 'USD'
  })
}

Using window.datalyr (Script Tag Method)

'use client'

function handleClick() {
  if (window.datalyr) {
    window.datalyr.track('button_clicked', {
      button_name: 'Sign Up',
      location: 'hero_section'
    })
  }
}

Identify Users

Track users for cross-device attribution:
import { datalyr } from '@datalyr/web'

// After user signs up or logs in
datalyr.identify('user_12345', {
  email: '[email protected]',
  name: 'John Doe',
  plan: 'pro'
})

Track Page Views (App Router)

For App Router, manually track page views on route changes:
'use client'

import { usePathname, useSearchParams } from 'next/navigation'
import { useEffect } from 'react'
import { datalyr } from '@datalyr/web'

export function PageViewTracker() {
  const pathname = usePathname()
  const searchParams = useSearchParams()

  useEffect(() => {
    const url = pathname + (searchParams?.toString() ? `?${searchParams}` : '')
    datalyr.page({ path: url })
  }, [pathname, searchParams])

  return null
}
Add to your root layout:
import { PageViewTracker } from './page-view-tracker'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        <PageViewTracker />
        {children}
      </body>
    </html>
  )
}

Server-Side Tracking

For server-side events (API routes, Server Components):
// app/api/purchase/route.ts
import { NextResponse } from 'next/server'

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

  // Send server-side event to DATALYR
  await fetch('https://ingest.datalyr.com/events', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      workspaceId: process.env.DATALYR_WORKSPACE_ID,
      events: [{
        eventName: 'purchase',
        timestamp: new Date().toISOString(),
        properties: {
          order_id: body.orderId,
          revenue: body.amount,
          currency: 'USD',
        }
      }]
    })
  })

  return NextResponse.json({ success: true })
}

TypeScript Support

The @datalyr/web SDK includes full TypeScript definitions:
import { datalyr, type EventProperties, type UserTraits } from '@datalyr/web'

// Type-safe event tracking
const properties: EventProperties = {
  button_name: 'Sign Up',
  location: 'hero_section'
}

datalyr.track('button_clicked', properties)

// Type-safe user identification
const traits: UserTraits = {
  email: '[email protected]',
  name: 'John Doe',
  plan: 'pro'
}

datalyr.identify('user_123', traits)

Troubleshooting

Events not showing in dashboard? Check that:
  • Your workspace ID is correct in environment variables
  • You’re using NEXT_PUBLIC_ prefix for client-side variables
  • SDK is initialized before tracking events
  • Ad blockers are disabled
Duplicate page views? Make sure you’re only initializing DATALYR once (in _app.tsx or root layout, not in individual pages). TypeScript errors? Install type definitions:
npm install --save-dev @types/node
SDK not found? If using script tag method, check that the script loads:
useEffect(() => {
  console.log('DATALYR loaded:', !!window.datalyr)
}, [])

What Gets Tracked Automatically

The SDK automatically captures:
  • Page views (when you call datalyr.page())
  • Visitor IDs (persistent across sessions)
  • UTM parameters and ad click IDs
  • Referrer and traffic source
  • Device and browser information
  • Session tracking

Next Steps

Need Help?

Having issues with Next.js tracking? Check our troubleshooting guide or contact support.