Your Guide to Google Core Vitals in 2024

July 31, 2024
Analytics / Performance

Whether you’re a web content manager, digital marketing professional, tech manager, or developer, you know that Google uses its Core Vitals metrics to evaluate your website’s page speed and overall on-page user experience — and serves up rewards or penalties accordingly with search results rankings. Unfortunately, the algorithms they use are always a moving target.

Here’s a look at where Core Vitals currently stands and how you can best position your site to adapt to recent changes.

Don’t have time to dig into the details below? Use this simple checklist for easy wins in improving your Core Vitals score.

The Quick Core Vitals Checklist

  • Serve responsive WebP image files sized to appropriate browser widths via lazy loading.
  • Compress javascript and CSS files — and only serve them as needed for each specific page.
  • Use a caching mechanism/content delivery network like Varnish, Cloudflare, or Fastly.
  • Remove third-party scripts you no longer need.
  • Don’t use an economy or shared hosting plan.
  • Limit animations that fire as soon as pages load.
  • Provide a loading indicator for events that aren’t instantaneous.

The Three Core Vitals Metrics for SEO in 2024

Largest Contentful Paint

What It Is: Essentially, this is the most complicated graphical element shown on the screen, usually an image or a video. Note that it’s not the largest download, but rather the part of the visible area of the page that took the most time and processing power to render.

Why It Matters: From the W3C docs, “The largest paint during the loading process of the page is likely to signify a meaningful event from the user’s perspective”. The assumption is that the page probably isn’t useful until this big important thing is fully loaded.

 

HOW TO IMPROVE LARGEST CONTENTFUL PAINT (LCP) IN CORE VITALS:

  • The biggest contributors to LCP are images and video. For starters, if you have large images or videos on your page, ask whether they add value to the user experience. Especially on small screen sizes, sometimes the best thing to do is to eliminate large hero and banner images that the user simply has to scroll beyond to get to the content.
  • Make sure you’re using a content delivery network or other caching layer. Varnish, Cloudflare, Fastly, and similar services are inexpensive and significantly improve the speed of your site by serving up stored snapshots of pages, images, and videos rather than repeatedly regenerating the same pages from scratch. This is critical because the “time to first byte” — the time it took for the browser to get a response when it requested a file — accounts for 40% of the LCP score.
  • Serve compressed images in the WebP image format. Even large images should have less than 300KB file size, and lower file size is always better unless it causes degradation of the image quality. Serving raw, uncompressed images wastes time and data transfer and negatively impacts your LCP score. Most CMS platforms can automatically compress & convert images to the WebP format.
  • Serve responsive image files that are sized to the appropriate browser width. For example, you don’t need to download a full-size image to display on a small mobile phone. Keep in mind, however, that just because the image appears smaller doesn’t mean the file itself is smaller, so you’ll have to ensure your CMS generates multiple separate image files for different screen sizes.
  • Use the built-in lazy loading attribute (loading=”lazy”) on images and/or a third-party library or plugin from your CMS or front-end framework to ensure that images aren’t transferred from the server until they’re needed. You don’t want to waste time and processing power if you have images at the bottom of the page, but the user never scrolls that far.
  • Use preload tags so your browser starts downloading the largest images as soon as it begins loading the page. Otherwise, it won’t start downloading the largest element until it encounters it on the page, which may be later in the loading process.
  • Use a fast, non-shared hosting platform with its own caching layer so that requests to the server are returned to the browser as quickly as possible. You don’t have to break the bank on hosting, but if you’re on a shared plan, you’re competing with other websites for available resources on your same server. We recommend:

WPEngine (WordPress)


Pantheon (WordPress & Drupal)

Acquia (Drupal)


Platform.sh (WordPress, Drupal, and others)

A laptop with a Largest Contentful Paint document on the screen. LCP (Largest Contentful Paint) graph: Good (0 to 2.5 sec), Need Improvement (2.6 to 4.0 sec), Poor (> 4.0 sec)” src=”https://www.easternstandard.com/wp-content/uploads/2024/07/1-Image-LCP-and-W3-880×433.png” class=”block-image__image” loading=”lazy” is=”block-lazy-image”></picture></div><div class=


Interaction to Next Paint (INP)

What It Is: After a page has loaded, interaction to next paint measures how quickly the page responds to clicks, taps, or key presses. For example, if a user clicks something on the page (expanding an accordion, for example) and it pauses for a brief section before anything happens, that’s a slow INP.

INP replaced First Input Delay (FID) in 2024. Whereas FID measures only the first interaction on the page, INP measures all of them. 

Why It Matters: Users expect the experience on the page to be responsive to clicks and taps. If the page feels “laggy,” users are more likely to abandon the page for something else. It can also create a confusing experience if it’s unclear whether a click or a tap actually registered.

HOW TO IMPROVE INTERACTION TO NEXT PAINT (INP) IN CORE VITALS:

  • Your HTML should be as clean and minimal as possible so the Document Object Model (DOM) is as lean as it can be. The fewer HTML elements on the page, the less work the page has to do to update its state.
  • Make your interactions depend on as few scripts as possible. Sometimes, the page is rendered (i.e., displayed to the user) but because the scripts are still loading or processing, an element isn’t really ready for a user to interact with it. Remember to periodically go through all your third-party scripts and remove anything you no longer need: old tracking pixels, third-party software, irrelevant libraries, etc.
  • Limit animations that fire as soon as the page is loaded. It might look nice to have everything fade and slide into view, but the user has to wait for these actions to finish before they can fully interact with the page.
  • For animations and other changes that occur when a user clicks or taps, use CSS animations in place of javascript wherever possible. In all cases, minify/compress your javascript and CSS files to make them as small as possible. Your CMS should have minification built in or available as a plugin (Drupal has built-in minification — if enabled — and an advanced aggregation module. WordPress has autoptimize and others.)
  • Don’t compile all your javascript and CSS into a large file and serve it on every page; instead, only serve what you need for each specific page.
  • If you have a series of steps that run when a user interacts with an element, run those steps in different “frames” by using requestAnimationFrame. There’s a good example of this approach in the Optimize INP docs on web.dev
  • For any events (e.g., click, tap) that aren’t instantaneous (i.e., loading a next page, etc.), show a loading indicator of some kind as soon as the user initiates the event; that way there’s immediately a “next paint.”

Another important note about INP can be found in the INP docs: “Therefore, the intent of INP is not to measure all the eventual effects of an interaction—such as network fetches and UI updates from other asynchronous operations—but the time that the next paint is being blocked. By delaying visual feedback, users may get the impression that the page is not responding quickly enough, and INP was developed to help developers measure this part of the user experience.”

 

Cumulative Layout Shift (CLS)

What It Is: As a page loads, you may notice that some elements “bounce” around a bit for settling into place. That bouncing is the “layout shift” and it should be avoided as much as possible.

Why It Matters: Having page elements shift while a user is trying to interact with them leads to a frustrating user experience.

 

HOW TO IMPROVE CUMULATIVE LAYOUT SHIFT (CLS) IN CORE VITALS

  • Assign a width and height to all images. Otherwise, the page will readjust to fit the image after it’s loaded, leading to layout shift.
  • Utilize CSS transitions instead of javascript for changing the position of elements.
  • If using scripts that add content to a page (e.g., ads), leave enough empty space in the layout for the new content to fit without forcing the layout to readjust.
  • Load any scripts that alter the DOM as early as possible; inline script is usually best wherever possible.
Drupal, WordPress, and Plugin symbols

The Best WordPress Plugins for Google Core Vitals

These WordPress plugins provide many of the features you need to elevate your Core Vitals score:

WebP Express — Automatically converts your images to the WebP format


WebP Converter for Media — Another plugin for converting images to the WebP format


Autoptimize — Compresses & combines CSS and javascript files

Rocket Lazy Load — “Lazy” loads images so that only images that are displayed to the end user are downloaded from the server


Smush — WebP converter and lazy loader for images

The Best Drupal Modules for Google Core Vitals

If you’re using Drupal, improve your Core Vitals score using these modules:

WebP — Automatically converts your images to the WebP format using Drupal image styles


Lazy Load — “Lazy” loads images so that only images that are displayed to the end user are downloaded from the server

Advanced Aggregation — Adds additional compression & aggregation features to Drupal’s built-in CSS and Javascript aggregation capabilities.

How to Defer Google Tag Manager Scripts for Better Core Vitals Scores

This recommendation will probably require help from your web developer, but it can help immensely with your core vitals scores.

You may have noticed that “Minimize main-thread work” and “Reduce Javascript execution time” appear in your PageSpeed Insights reports. If you’ve eliminated from Google Tag Manager all the scripts you can do without, you may think you’ve done all you can.

However, you can defer the loading of your Google Tag Manager scripts (i.e. allow the page to render before it executes them) so they don’t have as much impact on page loading. You probably don’t want to defer your main Google Analytics tag, so we’ve actually been creating two separate Google Tag Manager Containers — one with our Analytics tag and one with everything else — and deferring the “everything else” container. The steps are as follows:

  1. Create a new container in your Google Tag Manager account. We usually name this “Non-Deferred Tags”
  2. Rename your existing container “Deferred Tags”
  3. Add your “Google Tag” (the one that is responsible for GA4 tracking) to the “Non-Deferred Tags” container
  4. Disable the “Google Tag” in the “Deferred Tags” container
  5. Make sure the “non-deferred” Google Analytics tag is added to your site’s <head> tag
  6. The “deferred” tag can go at the bottom of the body tag, but there’s one very important step to take here: in the tag manager snippet, before “j.src”, you’ll want to add “j.defer=true;”, allowing the tag to be deferred. Example code is below.
  7. Once everything is in place, make sure to publish your changes on both Google Tag Manager containers

So your template will look something like this:

<head>
<!-- Google Tag Manager NON-Deferred tags -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-ABC123');</script>
<!-- End Google Tag Manager -->
</head>
<body>
<script>
// Separate Google tag manager for deferred scripts. Notice that j.defer is true.
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});
var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.defer=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XYZ789');
</script>
</body>

Need help with improving your Google Core Vitals as part of your overall digital strategy? Let’s talk.