Automatic Instrumentation for Next.js
Learn what spans are captured after tracing is enabled.
Capturing spans requires that you first set up tracing in your app if you haven't already.
@sentry/nextjs provides a BrowserTracing integration to add automatic instrumentation for monitoring the performance of browser applications, which is enabled by default once you set up tracing in your app. Further, the SDK will automatically enable error collection and tracing in your API routes and Next.js Data Fetchers.
If you're using stream mode, automatic instrumentation works the same way as described in this guide but applies to service spans instead of transactions. See Streamed Spans for more information.
Once you enable tracing, the SDK automatically captures performance data without additional code:
| What | Description | Metrics |
|---|---|---|
| Page loads | Full page load performance | LCP, CLS, TTFB |
| Navigations | Client-side route changes | Duration, Web Vitals |
| HTTP requests | All fetch/XHR calls | Duration, status, URL |
| Responsiveness | Interaction to Next Paint | INP |
| Long tasks | Main thread blocking > 50ms | Duration, attribution |
The BrowserTracing integration creates a new transaction for each pageload and navigation event, and creates a child span for every XMLHttpRequest or fetch request that occurs while those transactions are open. Additionally, the SDK creates transactions for all requests to API routes and Next.js data fetchers. Learn more about traces, transactions, and spans.
To enable tracing, simply set either a tracesSampleRate or a tracesSampler in your SDK configuration options, as detailed in Set Up Tracing.
Most apps only need these options:
- Distributed Tracing Targets — Connect frontend and backend spans
- Customize Span Names — Normalize URLs or add context
- Filter Out Unwanted Requests — Exclude health checks, analytics
tracePropagationTargets
| Type | Array<string | RegExp> |
|---|---|
| Default | ['localhost', /^\/$/] |
Controls which outgoing requests include tracing headers (sentry-trace and baggage). Required for connecting frontend spans to backend spans.
By default, tracing headers are only attached to requests containing localhost or starting with /. Add your API domains to trace requests across services:
For example:
- A frontend application is served from
example.com. - A backend service is served from
api.example.com. - During development, the backend service is served from
localhost. - The frontend application makes API calls to the backend.
- Set the
tracePropagationTargetsoption to["localhost", /^https:\/\/api\.example\.com/]. - Now outgoing XHR/fetch requests to your backend service will get the
sentry-traceandbaggageheaders attached.
Sentry.init({
// ...
integrations: [Sentry.browserTracingIntegration()],
// Set `tracePropagationTargets` to control for which URLs trace propagation should be enabled
tracePropagationTargets: ["localhost", /^https:\/\/yourserver\.io\/api/],
});
Sentry.init({
// ...
integrations: [Sentry.browserTracingIntegration()],
// Set `tracePropagationTargets` to control for which URLs trace propagation should be enabled
tracePropagationTargets: ["localhost", /^https:\/\/yourserver\.io\/api/],
});
Your server must allow these headers via CORS: Access-Control-Allow-Headers: sentry-trace, baggage
beforeStartSpan
| Type | (options: StartSpanOptions) => StartSpanOptions |
|---|
Modify span data before it's captured. Useful for adding context or normalizing URLs with dynamic segments:
Sentry.init({
// ...
integrations: [
Sentry.browserTracingIntegration({
beforeStartSpan: (context) => {
return {
...context,
attributes: {
...context.attributes,
resultFormat: "legacy",
},
};
},
}),
],
});
Sentry.init({
// ...
integrations: [
Sentry.browserTracingIntegration({
beforeStartSpan: (context) => {
return {
...context,
attributes: {
...context.attributes,
resultFormat: "legacy",
},
};
},
}),
],
});
shouldCreateSpanForRequest
| Type | (url: string) => boolean |
|---|
Exclude requests from tracing, such as health checks or analytics pings:
Sentry.init({
// ...
integrations: [
Sentry.browserTracingIntegration({
shouldCreateSpanForRequest: (url) => {
// Do not create spans for outgoing requests to a `/health/` endpoint
return !url.match(/\/health\/?$/);
},
}),
],
});
Sentry.init({
// ...
integrations: [
Sentry.browserTracingIntegration({
shouldCreateSpanForRequest: (url) => {
// Do not create spans for outgoing requests to a `/health/` endpoint
return !url.match(/\/health\/?$/);
},
}),
],
});
BrowserTracing automatically captures Web Vitals. To capture clicks and the work they trigger as spans, add the Interactions integration.
webVitals
| Available since | 11.0.0 |
|---|---|
| Type | WebVitalsOptions |
Configure which Web Vitals BrowserTracing collects. For example, to disable INP collection:
Sentry.init({
// ...
integrations: [
Sentry.browserTracingIntegration({
webVitals: {
ignore: ["inp"],
},
}),
],
});
Sentry.init({
// ...
integrations: [
Sentry.browserTracingIntegration({
webVitals: {
ignore: ["inp"],
},
}),
],
});
If you explicitly add webVitalsIntegration(), configure these options on that integration instead. See WebVitals for details and browser support requirements.
BrowserTracing automatically captures INP to measure responsiveness. Results appear in the Web Vitals module.
enableInp
| Available since | 7.104.0 |
|---|---|
| Type | boolean |
| Default | true (since version 8.0.0) |
Enable or disable INP collection. Defaults to true in SDK 8 and later, and false in SDK 7.x.
Deprecated in SDK version 11. Use webVitals: { ignore: ["inp"] } to disable INP. Explicitly adding webVitalsIntegration() takes precedence over this option.
The browserTracingIntegration is automatically enabled in @sentry/nextjs. To customize options, include it explicitly in instrumentation-client.js:
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: "___PUBLIC_DSN___",
integrations: [
Sentry.browserTracingIntegration({
// your options here
}),
],
tracesSampleRate: 1.0,
tracePropagationTargets: [
"localhost",
/^\//,
/^https:\/\/yourserver\.io\/api/,
],
});
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: "___PUBLIC_DSN___",
integrations: [
Sentry.browserTracingIntegration({
// your options here
}),
],
tracesSampleRate: 1.0,
tracePropagationTargets: [
"localhost",
/^\//,
/^https:\/\/yourserver\.io\/api/,
],
});
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").