Core Web Vitals are Google’s page experience metrics. They affect rankings, and they affect every reader who lands on your site. A blog with poor vitals loads slowly, feels janky to interact with, and bleeds visitors who never say why they left. This post is the practical troubleshooting guide for fixing them.

A Core Web Vitals report showing LCP, INP, and CLS metrics in green, orange, and red bands

What Core Web Vitals are

Google measures three real-world performance metrics from actual Chrome users, not just synthetic lab tests:

  • LCP (Largest Contentful Paint): how long until the biggest visible element loads. Target: under 2.5 seconds.
  • INP (Interaction to Next Paint): how responsive the page feels to clicks and taps. It replaced FID as the official responsiveness metric in March 2024. Target: under 200 milliseconds.
  • CLS (Cumulative Layout Shift): how much the page jumps around as it loads. Target: under 0.1.

Each metric has three bands: Good (green), Needs Improvement (orange), and Poor (red). Google evaluates the 75th percentile of your real visitors against these thresholds, so a handful of slow loads on old phones won’t tank your score by themselves.

Where to measure

PageSpeed Insights

Head to pagespeed.web.dev and enter your URL. It shows both lab data (a synthetic test run right then) and field data (real Chrome users’ actual experience, when enough traffic exists to report it).

The field data is what Google actually uses for rankings. The lab data is what helps you debug.

Google Search Console

Under Search Console, then Core Web Vitals, you’ll find site-wide field data grouped by URL pattern.

This is where you’ll find out which groups of pages have poor vitals, rather than checking one URL at a time.

Chrome DevTools Performance tab

For deep debugging, this shows you exactly what’s blocking rendering and when.

Fixing LCP

LCP is usually the hero image, the post title, or the first paragraph, whichever one renders last.

The hero image is the biggest LCP killer

Common causes worth checking first:

  • The image is too large: an unoptimized JPEG or PNG running several megabytes.
  • The wrong format is in use, like PNG when WebP would work just as well and load faster.
  • The image is lazy-loaded when it shouldn’t be. Anything above the fold should never be lazy-loaded.
  • Image dimensions aren’t set in the markup.
  • The image is served from a slow source, like a leftover Squarespace CDN link after a migration, or a hot-linked image from another site.

Fixes

  • Convert featured images to WebP using a plugin like Imagify, ShortPixel, or Smush.
  • Resize before uploading. Featured images rarely need to be 4000px wide; 1800px is plenty for nearly every layout.
  • Set fetchpriority="high" on the hero image. Most modern themes and SEO plugins do this automatically, but it’s worth verifying.
  • Exclude above-the-fold images from lazy loading entirely.
  • Preload critical font files so text doesn’t wait on a font request.
  • Self-host fonts instead of pulling from the Google Fonts CDN, which removes one DNS lookup from the critical path.

Render-blocking scripts

JavaScript and CSS loaded in <head> blocks rendering until it finishes, which eats directly into your LCP time.

The fix:

  • Move non-essential JavaScript to the footer.
  • Add defer or async to script tags where it’s safe to do so.
  • Caching plugins like WP Rocket or FlyingPress handle this automatically once configured.
  • Remove unused plugins. Every plugin you keep adds its own scripts to the page.

Fixing INP

INP measures how quickly the page actually responds once a user interacts with it.

Main causes

  • Heavy JavaScript running on the page.
  • Third-party scripts, especially ads, analytics, and embed widgets.
  • Inefficient event handlers that block the main thread.
  • A bloated DOM with too many elements for the browser to manage.

Fixes

  • Reduce overall JavaScript volume. Audit your plugins, since each one adds its own scripts.
  • Lazy-load third-party embeds: YouTube via lite-youtube-embed, social embeds via plugins that defer loading until they’re needed.
  • Delay non-critical JavaScript until the user actually interacts with the page. WP Rocket’s “Delay JavaScript Execution” feature does exactly this.
  • Use a code-splitting or modern asset pipeline if you’re customizing themes directly.

Ads and INP

Ad scripts are the single biggest INP killer on monetized blogs.

  • Lazy-load ad slots so ads don’t load until the user scrolls near them.
  • Reduce overall ad density on the page.
  • Mediavine and Raptive optimize this internally as part of their service; AdSense Auto Ads does much less of that work for you.

Fixing CLS

CLS is essentially “things moving around while the page loads.” It’s frustrating for readers, and thankfully one of the easier metrics to fix.

Common causes

  • Images without width and height attributes, so the browser doesn’t know how much space to reserve before the image loads.
  • Ads loading in and pushing content down the page.
  • Embeds like tweets or Instagram posts loading and resizing after the fact.
  • Web fonts loading late and causing text to reflow.
  • Dynamically injected content, like cookie banners or popups, shoving everything else around.

Fixes

  • Set width and height on every <img> tag. Modern WordPress does this automatically for images added through the media library.
  • Reserve fixed space for ad slots by setting a min-height on ad containers.
  • Reserve space for embeds using the CSS aspect-ratio property or fixed dimensions.
  • Use font-display: optional or swap paired with size-adjust to minimize the visible reflow when fonts load.
  • Avoid injecting elements above existing content. A banner that appears at the top and pushes everything else down is a classic CLS spike.
A waterfall chart showing render-blocking resources and how to optimize them

WordPress-specific optimization steps

1. Caching

This is essential. Caching reduces TTFB (time to first byte), which directly feeds into your LCP score.

  • WP Rocket: paid, and the simplest to configure.
  • LiteSpeed Cache: free, but only if your host runs LiteSpeed.
  • W3 Total Cache: free, though more complex to set up well.
  • WP Super Cache: free and straightforward.

Our full guide to setting up WordPress caching covers configuring any of these in more depth.

2. Image optimization

  • Convert images to WebP.
  • Resize uploads before adding them to the media library.
  • Use a CDN with built-in image optimization, like Cloudflare’s Polish or Bunny.net’s optimizer.

See our complete image optimization guide for the full process, from compression settings to lazy loading.

3. Reduce plugin count

Every plugin adds JavaScript, CSS, and PHP overhead, whether you use it daily or not. Worth auditing:

  • Remove plugins you haven’t used in the last 30 days.
  • Replace several single-purpose plugins with one well-built multi-purpose plugin where that makes sense.
  • Avoid plugins that load assets sitewide for a feature that’s only used on one page.

4. CDN

Cloudflare’s free tier handles static asset delivery, basic optimization, and DDoS protection at no cost.

For better performance beyond that: Cloudflare Pro or Business, or BunnyCDN.

5. Database optimization

Old WordPress sites quietly accumulate post revisions, transients, and spam comments over time.

  • WP-Optimize cleans up the database for you.
  • Limit post revisions directly in wp-config.php to stop the accumulation at the source.

6. Hosting

Cheap shared hosting is often capped at slow PHP execution speeds no plugin can fix.

Upgrading to managed WordPress hosting, such as SiteGround GoGeek and above, WP Engine, or Kinsta, produces a measurable Core Web Vitals improvement in most cases.

Common WordPress performance plugins

  • WP Rocket: caching, CSS/JS optimization, lazy loading, and delayed JS. Paid, starting around $59/year.
  • FlyingPress: a similar feature set, often with faster results. Starting around $60/year.
  • LiteSpeed Cache: free, but requires a LiteSpeed-based host.
  • Perfmatters: targeted optimizations like disabling scripts per page and lazy-loading embeds. Starting around $24.95/year.
  • Autoptimize: a free option for CSS and JS optimization.

The 80/20 priority list

If you only have time for five things, do these:

  1. Convert images to WebP.
  2. Install a caching plugin and enable the basic options.
  3. Set up Cloudflare in front of your site.
  4. Audit and remove unused plugins.
  5. Lazy-load YouTube embeds.

Those five changes alone usually move a poor-vitals site to a passing one.

Quick tip: retest a few hours after any fix, not immediately. Field data in PageSpeed Insights is a rolling 28-day average, so a single retest right after a change often still reflects the old numbers.

Mobile vs desktop

Google primarily uses mobile data for ranking purposes. Mobile is the harder environment to optimize for because of:

  • Slower CPUs on most phones compared to desktops.
  • Slower and less consistent networks.
  • Smaller screens, which change which element actually counts as your LCP.

Always test on mobile through PageSpeed Insights. Passing on mobile is the real goal, not just passing on desktop.

What “good enough” looks like

You don’t need a perfect 100/100 score. The real targets are:

  • LCP under 2.5 seconds on mobile.
  • INP under 200 milliseconds.
  • CLS under 0.1.

That’s “Good” across all three metrics. Chasing a perfect Lighthouse score past that point has sharply diminishing returns for the time it costs.

Monitoring over time

Set up ongoing monitoring rather than checking once and forgetting about it:

  • Google Search Console’s Core Web Vitals report, checked weekly.
  • PageSpeed Insights, checked occasionally.
  • Real User Monitoring through Cloudflare Web Analytics or a similar third-party tool.

Vitals can quietly degrade as you add plugins, third-party scripts, or larger images over time. Catching regressions early is much easier than untangling six months of accumulated slowdowns at once. WordPress.org’s own performance optimization documentation is a good place to check when a new plugin introduces a regression you can’t immediately explain.

Where your theme comes in

A lot of this troubleshooting exists because themes and page builders ship more markup, more CSS, and more JavaScript than a blog actually needs. Aurora was built specifically to avoid that: clean output, properly sized images, and no bloated builder framework running underneath. If you’re fighting Core Web Vitals on a heavier theme, switching to something built lighter from the start often does more for your scores than any single plugin fix on this page, and our guide to how Aurora affects Core Web Vitals walks through the specifics.

Where the real gains hide

Core Web Vitals affect both rankings and how a reader experiences your site. LCP is usually your hero image or render-blocking scripts. INP is JavaScript-heavy plugins and ad scripts. CLS is unreserved space for images, ads, and embeds. The WordPress fixes are well established at this point: WebP conversion, a caching plugin, Cloudflare, a plugin audit, and lazy-loaded embeds. You don’t need a perfect score. You need green across all three, and a system for noticing when that slips.