Track named events
Fire explicit business events like feature.report.generated by wrapping the routes that matter.
Behavior capture records requests automatically. Sometimes you also want to fire an explicit named event — "report generated", "teammate invited" — so understanding can reason about the actions that matter most to your product.
Wrap a route
Pick 3–5 API routes where a customer account does something meaningful — not every route, not static assets, not health checks. Good candidates: creating a resource, completing a core action, an admin acting for a customer.
// app/api/reports/route.ts — track "report generated"
import { withAtuneTracking } from "@/lib/atune-track";
// Atune auto-detects the account from your auth session — nothing to wire up.
export const POST = withAtuneTracking(
"feature.report.generated",
async (req) => {
// ...your existing handler logic, unchanged
return Response.json({ ok: true });
},
);The wrapper runs your handler, then fires the event without awaiting it — a slow or down Atune can never delay or break the response.
Custom account accessor
Using an auth system Atune can't auto-detect? Pass a getAccount accessor as the
third argument and return the account the request belongs to — not just the
logged-in user:
export const POST = withAtuneTracking(
"feature.report.generated",
handler,
{ getAccount: (req) => ({ accountId: yourOrgId, userId: yourUserId }) },
);Verify it landed
Trigger one wrapped action, then open your Atune onboarding page and click
"Check connection" — confirm the latest event's account/user matches what you
just did. If nothing shows, check the console for a [atune] warning; it explains
why (usually a wrong key/URL, or an auth system to wire via getAccount).
The full lib/atune-track.ts helper — with Clerk / NextAuth / Supabase
auto-detection built in — is generated for you by npx atune init.