Skip to content

How to set up analytics

Next.js has built-in support for measuring and reporting performance metrics. You can either use the useReportWebVitals hook to manage reporting yourself, or alternatively, Vercel provides a managed service to automatically collect and visualize metrics for you.

Client Instrumentation

For more advanced analytics and monitoring needs, Next.js provides a instrumentation-client.js|ts file that runs before your application's frontend code starts executing. This is ideal for setting up global analytics, error tracking, or performance monitoring tools.

To use it, create an instrumentation-client.js or instrumentation-client.ts file in your application's root directory:

instrumentation-client.js
// Initialize analytics before the app startsconsole.log('Analytics initialized')// Set up global error trackingwindow.addEventListener('error', (event) => {// Send to your error tracking servicereportError(event.error)})

Build Your Own

pages/_app.js
import { useReportWebVitals } from'next/web-vitals'functionMyApp({ Component, pageProps }) {useReportWebVitals((metric) => {console.log(metric) })return <Component {...pageProps} />}

View the API Reference for more information.

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.

pages/_app.js
import { useReportWebVitals } from'next/web-vitals'functionMyApp({ Component, pageProps }) {useReportWebVitals((metric) => {switch (metric.name) {case'FCP': {// handle FCP results }case'LCP': {// handle LCP results }// ... } })return <Component {...pageProps} />}

Custom Metrics

In addition to the core metrics listed above, there are some additional custom metrics that measure the time it takes for the page to hydrate and render:

  • Next.js-hydration: Length of time it takes for the page to start and finish hydrating (in ms)
  • Next.js-route-change-to-render: Length of time it takes for a page to start rendering after a route change (in ms)
  • Next.js-render: Length of time it takes for a page to finish render after a route change (in ms)

You can handle all the results of these metrics separately:

exportfunctionreportWebVitals(metric) {switch (metric.name) {case'Next.js-hydration':// handle hydration resultsbreakcase'Next.js-route-change-to-render':// handle route-change to render resultsbreakcase'Next.js-render':// handle render resultsbreakdefault:break }}

These metrics work in all browsers that support the User Timing API.

Sending results to external systems

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

useReportWebVitals((metric) => {constbody=JSON.stringify(metric)consturl='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 }) }})

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-analyticswindow.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.

close