rembrembdocs

useReportWebVitals

Last updated April 23, 2026

The useReportWebVitals hook allows you to report Core Web Vitals, and can be used in combination with your analytics service.

New functions passed to useReportWebVitals are called with the available metrics up to that point. To prevent reporting duplicated data, ensure that the callback function reference does not change (as shown in the code examples below).

app/_components/web-vitals.js

'use client'
 
import { useReportWebVitals } from 'next/web-vitals'
 
const logWebVitals = (metric) => {
  console.log(metric)
}
 
export function WebVitals() {
  useReportWebVitals(logWebVitals)
 
  return null
}

app/layout.js

import { WebVitals } from './_components/web-vitals'
 
export default function Layout({ children }) {
  return (
    <html>
      <body>
        <WebVitals />
        {children}
      </body>
    </html>
  )
}

Since the useReportWebVitals hook requires the 'use client' directive, the most performant approach is to create a separate component that the root layout imports. This confines the client boundary exclusively to the WebVitals component.

useReportWebVitals

The metric object passed as the hook's argument consists of a number of properties:

Web Vitals

Web Vitals are a set of useful metrics that aim to capture the user experience of a web page. The following web vitals are all included:

You can handle all the results of these metrics using the name property.

app/components/web-vitals.tsx

JavaScriptTypeScript

'use client'
 
import { useReportWebVitals } from 'next/web-vitals'
 
type ReportWebVitalsCallback = Parameters<typeof useReportWebVitals>[0]
 
const handleWebVitals: ReportWebVitalsCallback = (metric) => {
  switch (metric.name) {
    case 'FCP': {
      // handle FCP results
    }
    case 'LCP': {
      // handle LCP results
    }
    // ...
  }
}
 
export function WebVitals() {
  useReportWebVitals(handleWebVitals)
}

Sending results to external systems

You can send results to any endpoint to measure and track real user performance on your site. For example:

function postWebVitals(metric) {
  const body = JSON.stringify(metric)
  const url = 'https://example.com/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 })
  }
}
 
useReportWebVitals(postWebVitals)

Good to know: If you use Google Analytics, using the id value can allow you to construct metric distributions manually (to calculate percentiles, etc.)

useReportWebVitals(metric => {
  // Use `window.gtag` if you initialized Google Analytics as this example:
  // https://github.com/vercel/next.js/blob/canary/examples/with-google-analytics
  window.gtag('event', metric.name, {
    value: Math.round(metric.name === 'CLS' ? metric.value * 1000 : metric.value), // values must be integers
    event_label: metric.id, // id unique to current page load
    non_interaction: true, // avoids affecting bounce rate.
  });
}

Read more about sending results to Google Analytics.

Was this helpful?