Better AnalyticsBetter Analytics

Next.js Integration

Better Analytics provides seamless integration with Next.js applications with automatic initialization for both client and server-side tracking.

Installation

pnpm add better-analytics

Setup

Add the Analytics component to your layout - this automatically enables both client and server-side tracking:

app/layout.tsx
import { Analytics } from 'better-analytics/next'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        <Analytics site="your-site-id" />
        {children}
      </body>
    </html>
  )
}

Environment Variables

Set up your environment variables once and they work for both client and server:

.env.local
# Required: Your site identifier
NEXT_PUBLIC_BA_SITE=your-site-id

# Optional: Custom endpoint (defaults to Better Analytics SaaS)
NEXT_PUBLIC_BA_URL=https://your-endpoint.com/api/collect

# Optional: Server-only variables
BA_API_KEY=your-server-api-key    # For server-side authentication
BA_DEBUG=true                      # Enable server-side debug logging

How it works:

  • NEXT_PUBLIC_BA_SITE - Used by both client and server
  • NEXT_PUBLIC_BA_URL - Used by both client and server
  • BA_API_KEY - Server-only (for authentication)
  • BA_DEBUG - Server-only (debug logging)

Component Configuration

<Analytics
  site="your-site-id"           // Required if not in env
  api="/api/collect"            // Custom endpoint
  mode="auto"                   // auto | development | production
  debug={false}                 // Enable console logging
  beforeSend={(event) => event} // Transform events
/>

Automatic Features

Page Tracking

The Analytics component automatically tracks:

  • Route changes - Both App Router and Pages Router
  • Dynamic routes - Converts /user/123 to /user/[id]
  • Search parameters - Included in page context
  • Page metadata - Title, pathname, and load time

Route Computation

Next.js dynamic routes are automatically computed:

// /user/123/settings → /user/[id]/settings
// /blog/[...slug] → /blog/[...slug]
// /shop/[category]/[product] → /shop/[category]/[product]

Client-side Tracking

Manual Events

Track custom events in client components:

'use client'

import { track, identify } from 'better-analytics/next'

export default function MyComponent() {
  const handleClick = () => {
    track('button_click', {
      button: 'signup',
      location: 'header'
    })
  }

  const handleLogin = (userId: string) => {
    identify(userId, {
      email: 'user@example.com',
      plan: 'pro'
    })
  }

  return (
    <button onClick={handleClick}>
      Sign Up
    </button>
  )
}

React Hooks

Use analytics in React components:

'use client'

import { useEffect } from 'react'
import { track } from 'better-analytics/next'

export default function ProductPage({ product }) {
  useEffect(() => {
    track('product_viewed', {
      product_id: product.id,
      category: product.category,
      price: product.price
    })
  }, [product])

  return <div>{product.name}</div>
}

Server-side Tracking

Auto-initialization

Server functions automatically initialize using your environment variables - no manual setup needed:

// No initialization needed - automatically uses NEXT_PUBLIC_BA_SITE and other env vars
import { trackServer } from 'better-analytics/next'

await trackServer('purchase', {
  value: 99.99,
  currency: 'USD'
})

API Routes

// app/api/purchase/route.ts
import { trackServer } from 'better-analytics/next'

export async function POST(request: Request) {
  const body = await request.json()
  
  // Your purchase logic here
  
  await trackServer('purchase', {
    value: body.amount,
    currency: body.currency,
    payment_method: body.paymentMethod
  }, {
    headers: request.headers
  })

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

Server Actions

// app/actions.ts
'use server'

import { trackServer } from 'better-analytics/next'

export async function createUser(formData: FormData) {
  // Your user creation logic
  
  await trackServer('user_created', {
    method: 'form',
    source: 'signup_page'
  })
}

Server Components

Track events in Server Components:

// app/page.tsx
import { trackPageviewServer } from 'better-analytics/next'
import { headers } from 'next/headers'

export default async function HomePage() {
  // Track server-side page view
  await trackPageviewServer('/', {
    headers: headers()
  })

  return <div>Welcome!</div>
}

Middleware

Track requests in Next.js middleware:

// middleware.ts
import { NextResponse } from 'next/server'
import { trackServer } from 'better-analytics/next'

export async function middleware(request) {
  await trackServer('middleware_request', {
    pathname: request.nextUrl.pathname,
    method: request.method
  }, {
    headers: request.headers
  })

  return NextResponse.next()
}

Session Stitching

Connect client and server events for the same user:

// app/api/purchase/route.ts
import { trackServer, stitchSession } from 'better-analytics/next'

export async function POST(request: Request) {
  // Get client session from cookies
  const clientSessionId = request.cookies.get('ba_session')?.value
  const clientDeviceId = request.cookies.get('ba_device')?.value

  await trackServer('purchase', {
    value: 99.99,
    currency: 'USD'
  }, {
    headers: request.headers,
    user: stitchSession(clientSessionId, clientDeviceId)
  })

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

TypeScript Support

Full TypeScript support with Next.js-specific types:

import type { AnalyticsProps, ServerTrackOptions } from 'better-analytics/next'

// Component props
const analyticsProps: AnalyticsProps = {
  site: 'your-site-id',
  debug: true,
  beforeSend: (event) => {
    // Type-safe event transformation
    return event
  }
}

// Server options
const serverOptions: ServerTrackOptions = {
  headers: request.headers,
  user: { id: 'user-123' }
}

Development Workflow

package.json
# Enable debug logging
BA_DEBUG=true pnpm dev

# Or in your scripts
{
  "scripts": {
    "dev": "BA_DEBUG=true next dev",
    "dev:analytics": "BA_DEBUG=true NEXT_PUBLIC_BA_DEBUG=true next dev"
  }
}

Best Practices

  1. Use Analytics component in layout - Single setup works for everything
  2. Use NEXT_PUBLIC_ variables - Work for both client and server
  3. Track server-side conversions - More reliable than client-side
  4. Use session stitching - Connect client and server events
  5. Enable debug in development - Monitor events during development

Troubleshooting

Events Not Appearing

  1. Check that NEXT_PUBLIC_BA_SITE is set
  2. Verify the Analytics component is in your layout
  3. Enable debug mode to see console logs
  4. Check network tab for outgoing requests

Server Events Not Working

  1. Ensure NEXT_PUBLIC_BA_SITE is set (used by server as fallback)
  2. Enable BA_DEBUG=true for server logging
  3. Check server logs for errors
  4. Verify server functions are being called

Route Tracking Issues

  1. Ensure Analytics component is in the layout
  2. Check dynamic route parameters
  3. Verify route computation with debug mode
  4. Test with both App Router and Pages Router

How is this guide?