Measure a web page's Core Web Vitals with the web-vitals library

1. Before you begin

In this codelab, you learn how to measure a web page's Core Web Vitals with the web-vitals JavaScript library.

Google recommends that you measure Core Web Vitals and that they fall within the 75th percentile of page loads segmented across mobile and desktop devices.

Core Web Vitals include these three metrics, which apply to all web pages and provide you with critical insight into the user experience:

  • Largest Contentful Paint (LCP). Measures load performance and should occur within 2.5 seconds of when the page begins to load.
  • Interaction to Next Paint (INP). Measures interactivity and should occur within 200 milliseconds.
  • Cumulative Layout Shift (CLS). Measures visual stability and should be within 0.1.

Prerequisites

What you'll do

  • Add the web-vitals library to a web page.
  • Measure the web page's Core Web Vitals in Google Chrome Developer Tools.
  • Optional: Report the web page's Core Web Vitals to Google Analytics.

What you'll need

  • A text editor of your choice, such as Sublime Text or Visual Studio Code
  • A Chromium-based web browser, such as Google Chrome or Microsoft Edge (For more information about why you need a Chromium-based web browser, see Browser Support.)

2. Add the web-vitals library to a web page

  1. In your text editor, create a web-vitals-test.html file and then enter this HTML code in the file:

web-vitals-test.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Web Vitals Test</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
  <p><img style="max-width: 360px" src="https://placekitten.com/g/3840/2160" alt="Kitten" /></p>
  <p>Text below image</p>
</body>
</html>

This code creates the web page that you use for this codelab.

  1. In the HTML code's <body> element after the second <p> element, enter this module script and then save the file:

web-vitals-test.html

<script type="module">
  import {onCLS, onINP, onLCP} from 'https://unpkg.com/web-vitals@4?module';

  onCLS(console.log);
  onINP(console.log);
  onLCP(console.log);
</script>

This module script loads the web-vitals library from a content delivery network. Now your file looks like this code snippet:

web-vitals-test.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Web Vitals Test</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
  <p><img style="max-width: 360px" src="https://placekitten.com/g/3840/2160" alt="Kitten" /></p>
  <p>Text below image</p>

<script type="module">
  import {onCLS, onINP, onLCP} from 'https://unpkg.com/web-vitals@4?module';

  onCLS(console.log);
  onINP(console.log);
  onLCP(console.log);
</script>
</body>
</html>

All modern browsers support module scripts, which are a good fit for code that only uses new APIs, such as those required to measure Core Web Vitals. Browsers that don't support modules or the Core Web Vitals APIs won't attempt to load this script.

3. Measure the web page's Core Web Vitals in Google Chrome Developer Tools

  1. In your web browser, open the saved file.
  2. Right-click the web page and then click Inspect in the dialog.
  3. In the Google Chrome Developer Tools pane, click the Console tab and then select Console settings 6a9a7d8992edcd2c.png > Preserve log. This setting ensures that logs persist when you refresh the web page.

74044d63a2f32916.png

  1. Click the Network tab, and then click the c5262a3662ee288c.png expander arrow of the throttling drop-down menu and select Slow 3G. This setting simulates a slow network connection.

The Network tab with the Slow 3G setting selected in the Throttling drop-down menu.

  1. Navigate back to the Console tab, and then click anywhere on the web page. The LCP metric prints in the Console tab.

The Console tab after the LCP metric prints.

  1. Refresh the web page. The CLS metric prints in the Console tab.

The Console tab after the CLS metric prints.

  1. Navigate back to the Network tab, and then click the c5262a3662ee288c.png expander arrow of the throttling drop-down menu and select Fast 3G. This setting simulates a fast network connection.
  2. Navigate back to the Console tab, and then click anywhere on the web page.The LCP metric prints in the Console tab again, but they improved from earlier.

The Console tab after the LCP metric prints again.

  1. Refresh the web page. The CLS metric prints in the Console tab again, but it improved from earlier.

The Console tab after the CLS metric prints again.

4. Optional: Report the web page's Core Web Vitals to Google Analytics

  • In the web-vitals-test.html file after the module script's import statement, enter this sendToGoogleAnalytics() function and then save the file:

web-vitals-test.html

function sendToGoogleAnalytics({name, delta, id}) {
  // Assumes the global `gtag()` function exists, see:
  // https://developers.google.com/analytics/devguides/collection/gtagjs
  gtag('event', name, {
    event_category: 'Web Vitals',
    // Google Analytics metrics must be integers, so the value is rounded.
    // For CLS the value is first multiplied by 1000 for greater precision
    // (note: increase the multiplier for greater precision if needed).
    value: Math.round(name === 'CLS' ? delta * 1000 : delta),
    // The `id` value will be unique to the current page load. When sending
    // multiple values from the same page (e.g. for CLS), Google Analytics can
    // compute a total by grouping on this ID (note: requires `eventLabel` to
    // be a dimension in your report).
    event_label: id,
    // Use a non-interaction event to avoid affecting bounce rate.
    non_interaction: true,
  });
}

onCLS(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);

This code sends the Core Web Vitals to Google Analytics, where you can view them in the Top Events report:

The Top Events report in Google Analytics

Now your file looks like this code snippet:

web-vitals-test.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Web Vitals Test</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
  <p><img style="max-width: 360px" src="https://placekitten.com/g/3840/2160" alt="Kitten" /></p>
  <p>Text below image</p>

<script type="module">
  import {onCLS, onINP, onLCP} from 'https://unpkg.com/web-vitals@4?module';

  function sendToGoogleAnalytics({name, delta, id}) {
    // Assumes the global `gtag()` function exists, see:
    // https://developers.google.com/analytics/devguides/collection/gtagjs
    gtag('event', name, {
      event_category: 'Web Vitals',
      // Google Analytics metrics must be integers, so the value is rounded.
      // For CLS the value is first multiplied by 1000 for greater precision
      // (note: increase the multiplier for greater precision if needed).
      value: Math.round(name === 'CLS' ? delta * 1000 : delta),
      // The `id` value will be unique to the current page load. When sending
      // multiple values from the same page (e.g. for CLS), Google Analytics can
      // compute a total by grouping on this ID (note: requires `eventLabel` to
      // be a dimension in your report).
      event_label: id,
      // Use a non-interaction event to avoid affecting bounce rate.
      non_interaction: true,
    });
  }

  onCLS(sendToGoogleAnalytics);
  onINP(sendToGoogleAnalytics);
  onLCP(sendToGoogleAnalytics);
</script>
</body>
</html>

5. Congratulations

Congratulations! You learned how to measure and report a web page's Core Web Vitals with the web-vitals library.

Learn more