Developer pages

Web vitals & tracing

Core Web Vitals ($web_vitals) and distributed spans — options, APIs, and Insights surfaces.

Web vitals

Options

OptionDefaultMeaning
enableWebVitalstrueCollect FCP, LCP, CLS, INP, TTFB via the web-vitals library path in the SDK
HumanBehaviorTracker.init(apiKey, {
  enableWebVitals: true,
});

Event shape

Each metric is emitted as a custom event named $web_vitals with properties such as:

PropertyExample / meaning
$web_vitals_metricFCP | LCP | CLS | INP | TTFB
$web_vitals_valueNumeric metric value
$web_vitals_<METRIC>_valuePer-metric alias (e.g. $web_vitals_LCP_value)
$web_vitals_ratinggood | needs-improvement | poor
$web_vitals_idMetric id from the library
$web_vitals_navigation_typeNavigation type
$web_vitals_pageload_idCorrelates metrics for one page load

Some metrics settle at page-hide; short sessions still respect the minimum-duration gate unless configured otherwise.

Product surface

Insights → Web Vitals

Tracing / spans

Options

OptionDefaultMeaning
enableTracingtruePage-load transaction, Navigation Timing phases, Resource Timing children, custom spans

Transport: POST /api/ingestion/spans/batch (beacon on unload when needed).

Automatic spans

When enabled, the SDK opens a root pageload trace and attaches:

  • Navigation phases (request / response / DOM)
  • Resource children (resource.script, resource.css, resource.img, http.client, …)
  • Shared W3C-style traceId; children reference parentSpanId
  • Outgoing same-origin requests may receive traceparent / sentry-trace headers for backend continuation

SDK-owned ingestion URLs are skipped via the same skip list as network tracking.

Custom spans

// Time a sync/async callback (no-op wrapper if tracing disabled)
const result = tracker.startSpan(
  { name: "checkout.compute", op: "function", attributes: { step: "tax" } },
  () => computeTax(),
);

// Manual span
const span = tracker.startInactiveSpan({ name: "checkout.pay", op: "ui.action" });
span.setAttribute("method", "card");
try {
  await pay();
  span.setStatus("ok");
} catch (e) {
  span.setStatus("error");
  throw e;
} finally {
  span.end();
}
APIBehavior
startSpan({ name, op?, attributes? }, callback)Runs callback; returns its value; ends span automatically
startInactiveSpan({ name, op?, attributes? })Returns { setAttribute, setStatus, end }; no-op object if tracing off

Span status values: 'ok' | 'error' | 'cancelled'.

Product surface

Insights → Traces

Verify

  1. Load pages under production-like conditions with vitals/tracing left on.
  2. Open Insights → Web Vitals / Traces with a date range that includes traffic.
  3. Network tab: confirm /api/ingestion/spans/batch and $web_vitals custom-event traffic.
  4. Empty windows usually mean no traffic, capture disabled, or filters excluding the environment.