Automatic Instrumentation

Learn what spans are captured after tracing is enabled.

The Sentry SDK provides a BrowserTracing integration to add automatic instrumentation for monitoring the performance of browser applications.

Once you enable tracing, the SDK automatically captures performance data without additional code:

WhatDescriptionMetrics
Page loadsFull page load performanceLCP, CLS, TTFB
NavigationsClient-side route changesDuration, Web Vitals
HTTP requestsAll fetch/XHR callsDuration, status, URL
User interactionsClicks, inputs that trigger workINP (responsiveness)
Long tasksMain thread blocking > 50msDuration, attribution

The BrowserTracing integration creates a new transaction for each page load and navigation event, and creates a child span for every XMLHttpRequest or fetch request that occurs while those transactions are open. Learn more about traces, transactions, and spans.

To enable tracing, include browserTracingIntegration in your SDK configuration options.

After configuration, you will see both pageload and navigation transactions in the Sentry UI.

Copied
// If you're using one of our framework SDK packages, like `@sentry/react`,
// substitute its name for `@sentry/browser` here
import * as Sentry from "@sentry/browser";

Sentry.init({
  dsn: "___PUBLIC_DSN___",

  integrations: [Sentry.browserTracingIntegration()],

  // We recommend adjusting this value in production, or using tracesSampler
  // for finer control
  tracesSampleRate: 1.0,
});

By default, the browserTracingIntegration() will create a pageload span for when the page is initially loaded, as well as a navigation span for whenever the URL changes afterwards.

To make sure that spans are created correctly for a custom routing setup, you'll need to opt out of the default span creation by setting instrumentNavigation: false and instrumentPageLoad: false in the browserTracingIntegration() options. You can then manually create spans like this:

Copied
const client = Sentry.init({
  integrations: [
    Sentry.browserTracingIntegration({
      // disable automatic span creation
      instrumentNavigation: false,
      instrumentPageLoad: false,
    }),
  ],
});

// We start the pageload span as early as possible!
let pageLoadSpan = Sentry.startBrowserTracingPageLoadSpan(client, {
  name: window.location.pathname,
  attributes: {
    [Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
  },
});

// Somewhere, instrument your router like this:
myRouter.on("routeChange", (route) => {
  // Make sure that the pageload span uses the route name
  // After that, each route change should trigger a navigation span (which will automatically finish the previous one)
  if (pageLoadSpan) {
    pageLoadSpan.updateName(route.name);
    pageLoadSpan.setAttribute(
      Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
      "route",
    );
    pageLoadSpan = undefined;
  } else {
    Sentry.startBrowserTracingNavigationSpan(client, {
      op: "navigation",
      name: route.name, // or what the name of the span should be
      attributes: {
        [Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "route",
      },
    });
  }
});

Most apps only need these options:

tracePropagationTargets

TypeArray<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 tracePropagationTargets option to ["localhost", /^https:\/\/api\.example\.com/].
  • Now outgoing XHR/fetch requests to your backend service will get the sentry-trace and baggage headers attached.
Copied
Sentry.init({
  // ...
  integrations: [Sentry.browserTracingIntegration()],

  // Set `tracePropagationTargets` to control for which URLs trace propagation should be enabled
  tracePropagationTargets: ["localhost", /^https:\/\/yourserver\.io\/api/],
});

beforeStartSpan

Type(options: StartSpanOptions) => StartSpanOptions

Modify span data before it's captured. Useful for adding context or normalizing URLs with dynamic segments:

One common use case is parameterizing transaction names. For both pageload and navigation transactions, the browserTracingIntegration uses the browser's window.location value to generate a transaction name. Using beforeStartSpan lets you modify the transaction name to make it more generic, so that for example, transactions named GET /users/12312012 and GET /users/11212012 can both be renamed to GET /users/:userid. That way they'll be grouped together.

Copied
Sentry.init({
  // ...
  integrations: [
    Sentry.browserTracingIntegration({
      beforeStartSpan: (context) => {
        return {
          ...context,
          // You could use your UI's routing library to find the matching
          // route template here. We don't have one right now, so do some basic
          // parameter replacements.
          name: location.pathname
            .replace(/\/[a-f0-9]{32}/g, "/<hash>")
            .replace(/\/\d+/g, "/<digits>"),
        };
      },
    }),
  ],
});

shouldCreateSpanForRequest

Type(url: string) => boolean

Exclude requests from tracing, such as health checks or analytics pings:

Copied
Sentry.init({
  // ...
  integrations: [
    Sentry.browserTracingIntegration({
      shouldCreateSpanForRequest: (url) => {
        // Do not create spans for outgoing requests to a `/health/` endpoint
        return !url.match(/\/health\/?$/);
      },
    }),
  ],
});

enableInp

Available since7.104.0
Typeboolean
Defaulttrue (See note)

Automatically captures INP events to measure responsiveness. Results appear in the Web Vitals module.

Default: true in SDK 8.x+, false in 7.x.

Copied
Sentry.init({
  // ...
  integrations: [
    Sentry.browserTracingIntegration({
      enableInp: true,
    }),
  ],
});

interactionsSampleRate

Typenumber
Default1.0

Sample rate for INP spans, applied on top of tracesSampleRate. For example, interactionsSampleRate: 0.5 with tracesSampleRate: 0.1 results in 5% of interactions captured.

Timing & Timeout Options

idleTimeout

Typenumber
Default1000

Time in ms to wait before finishing a pageload/navigation span when no unfinished child spans remain.

finalTimeout

Typenumber
Default30000

Maximum duration in ms for pageload/navigation spans. Spans exceeding this are automatically finished.

childSpanTimeout

Typenumber
Default15000

Maximum time in ms a child span can run before the parent pageload/navigation span is finished.

Enable/Disable Specific Instrumentation

instrumentPageLoad

Typeboolean
Defaulttrue

Enable/disable automatic pageload span creation on initial page load.

instrumentNavigation

Typeboolean
Defaulttrue

Enable/disable automatic navigation span creation on history changes.

enableLongTask

Typeboolean
Defaulttrue

Enable/disable automatic spans for long tasks (main thread blocking > 50ms).

enableLongAnimationFrame

Available since8.18.0
Typeboolean
Defaulttrue

Enable/disable spans for long animation frames. Falls back to long tasks if browser doesn't support long animation frames.

markBackgroundSpan

Typeboolean
Defaulttrue

Mark pageload/navigation spans as "cancelled" when the tab moves to background. Recommended to keep enabled for accurate measurements.

enableReportPageLoaded

Available since10.13.0
Typeboolean
Defaultfalse

Enable the Sentry.reportPageLoaded() function.

Filtering & Ignoring Spans

ignoreResourceSpans

Available since9.23.0
TypeArray<string>
Default[]

Ignore specific resource span categories by their op (e.g., resource.script, resource.css):

Copied
Sentry.init({
  integrations: [
    Sentry.browserTracingIntegration({
      ignoreResourceSpans: ["resource.css", "resource.script"],
    }),
  ],
});

ignorePerformanceApiSpans

Available since9.23.0
TypeArray<string | RegExp>
Default[]

Ignore spans created from performance.mark() and performance.measure():

Copied
Sentry.init({
  integrations: [
    Sentry.browserTracingIntegration({
      ignorePerformanceApiSpans: ["myMeasurement", /myMark/],
    }),
  ],
});

onRequestSpanStart

Type(span: Span, requestInformation: { headers?: WebFetchHeaders }): void

Callback invoked when a span starts for an outgoing fetch/XHR request. Use to annotate spans with additional attributes based on request headers.

Was this helpful?
Help improve this content
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").