JustAnalytics for Next.js
Step-by-step guide to add analytics, error tracking, and APM to your Next.js app
JustAnalytics for Next.js
Add full-stack observability to your Next.js application — distributed tracing, error tracking, structured logging, and infrastructure metrics.
Time to data: 3-5 minutesPrerequisites#
- Next.js 14+ (App Router recommended; Pages Router also supported)
- Node.js 18+
- A JustAnalytics account with a Site ID and API key
Install the SDK
npm install @justanalyticsapp/node
Or with your preferred package manager:
yarn add @justanalyticsapp/node
# or
pnpm add @justanalyticsapp/node
Initialize via instrumentation.ts
Next.js 15+ provides an instrumentation.ts hook that runs once when the server starts. This is the recommended way to initialize JustAnalytics.
Zero-config (reads from environment variables):
// instrumentation.ts (project root)
export { register } from '@justanalyticsapp/node/next';
With explicit configuration:
// instrumentation.ts
import { withJustAnalytics } from '@justanalyticsapp/node/next';
export function register() {
withJustAnalytics({
siteId: process.env.JA_SITE_ID!,
apiKey: process.env.JA_API_KEY!,
serviceName: 'my-next-app',
environment: process.env.NODE_ENV,
});
}
Add your credentials to .env.local:
JA_SITE_ID=site_abc123
JA_API_KEY=ja_sk_your_api_key_here
Add API route tracing
Wrap your API route handlers with withTracing to automatically create spans for each request:
// app/api/users/[id]/route.ts
import { withTracing } from '@justanalyticsapp/node/next';
export const GET = withTracing(async (req, { params }) => {
const { id } = await params;
const user = await db.users.findUnique({ where: { id } });
return Response.json(user);
});
export const POST = withTracing(async (req) => {
const body = await req.json();
const user = await db.users.create({ data: body });
return Response.json(user, { status: 201 });
});
Add middleware tracing (optional)
Trace your Next.js middleware to measure authentication, redirects, and other middleware logic:
// middleware.ts
import { withMiddlewareTracing } from '@justanalyticsapp/node/next';
import { NextResponse } from 'next/server';
export default withMiddlewareTracing(async (req) => {
// Your middleware logic
const token = req.cookies.get('session');
if (!token && req.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', req.url));
}
return NextResponse.next();
});
export const config = {
matcher: ['/dashboard/:path*'],
};
Add Server Component tracing (optional)
Trace data fetching in Server Components:
// app/users/[id]/page.tsx
import { traceServerComponent } from '@justanalyticsapp/node/next';
export default async function UserPage({ params }: { params: { id: string } }) {
return traceServerComponent('UserPage', async () => {
const user = await getUser(params.id);
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
});
}
Add client-side tracking (optional)
For frontend analytics (page views, clicks, Web Vitals), add the tracking script to your root layout:
// app/layout.tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<script
defer
data-site-id="site_abc123"
src="https://justanalytics.up.railway.app/tracker.js"
/>
<script
defer
data-site-id="site_abc123"
src="https://justanalytics.up.railway.app/monitor.js"
/>
</head>
<body>{children}</body>
</html>
);
}
Verify Your Setup
Send a request to any API route, then check the Traces tab in your dashboard. You should see server spans with route names like 'GET /api/users/[id]'.
Open DashboardAdvanced Features#
Error tracking#
Errors thrown inside withTracing handlers are automatically captured. You can also capture errors manually:
import JA from '@justanalyticsapp/node';
try {
await riskyOperation();
} catch (error) {
JA.captureException(error, {
tags: { module: 'payments' },
extra: { orderId: '12345' },
});
}
Structured logging#
import JA from '@justanalyticsapp/node';
JA.logger.info('User signed up', { userId: 'u123', plan: 'pro' });
JA.logger.error('Payment failed', { orderId: 'o456', reason: 'insufficient_funds' });
Custom spans#
import JA from '@justanalyticsapp/node';
const result = await JA.startSpan('process-order', async (span) => {
span.setAttribute('order.id', orderId);
span.setAttribute('order.total', total);
return await processOrder(orderId);
});
User identification#
import JA from '@justanalyticsapp/node';
// In your auth middleware or after login
JA.setUser({ id: user.id, email: user.email });
Custom metrics#
import JA from '@justanalyticsapp/node';
JA.recordMetric('custom.queue_size', 42, { queue: 'emails' });
Environment configuration#
| Variable | Description | Required |
|----------|-------------|----------|
| JA_SITE_ID | Your site ID from the dashboard | Yes |
| JA_API_KEY | API key (starts with ja_sk_) | Yes |
| JA_SERVICE_NAME | Service name for traces | No (defaults to package name) |
| JA_ENVIRONMENT | Deployment environment | No (defaults to NODE_ENV) |
Pages Router support#
If you are using the Pages Router, initialize the SDK in a custom server or at the top of _app.tsx:
// pages/_app.tsx
import JA from '@justanalyticsapp/node';
if (typeof window === 'undefined') {
JA.init({
siteId: process.env.JA_SITE_ID!,
apiKey: process.env.JA_API_KEY!,
serviceName: 'my-next-app',
});
}
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />;
}
For API routes in Pages Router, wrap handlers manually:
// pages/api/users.ts
import JA from '@justanalyticsapp/node';
import type { NextApiRequest, NextApiResponse } from 'next';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
return JA.startSpan(`${req.method} /api/users`, async (span) => {
const users = await db.users.findMany();
res.json(users);
});
}