Core Web Vitals Pro

Capture the five Core Web Vitals — LCP, CLS, INP, FCP, and TTFB — on real user loads. One web_vital event per metric per page load, with the metric name, value, rating, and pathname so you can segment by page.

Install the peer dep

The web-vitals capture path is dynamic-imported, so it only lands in the bundle when enabled. You need web-vitals as a peer dependency:

terminal
npm install web-vitals

If the peer dep isn’t installed, the extension silently no-ops. Nothing breaks, but no web_vital events fire. Turn on debug mode to verify.

Enable

init
init("proj_xxx", { extensions: { webVitals: true } })

// or, in React:
<Analytics projectId="proj_xxx" extensions={{ webVitals: true }} />

What fires

One web_vital event per captured metric per page load:

PropertyExampleNotes
metricLCPOne of LCP, CLS, INP, FCP, TTFB.
value2453.12Rounded to 2 decimals, sent as a string. Milliseconds for time metrics; unitless for CLS.
ratinggoodOne of good, needs-improvement, poor. Buckets come from the web-vitals library.
idv4-1712345678-123Unique per measurement. Dedup if you aggregate server-side.
pathname/pricingThe page the metric was measured on. Segment by this for per-page CWV.

The five metrics

Sampling

Default sampleRate is 1(100%). At low traffic that’s the right call — you want every sample. High traffic sites can lower it to stay within event quotas:

Sample 10% of loads
init("proj_xxx", {
  extensions: {
    webVitals: { sampleRate: 0.1 },
  },
})

The decision happens once per page load. If the page is sampled, all five metrics fire; if not, zero fire. You don’t get partial samples across metrics for the same visit.

Per-page analysis

The pathnameproperty makes segmentation trivial: ask “what’s the p75 LCP on /pricing” or “which pages have the worst INP”. Use the MCP tools to slice web_vital events by pathname and metric.

Gotchas