Next.js

Install Clamp in a Next.js app. App Router, Pages Router, server-side events from Route Handlers, queryable by your AI agent via MCP.

Install

terminal
npm install @clamp-sh/analytics

App Router

Add the Analytics component to your root layout.tsx. It’s a Client Component; render it as a sibling of {children}.

app/layout.tsx
import { Analytics } from "@clamp-sh/analytics/react"

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        {children}
        <Analytics projectId="proj_xxx" />
      </body>
    </html>
  )
}

Pageviews — including client-side navigations via next/link and router.push() — are tracked automatically.

Pages Router

Add the component to _app.tsx:

pages/_app.tsx
import type { AppProps } from "next/app"
import { Analytics } from "@clamp-sh/analytics/react"

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <Component {...pageProps} />
      <Analytics projectId="proj_xxx" />
    </>
  )
}

Track custom events

Import track from the main SDK entry (not /react) and call it from any Client Component:

components/SignupButton.tsx
"use client"

import { track } from "@clamp-sh/analytics"

export function SignupButton() {
  return (
    <button onClick={() => track("signup_started", { plan: "pro" })}>
      Sign up
    </button>
  )
}

Properties must be flat string key-value pairs. See Events for limits and schema.

Server-side events

From a Route Handler, Server Action, or API Route, use the /server entry with an API key:

app/api/signup/route.ts
import { init, track } from "@clamp-sh/analytics/server"

init({ projectId: "proj_xxx", apiKey: process.env.CLAMP_API_KEY! })

export async function POST(req: Request) {
  const { anonymousId, email } = await req.json()

  await track("signup_completed", {
    anonymousId,
    properties: { email_domain: email.split("@")[1] },
  })

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

Pass anonymousId from the browser (via getAnonymousId()) to link server events to the visitor session.

Verify

  1. Deploy or open your app at a non-localhost URL (localhost is skipped by design).
  2. Navigate between a few pages.
  3. In your Clamp dashboard, pageviews should appear within ~5 seconds.
  4. DevTools → Network → filter for e/batch to confirm requests are sending.

Gotcha

App Router: place <Analytics /> in the root app/layout.tsx, not in a nested layout or a route group layout. The root layout is stable across navigations, so tracking initializes once. Nested layouts can remount when routing between segments, which re-runs init and can double-count sessions.

Next step