Fixing Core Web Vitals in WordPress
WordPress itself is not slow, but a typical WordPress site is built from a theme, a page builder and a couple of dozen plugins, each adding its own scripts, styles and database queries.
Core Web Vitals failures on WordPress almost always trace back to three things: pages built from scratch on every visit, plugins loading code on pages that do not use it, and heavy builder layouts. This guide works through the WordPress-specific fixes in order of impact, using the tools and settings WordPress already provides, and explains where optimisation plugins help and where they cause new problems.
Where WordPress sites lose their Core Web Vitals
| Metric failing | Usual WordPress cause | First thing to check |
|---|---|---|
| LCP | No page cache, so PHP and the database build every page; hero image set as a CSS background by a builder; slider plugin on the home page | Response headers for a cache hit, and which element is LCP |
| INP | Many plugins adding JavaScript to every page; pop-ups, chat, social feeds and several tracking tools running together; very deep builder markup | Long tasks in a throttled DevTools recording and which plugin files own them |
| CLS | Announcement bars and cookie notices pushing content down; sliders that start at zero height; fonts from an external service swapping late; ads injected by a plugin | Layout Shift Regions at phone width |
The thresholds are the same as on any site: LCP 2.5 seconds or less, INP 200 milliseconds or less and CLS 0.1 or less at the 75th percentile of real visits. What is specific to WordPress is where the weight comes from, and the fact that most of it was added by installing something rather than writing code.
What recent WordPress versions already do for you
- Image dimensions and lazy loading. Core adds
widthandheightto images inserted through the editor and addsloading="lazy"to images it expects to be below the fold. - Hero image priority. Since WordPress 6.3, core tries to skip lazy loading on the
image most likely to be the LCP element and adds
fetchpriority="high"to it. - Script loading strategies. Since 6.3, themes and plugins can register scripts with
a
deferorasyncstrategy. - Local fonts. The Font Library added in 6.5 stores fonts installed through it on your own site rather than loading them from a third party.
- Responsive images. Core has generated
srcsetandsizesfor content images for many years.
These only help if the theme and plugins do not work around them. A builder that outputs its own image markup, or a theme that prints the hero through CSS, bypasses all of it.
The fix, step by step
Step 1
Measure each template, not just the home page
List one URL for each template: home, a page, a post, an archive, and on WooCommerce a product, a category and the basket. Run each through the Core Web Vitals checker and note which metric fails on mobile and desktop. Search Console groups similar URLs, so match each group to a template. A failing product template affects every product at once, which makes it a far better first target than a single slow landing page.
Step 2
Put a page cache in front of WordPress
Check
the response headers of a logged-out page for a cache status from your host, CDN or caching plugin. If
there is none, WordPress is running PHP and database queries for every visit. Turn on your host's page
cache if it has one, otherwise use a single caching plugin or a server-level cache. Exclude basket, checkout
and account pages, and make sure tracking parameters such as utm_source do not bypass the
cache.
Step 3
Find the heavy plugins with Query Monitor
Install Query Monitor on a staging copy and load each template while logged in as an administrator. Its panels list database queries grouped by the plugin that ran them, slow queries, and every script and stylesheet enqueued on the page with the plugin that added it. Note plugins that add code to pages where they do nothing, and those with slow or repeated queries. Replace or remove plugins you no longer need, then deactivate Query Monitor when finished.
Step 4
Let WordPress prioritise the hero image
Find the LCP element in a DevTools recording at phone width. If it is an image, it should
be an ordinary img in the HTML, without loading="lazy", and ideally with fetchpriority="high".
If a builder sets the hero as a CSS background, or a slider loads it with JavaScript, the browser finds
it late. Switch that section to an image block or widget, and replace the home page slider with a single
static image.
Step 5
Load plugin scripts only where they are used
For each plugin that loads code everywhere, find its script and style handles in
Query Monitor and dequeue them on pages that do not need them, using a small snippet in a child theme
or a site plugin. Check whether the plugin has its own setting to load only where used. For your own
theme scripts, register them with the defer strategy. Test forms, menus and checkout carefully
after each change, because some plugins expect their scripts on every page.
Step 6
Host fonts locally with a matched fallback
If the theme loads fonts from an external font service, host them on your own site instead,
through the Font Library, the theme settings or by uploading the files and declaring them in CSS. Limit
the site to the weights you actually use, preload only the one or two files needed for text in the first
screen, and use font-display: swap with a fallback font adjusted using size-adjust
so text does not reflow when the web font arrives.
Step 7
Slim down builder layouts and the theme
Page builders wrap each element in several containers, and long pages can reach thousands of DOM nodes, which slows styling and interaction. Remove unused sections, flatten nested rows and columns, and turn on any builder settings that reduce markup or load assets only for widgets on the page. Where a builder page is still heavy, rebuilding the key templates with the block editor and a lightweight block theme usually produces far less code.
Step 8
Retest on staging, then in the field
After each change, rerun the Core Web Vitals checker against staging and repeat a throttled DevTools recording, checking LCP, long tasks and layout shift regions. Click through forms, the basket and checkout to be sure nothing broke. Deploy one group of changes at a time and keep a note of what changed and when. Field data in the Chrome UX Report and Search Console improves over a rolling 28 days.
Snippets for child themes and site plugins
Put these in a child theme's functions.php or, better, a small site-specific plugin so
theme updates do not remove them. Test on staging first.
Dequeue a plugin's files where they are not used
add_action( 'wp_enqueue_scripts', function () {
// Handles found in Query Monitor's "Scripts" and "Styles" panels.
if ( ! is_front_page() ) {
wp_dequeue_script( 'example-slider' );
wp_dequeue_style( 'example-slider' );
}
if ( ! is_page( array( 'contact', 'book-a-visit' ) ) ) {
wp_dequeue_script( 'example-forms' );
wp_dequeue_style( 'example-forms' );
}
}, 100 );
The priority of 100 makes the snippet run after most plugins have enqueued their files. Handle names differ between plugins, so copy them exactly from Query Monitor.
Load your own scripts with defer
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_script(
'site-menu',
get_stylesheet_directory_uri() . '/js/menu.js',
array(),
'1.4.0',
array( 'strategy' => 'defer', 'in_footer' => true )
);
} );
Give a theme's hero image priority
If your theme outputs the hero with wp_get_attachment_image(), you can pass the loading attributes directly:
echo wp_get_attachment_image(
$hero_id,
'full',
false,
array( 'loading' => 'eager', 'fetchpriority' => 'high', 'sizes' => '100vw' )
);
fetchpriority="high" to several images on a page. Raising
the priority of everything is the same as raising the priority of nothing, and it can delay the real
LCP image.Optimisation plugins: what helps and what backfires
Performance plugins bundle many options together. Some settings are reliably helpful; others trade one problem for another.
| Setting | Verdict | Why |
|---|---|---|
| Page caching | Usually the biggest win | Removes PHP and database time from logged-out requests, which directly shortens TTFB and LCP. |
| Image compression and modern formats | Helpful | Smaller files download faster, especially on mobile. |
| Minify CSS and JavaScript | Small gain, low risk | Removes whitespace and comments; check nothing breaks. |
| Combine files | Often not worth it | With HTTP/2 and HTTP/3, many small files are fine, and one large combined file can delay everything. |
| Remove unused CSS / generate critical CSS | Helpful but test carefully | Can speed up first paint, but menus, pop-ups and content that appears later may lose their styles. |
| Delay JavaScript until interaction | Use selectively | Improves lab scores, but delayed scripts all run on the first tap, which can make that interaction slow and hurt INP. Delay only tags nobody needs straight away. |
| Lazy load everything | Harmful above the fold | Lazy loading the hero delays LCP. Exclude the first images on each template. |
WooCommerce specifics
Shops add work that brochure sites do not have. Product, category and basket pages all have different needs.
- Cart fragments. Some themes refresh the mini-basket with a request on every page load. That request cannot be cached and adds main thread work. Many themes and recent WooCommerce versions limit this; check whether yours still does it on every page.
- Uncacheable pages. Basket, checkout and account pages must bypass the page cache, so their speed depends on the database and plugins. An object cache such as Redis and a review of slow queries in Query Monitor help most here.
- Product galleries. Galleries with zoom and lightbox scripts are often the heaviest part of a product page. Make sure the main image is an ordinary image with dimensions, and that zoom scripts load without blocking it.
- Filters. Category filter plugins can run heavy queries and re-render large parts of the page on each click, which hurts INP.
For crawl and indexing issues on shops, see the WooCommerce crawl guide.
Edge cases
- Fast when logged in, slow for visitors, or the reverse. Administrators usually bypass the page cache and load the admin bar. Always test logged out in a private window.
- Scores change after a plugin update. Updates can add new scripts or change how assets load. Recheck key templates after updating large plugins or the theme.
- Host-level optimisation. Some managed hosts rewrite HTML, add their own lazy loading or minify files. If a change you make seems to have no effect, check whether the host is overriding it.
- Front-end admin-ajax requests. Front-end requests to
admin-ajax.phpfrom plugins bypass page caching and can be slow. Query Monitor and the DevTools Network panel show them. - Emoji and embed scripts. Core's emoji detection and oEmbed discovery scripts are small; removing them saves very little and is rarely the reason a page fails.
Keeping a WordPress site fast
- Treat every plugin as a cost. Before installing one, check what it loads on the front end and on which pages.
- Keep a staging site and test theme, builder and plugin updates there before production.
- Review plugins twice a year and remove anything unused; some leave code behind in the database or theme, so check after removing.
- Set editor rules for image size and for how many embeds and widgets a page may use.
- Watch the field data for each template group in Search Console, not just the home page.
For the individual metrics, see slow LCP, poor INP, slow TTFB and CLS in WordPress.
1. Why does my WordPress site fail Core Web Vitals?
The most common reasons are no page cache, so every visit waits for PHP and the database to build the page; plugins that load their scripts and styles on every page whether they are used or not; and page builder layouts with a very large amount of markup. Sliders, pop-ups, chat widgets and several tracking tools running together add to the load. Check which metric is failing and on which template before deciding which of these to fix first.
2. Which caching plugin should I use?
Start by checking whether your host already provides a page cache, because many managed WordPress hosts do and adding a plugin on top can cause conflicts. If there is none, any well-maintained caching plugin that supports page caching, exclusions for basket and account pages, and cache purging on content updates will do the core job. Use one caching solution only, and confirm it works by checking response headers on a logged-out page for a cache hit.
3. Is a page builder bad for Core Web Vitals?
Not automatically, but builders make it easy to produce heavy pages. Each element is wrapped in several containers, pages can reach thousands of DOM nodes, and some builders load their full set of styles and scripts on every page. That slows rendering and interaction, especially on phones. Most builders now have settings to reduce markup and load only the assets a page uses. For the most important templates, the block editor with a lightweight theme usually produces less code.
4. Should I use a plugin that delays all JavaScript?
Use that setting carefully. Delaying scripts until the first interaction makes lab tests look better because the scripts do not run during loading. But when a visitor first taps or scrolls, all the delayed scripts run together, which can make that first interaction slow and hurt INP, and features such as menus or forms may not work until then. Delay only scripts that nobody needs straight away, such as some tracking tags, and test every interactive element.
5. Does WordPress add fetchpriority to images automatically?
Since WordPress 6.3, core tries to identify the image most likely to be the Largest Contentful Paint element, skips lazy loading on it and adds fetchpriority high. This works for images output through core functions and blocks. It cannot help when a theme or page builder outputs its own image markup, sets the hero as a CSS background, or loads it through a slider script. Check the rendered HTML of your hero to see what actually reaches the browser.
6. How many plugins is too many?
There is no fixed number. What matters is what each plugin does on the front end. A plugin that only adds an admin screen costs visitors nothing, while a single social feed or pop-up plugin can add several scripts and slow database queries to every page. Use Query Monitor to see which plugins load files and run queries on each template, and judge each plugin by that rather than counting how many are installed.
7. Will moving to better hosting fix Core Web Vitals?
Better hosting mainly improves Time to First Byte, which helps LCP, and it helps most for pages that cannot be cached, such as basket and checkout. It does not fix INP problems caused by JavaScript running in the visitor's browser, or layout shifts caused by the theme. If your pages already come from a page cache and TTFB is fast, look at plugins, the theme and images before spending money on new hosting.
The Core Web Vitals checker shows real-user field data and a Lighthouse lab test side by side for your URL, breaks down each metric and points to the assets and code behind every failure, so you can see which theme or plugin files are slowing each template.
Open Core Web Vitals Fixes โ