Skip to main content
Next.js has built-in support for measuring and reporting Core Web Vitals—the metrics used by Google to evaluate real-world page performance.

Web Vitals

The following metrics are reported:
MetricDescription
TTFBTime to First Byte
FCPFirst Contentful Paint
LCPLargest Contentful Paint
FIDFirst Input Delay
CLSCumulative Layout Shift
INPInteraction to Next Paint

useReportWebVitals

The useReportWebVitals hook is called every time a metric value is available in the browser:
app/components/WebVitals.tsx
'use client'

import { useReportWebVitals } from 'next/web-vitals'

export function WebVitals() {
  useReportWebVitals((metric) => {
    console.log(metric)
  })

  return null
}
Render the component in your root layout:
import { WebVitals } from './components/WebVitals'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        <WebVitals />
        {children}
      </body>
    </html>
  )
}
Because useReportWebVitals requires the 'use client' directive, create a separate component for it rather than adding it directly to the root layout (which is a Server Component).

The metric object

The metric argument passed to the callback has the following shape:
id
string
A unique identifier for the metric in the context of the current page load.
name
string
The metric name. One of 'TTFB', 'FCP', 'LCP', 'FID', 'CLS', 'INP'.
value
number
The metric value. For time-based metrics, the unit is milliseconds. For CLS, it is a unitless score.
delta
number
The delta between the current value and the last reported value. Useful for calculating the total value when sending to analytics.
rating
string
The qualitative rating of the metric. One of 'good', 'needs-improvement', or 'poor'.
navigationType
string
How the page was loaded. One of 'navigate', 'reload', 'back-forward', 'back-forward-cache', 'prerender'.

Sending metrics to an analytics service

Send metrics to any analytics service inside the useReportWebVitals callback. The following examples show common integrations:
app/components/WebVitals.tsx
'use client'

import { useReportWebVitals } from 'next/web-vitals'

export function WebVitals() {
  useReportWebVitals((metric) => {
    const body = JSON.stringify(metric)
    const url = '/api/analytics'

    // Use `navigator.sendBeacon()` if available, falling back to `fetch`
    if (navigator.sendBeacon) {
      navigator.sendBeacon(url, body)
    } else {
      fetch(url, { body, method: 'POST', keepalive: true })
    }
  })

  return null
}

Vercel Speed Insights

Vercel provides Speed Insights as a built-in analytics product for applications deployed on Vercel. No additional code is required—Speed Insights is enabled automatically in the Vercel dashboard. For self-hosted deployments or to collect metrics manually, use the useReportWebVitals hook as shown above.

Performance budget

Use the rating field to alert when metrics fall outside acceptable ranges:
app/components/WebVitals.tsx
'use client'

import { useReportWebVitals } from 'next/web-vitals'

export function WebVitals() {
  useReportWebVitals((metric) => {
    if (metric.rating === 'poor') {
      console.warn(
        `Poor ${metric.name} score: ${metric.value} (${metric.rating})`
      )
    }

    // Send to monitoring service
    if (metric.name === 'LCP' && metric.value > 2500) {
      // LCP > 2.5s is considered poor
      reportToMonitoring('lcp_poor', metric)
    }
  })

  return null
}

Build docs developers (and LLMs) love