Next.js and React setup
Use the plain snippet or the tiny npm package, both end at the same 1KB tracker. The package just makes the component ergonomics nicer.
- Key takeaways
- Either next/script with the snippet or the @bobray/next package, same 1 KB tracker.
- useBobray() gives a typed track(event, meta) for component-level goals.
- Exclude *.vercel.app previews with a hostname rule so deploy checks don't count.
Option A: the snippet
In Next.js (App Router), add the snippet to app/layout.tsx using next/script:
import Script from "next/script";
<Script
defer
data-site="YOUR_SITE_ID"
src="https://cdn.bobray.com/b.js"
strategy="afterInteractive"
/>
Option B: the package
npm install @bobray/next
// app/layout.tsx
import { BobRay } from "@bobray/next";
<BobRay siteId="YOUR_SITE_ID" />The component renders the same deferred script and adds a useBobray() hook exposing track(event, meta) with types.
Tracking goals from components
const { track } = useBobray();
<button onClick={() => track('signup', { plan: 'growth' })}>
Create account
</button>
Environment tips
- Route changes are tracked automatically in both options.
- Preview deployments on
*.vercel.appcan be excluded underSettings → Exclusionswith a hostname rule. - Keep the site ID in an env var if you deploy the same code to multiple domains.
Common pitfalls
The mistakes we see most often on this topic, so you can skip them entirely.
- Putting the tag in a page component instead of the root layout, some routes go untracked.
- Using strategy="beforeInteractive", it blocks paint for no benefit; afterInteractive is right.
- Hard-coding the site ID across environments; use an env var per deploy target.
Quick reference
| Package | npm i @bobray/next |
| Component | |
| Hook | useBobray().track(name, meta) |
| Previews | Exclude *.vercel.app |
Did this solve it? If not, write to support with your site ID, a real person replies within one business day.