14+ years building on WordPress / Replies in under 5 hours
Performance 8 min read · Updated July 2026

How to Optimize Your WordPress Website for Core Web Vitals in 2025

Photo of Ajay Khandal
Ajay Khandal
WordPress Developer
How to Optimize Your WordPress Website for Core Web Vitals in 2025
TL;DR

Core Web Vitals: LCP (target <2.5s, usually the hero image) is fixed primarily by reducing TTFB via page caching and managed hosting, then optimising the LCP image — WebP format, fetchpriority=high, preload in <head>, no lazy-loading. INP (target <200ms, replaced FID in March 2024) is fixed by reducing JavaScript on the main thread — unloading plugin scripts from pages where they aren't needed, minimising page builder JS, and disabling WooCommerce cart fragments on non-cart pages. CLS (target <0.1) is fixed by setting explicit image dimensions (WordPress 5.5+ does this automatically for block editor images), self-hosting fonts instead of loading from Google, and reserving space for ads/cookie banners. Lab scores (Lighthouse) and field scores (Search Console) frequently disagree — always prioritise Search Console field data, which is what Google uses for ranking.

Core Web Vitals are Google’s three real-world performance metrics — LCP, INP, and CLS — measuring loading speed, interactivity, and visual stability. They’ve been a confirmed ranking signal since 2021 and were updated in March 2024 when Interaction to Next Paint (INP) replaced First Input Delay (FID). This guide covers what each metric actually measures, how to measure them correctly, and the specific WordPress fixes for each.

The three metrics and what they measure

LCP: Largest Contentful Paint — target under 2.5 seconds

LCP measures when the largest element visible in the viewport has loaded. For most WordPress sites, that’s the hero image, featured image above the fold, or a large heading. CSS background images don’t count — LCP is limited to <img> elements, <video> poster images, and text blocks rendered by the browser.

The thresholds: under 2.5s is “Good,” 2.5–4s “Needs improvement,” over 4s “Poor.” These apply to the 75th percentile of real-user page loads — so even if most visitors have a fast experience, the 25% with slower devices or connections determine whether you pass.

INP: Interaction to Next Paint — target under 200ms

INP replaced First Input Delay (FID) in March 2024. The difference matters: FID only measured the delay before the browser started processing the first user interaction after load. INP measures the full latency — from input to the next visual frame update — for any interaction throughout the entire page visit. A page can pass FID easily while failing INP if interactions later in the session (opening a dropdown, clicking a tab, submitting a form) are slow due to heavy JavaScript accumulating on the main thread.

For WordPress sites, INP failures are almost always caused by too much JavaScript loading on every page. Every plugin that loads scripts site-wide increases the risk of Long Tasks that block user interactions.

CLS: Cumulative Layout Shift — target under 0.1

CLS measures unexpected visual shifts during page loading — elements moving as other content loads in. The score is a unitless number representing the cumulative impact of all unexpected shifts. Common causes on WordPress sites: images without explicit dimensions, web fonts causing text reflow as they load, ads injecting into zero-height containers, and cookie consent banners that push content down rather than overlaying it.

How to measure — and why field data and lab data disagree

There are two fundamentally different types of CWV data:

Field data (real-user data) comes from actual Chrome users visiting your site, collected via the Chrome User Experience Report (CrUX). Google Search Console’s Core Web Vitals report shows field data aggregated over 28 days. This is what Google uses for ranking — it’s the measurement that matters for SEO.

Lab data (synthetic data) is what Chrome DevTools, Lighthouse, and the PageSpeed Insights “Diagnose” section show. It’s a controlled test on a simulated mobile device (Moto G Power equivalent, throttled 4G). Lab data is useful for diagnosing specific issues, but the score frequently doesn’t match field data.

A common frustration: 95–100 in Lighthouse while Search Console shows CWV failures. This happens because real users have a range of devices and connections, your LCP image might preload in the lab but not in production, and INP failures from actual interactions can’t be simulated in lab mode. Always prioritise Search Console field data — diagnose with Lighthouse second.

Fixing LCP

LCP improvement runs through three sub-components in order of impact:

Reduce Time to First Byte (TTFB)

TTFB — the time from request to first byte of HTML — is the most overlooked LCP sub-metric. A WordPress site on shared hosting with no caching can have a TTFB of 1–2 seconds before any content starts loading. With that server latency, achieving LCP under 2.5s is nearly impossible regardless of how well images are optimised.

Full-page caching eliminates PHP and MySQL processing time for repeat visits, serving pre-built HTML directly. WP Rocket and LiteSpeed Cache are the two main options — the detailed comparison of their caching approaches, configuration trade-offs, and performance differences is in the WP Rocket vs LiteSpeed Cache guide. For uncached first visits (new visitors, excluded pages, logged-in users), managed WordPress hosting (Kinsta, WP Engine, Cloudways) typically achieves TTFB under 200ms where shared hosting without caching commonly exceeds 800ms.

Optimise the LCP image

Once TTFB is under control, the LCP image is usually the remaining bottleneck. Three changes that reliably improve it:

  • Convert to WebP or AVIF — WebP is typically 25–35% smaller than JPEG at equivalent quality; AVIF is 40–50% smaller. ShortPixel and Imagify convert existing images in bulk and serve WebP automatically to supporting browsers.
  • Don’t lazy-load the LCP image — WordPress 5.5+ adds loading="lazy" to images automatically. This is correct for images below the fold but wrong for the hero or header image. Remove loading="lazy" from your LCP element and add fetchpriority="high" instead.
  • Preload the LCP image — add a <link rel="preload" as="image" href="..."> in the <head> for the hero image. This tells the browser to fetch it before the parser discovers it in the HTML. Most caching plugins have an LCP preload setting.

Add a CDN

A CDN reduces the physical distance between your server and visitors, directly lowering TTFB for geographically distant users. Cloudflare’s free tier serves static assets (images, CSS, JS) from edge nodes worldwide and is the lowest-friction starting point for most WordPress sites.

Fixing INP

INP is the hardest CWV metric to fix on WordPress sites, because the root cause is almost always JavaScript — and WordPress sites accumulate JS from every plugin installed.

Identify what JavaScript is loading and where

Chrome DevTools’ Performance panel (record a page interaction, look for Long Tasks shown in red) reveals which scripts block the main thread. A WordPress site with 15–20 active plugins commonly loads 20–30 separate JS files per page — many of them on pages where the plugin has no function at all.

Unload scripts from pages that don’t need them

Contact form plugins loading their assets on every page of a site are one of the most common INP culprits — a contact form script running on a product page where no form exists wastes main thread resources with no user benefit. Perfmatters and Asset CleanUp Pro both let you disable specific plugin scripts on specific URL patterns. For the underlying mechanism, and how to fix this properly in theme code rather than relying on a disabling plugin, see the guide to properly enqueuing scripts and styles in WordPress.

Evaluate page builder JavaScript

Page builders (Elementor, Divi, WPBakery) load substantial frontend JavaScript on every page to power their interactive and responsive features. This JS increases Long Tasks on the main thread and is a frequent cause of INP failures on builder-built sites. A lightweight block theme or custom theme carries a fraction of the JS footprint. The page builders vs custom code comparison covers the performance trade-offs in detail.

WooCommerce cart fragments

WooCommerce fires an AJAX request on every page load to fetch the live cart count. This admin-ajax.php call runs in the background and can trigger a Long Task that affects INP — it also prevents full page caching on pages where it fires. If your store doesn’t need a live cart counter on non-cart/checkout pages (most stores don’t), disabling cart fragments for those pages improves both INP and cacheability. The WooCommerce performance guide covers this and the other WooCommerce-specific performance bottlenecks in detail.

Fixing CLS

Set explicit image dimensions

The most common CLS cause on WordPress: images without explicit width and height attributes. Without dimensions, the browser doesn’t know how much space to reserve until the image loads, causing surrounding content to shift down. WordPress 5.5+ automatically adds width and height attributes to images inserted via the block editor. If you’re seeing CLS from images, check whether they were inserted via an older method — Classic Editor, custom meta fields, or some plugin output — that doesn’t add these attributes.

Handle web fonts

Google Fonts loaded from fonts.googleapis.com load in two steps: the CSS file, then the font files — creating a window where the browser shows fallback text in a different size, then shifts the layout when the custom font loads. Fix options in order of effectiveness:

  1. Self-host fonts — download font files and serve from your own domain. Eliminates the external request and avoids GDPR concerns about sending visitor IPs to Google’s servers.
  2. Preload the critical font file — add <link rel="preload" as="font" crossorigin> for the primary font weight in your <head>.
  3. Use font-display: swap — shows fallback text immediately; layout shift is smaller than with the default “block” behaviour, though not eliminated.

Reserve space for dynamically injected content

If you run ads, cookie consent banners, or any content injected by third-party scripts after initial render: specify a fixed min-height on the container. A cookie banner that pushes page content down on appearance is CLS; one that overlays content or appears in a sticky footer is not.

Realistic expectations

A perfect Lighthouse score (100/100) doesn’t guarantee good Core Web Vitals in Search Console. Lab data is controlled and repeatable; field data reflects your actual visitors’ devices, connections, and interaction patterns. Most WordPress sites can achieve good LCP and CLS with a page caching plugin, image optimisation, and correct image dimensions. INP typically requires more investigation — specifically identifying which JavaScript loads on each page and removing what isn’t needed there.

For the comprehensive performance checklist targeting a full 100/100 Lighthouse score alongside good field CWV — covering HTTP headers, resource hints, server configuration, and the full script audit process — the WordPress Lighthouse 100 guide covers the complete stack.

If you want a diagnostic review of your current CWV metrics with a specific fix list — which TTFB, LCP, INP, and CLS issues are present and in what order to address them — get in touch. Most CWV audits can be completed with read-only access to your Search Console and PageSpeed data.

Frequently asked questions

The three Core Web Vitals are: Largest Contentful Paint (LCP) — measures when the main content has loaded, target under 2.5 seconds; Interaction to Next Paint (INP) — measures the latency of user interactions throughout the page visit, target under 200ms; and Cumulative Layout Shift (CLS) — measures unexpected visual layout shifts, target under 0.1. All three thresholds apply to the 75th percentile of real-user page loads — meaning 75% of actual visits must meet the target for Google Search Console to rate the page 'Good'. INP replaced First Input Delay (FID) as a Core Web Vital in March 2024.

Page load speed (or 'load time') measures when the browser's load event fires — a technical milestone that may occur before or after what users visually perceive as loaded. LCP is specifically the time until the largest visible element (usually a hero image or large heading) appears in the viewport. LCP correlates more closely with perceived load performance than generic load time because it measures what users actually see, not when network activity finishes. A page can have a 6-second load time but a 1.8s LCP if the main content renders early while non-critical scripts and resources finish loading in the background.

First Input Delay (FID) measured only the delay before the browser started processing the very first user interaction after page load. Interaction to Next Paint (INP), which replaced FID in March 2024, measures the full latency — from input to the next visual paint — for any interaction throughout the entire page visit. A page could pass FID while failing INP if interactions later in the session (accordion clicks, menu opens, form submissions) are slow due to JavaScript accumulating on the main thread. INP provides a more accurate measure of real interactive responsiveness across the full page session, not just the first click.

WP Rocket and LiteSpeed Cache are the two strongest options. WP Rocket works on any host, requires minimal configuration, and includes page caching, file minification, LCP image preloading, and CDN integration in one plugin. LiteSpeed Cache is free and outperforms WP Rocket on LiteSpeed-powered servers (common on Namecheap, A2 Hosting, and some managed hosts) because it uses server-level caching rather than PHP-level caching. On a non-LiteSpeed host, WP Rocket is the stronger choice. W3 Total Cache is more complex to configure correctly and has a higher chance of misconfiguration; it's not the first recommendation for most WordPress sites.

Lab data (PageSpeed Insights' Lighthouse test) and field data (Search Console's real-user measurements) frequently disagree. The lab test runs on a controlled simulated device with a throttled connection; real users vary across mobile and desktop, fast and slow networks, cached and cold visits. Specific reasons the gap occurs: TTFB spikes under real traffic but not in a controlled lab test; the LCP image preloads in the lab but may not in production; INP failures from actual user interactions are impossible to simulate in Lighthouse; third-party scripts (ads, chat widgets, analytics) may not load in the lab but do fire for real users. Always prioritise Search Console field data — it's what Google uses for ranking.

Hosting is the primary driver of Time to First Byte (TTFB), which is the first sub-metric under LCP. A WordPress site on shared hosting with no caching can have TTFB of 1–2 seconds before any content loads — with that server latency, achieving LCP under 2.5s is nearly impossible regardless of image optimisation. Page caching eliminates most TTFB overhead for cached repeat visits. For uncached first visits, managed WordPress hosting (Kinsta, WP Engine, Cloudways) typically achieves TTFB under 200ms; shared hosting without caching often exceeds 800ms. If LCP is consistently failing despite image and script optimisation, measure TTFB separately in Chrome DevTools' Network panel — a high TTFB is a hosting and caching problem, not an image problem.

Photo of Ajay Khandal

Written by Ajay Khandal

I'm a freelance WordPress developer with 14+ years of experience building, fixing, and speeding up sites for businesses, agencies, and store owners across the US, UK, Europe, and Australia. I specialize in custom themes, WooCommerce, and performance — the kind of work that shows up as faster load times and fewer support tickets. No account managers, no outsourced tickets — you work directly with me, with replies typically inside 5 hours.

Work with me →