Next.js
NohmoNextProvider hooks into the Next.js router, so page views follow client-side navigation rather than only the first server render. Pick your router — the provider and the import differ, nothing else does.
Install
npm install nohmo
Wrap your root layout
Open app/layout.tsx and wrap your children with NohmoNextProvider. That's all — page views, clicks, scroll depth, and time spent are tracked automatically from this point.
// app/layout.tsximport { NohmoNextProvider } from 'nohmo'export default function RootLayout({ children }: { children: React.ReactNode }) {return (<html><body><NohmoNextProviderprojectId={process.env.NEXT_PUBLIC_NOHMO_PROJECT_ID!}apiKey={process.env.NEXT_PUBLIC_NOHMO_API_KEY!}>{children}</NohmoNextProvider></body></html>)}
Add your keys to .env.local
Get your project ID and API key from Dashboard → Settings → Setup.
NEXT_PUBLIC_NOHMO_PROJECT_ID=proj_xxxxNEXT_PUBLIC_NOHMO_API_KEY=pk_xxxx
Note: Restart your dev server after adding env vars — Next.js won't pick them up otherwise.
Track a custom event (optional)
Use the useNohmo() hook anywhere inside the provider tree.
import { useNohmo } from 'nohmo'export default function BuyButton() {const { send } = useNohmo()return (<button onClick={() => send('purchase_started', { plan: 'pro' })}>Buy now</button>)}
Identify users at login (optional)
Call linkUser() after a successful login. All anonymous events from that device are retroactively attached to the user — nothing is lost.
const { linkUser } = useNohmo()const handleLogin = async () => {const user = await loginAPI()await linkUser(user.id, user.email)}
You're all set
Open your Nohmo dashboard. You should see devices and events appearing within seconds of your first page load.
Note: The project ID and API key are public values that ship in the browser bundle, which is why they use the NEXT_PUBLIC_ prefix. Write keys are never used from the client. To capture errors thrown in route handlers and server actions as well, add Node.js & Express.
Next steps
Auto-capture lists what arrives without any code of your own. Custom events covers sending your own, and Configuration has every option the SDK accepts.