Skip to Main Content

How to identify & fix Core Web Vitals issues?

In this Case study of my website, I am going to show you how I identify and fix the Core Web Vitals reported on the Page Speed Insights - field data. You will learn what mistakes I made and you can avoid

Pass Core Web Vitals

A huge Thank you to Massimo Villa for the corrections and for giving me more insights. Much appreciate it.

Keywords to remember

  1. Chrome User Experience Report (CrUX).
  2. Page Speed Insights (PSI)
  3. Core Web Vitals (CWV)
  4. Largest Contentful paint (LCP)
  5. Cumulative Layout Shift (CLS)
  6. First Contentful Paint (FCP).
  7. Time To First Byte (TTFB).

I was alarmed to see my Core Web Vitals (CWV) plummeting in June. Despite applying all the optimization techniques I’d learned over the past few years, it wasn’t enough. That experience turned into a valuable learning curve, and I’m eager to share my journey with you.

Curious about how I ultimately passed the Core Web Vitals assessment? Join me as I detail my successes and stumbles, offering clear steps you can follow while avoiding the pitfalls I encountered. Together, let’s ensure your CWV never falters again!

Chrome UX Report (CrUX)

The Chrome User Experience Report (CrUX) provides user experience metrics for how real-world Chrome users experience popular destinations on the web.

You can find my latest website CrUX data here.

Latest CrUX data for

If you want to access your CrUX data/field data. You can do it in multiple ways – 

Google Search Console Report

Core Web Vitals Report

Google Search Console Report suggest there is no Core Web Vitals issue

Page Experience Report

Page Experience Report

While Google Search Console reports good Core Web Vitals and page experience, Page Speed Insights’ field data suggests otherwise. This is because PSI’s field data updates regularly, capturing real-world user experiences that may differ from Search Console’s broader dataset.

The difference between Field Data in Page Speed Insights (PSI) and the CrUX dataset on BigQuery is that PSI’s data is updated daily, while the BigQuery dataset is updated monthly and limited to origin-level data. Both data sources represent trailing 28-day periods.

Page Speed Insights – Field dataI have failed the Page Speed Insights assassement on 26 January 2023

What are the reasons behind the failure of field data in Page Speed Insights?

First Contentful Paint (FCP)-

While inlining the web-vitals JS initiator and lite-YouTube JS into the footer initially improved my FCP and LCP by prioritizing the LCP image, the scores have since declined. This suggests that early execution of these JavaScripts might be negatively impacting performance in other ways.

Cumulative Layout Shift (CLS)

Oops! Revamping my blog post design led to an unexpected CLS spike. ‍♀️

Here’s what happened:

  1. Maintenance Mode: I activated maintenance mode to redesign the blog page safely.
  2. Non-Optimized Page: Visitors got directed to a non-optimized version without critical CSS.
  3. FOUC Strikes: This caused Flash of Unstyled Content (FOUC), where elements briefly jump around before styling loads.
  4. CLS Chaos: The CLS (Cumulative Layout Shift) score, which measures visual stability, skyrocketed—not a good sign for user experience!

Largest Contentful Paint (LCP)

Image CDNs Without Custom Domains: A Detour on the Road to Fast LCP

Initially, I thought it would be better to offload images and videos and serve the images from image CDN because it automatically optimize, serve the images in .avif image format for faster performance. It seemed like a win-win: optimized image delivery and reduced server load. But after a few days of blissful ignorance, reality hit—my LCP score took a nosedive from 1.8 seconds to 2.7 seconds.

How did I identify and fix the issue?

To identify the real issues, I started using the Real User Monitoring (RUM) service to monitor my Core Web Vitals performance daily. First, I used Web Vitals JS libraries but turns out it is very expensive for me (maybe I used too many free available quotas) so I switched to Cloudflare Web analytics (Browsers insights is part of web analytics) which is free to pinpoint the issues that Lab data could not.

What is Real User Experience (RUM)?

Real user monitoring (RUM) tracks and measures the end-user experience in an application, including how long it takes for elements on a web page to load, whether a page has errors, and how long AJAX and HTTP requests take.You can also use RUM to better understand how your users interact with your websites, giving you valuable insights on how to improve your sites and deliver value to your customers.

If you want to know why RUM is so important. You can learn more from the New Relic article.

Many 3rd parties services also offer RUM solutions to help you gather real data from real users and these are the two services I use:

Web Vitals JS

Watch the video above on how to set up web vitals JS (Tutorial I use previously to monitor).

When I start collecting the RUM data. I know exactly the issues I have, & opportunities to improve my web performance like-

  1. Which selectors cause the layout shift,
  2. Whether an image or heading is the Largest Contentful Paint element.

Largest Contentful Paint

Data studio show the highest Metric values by debug target for LCP

Cumulative Layout shift

Data studio shows the highest Matric values by debug target for CLS

Web Vitals JS Libraries: A Game Changer for Performance Optimization

Having access to real-world user data through web vitals JS libraries has been a game-changer for optimizing my website’s performance. Compared to relying solely on lab data, identifying, analyzing, and fixing performance issues is significantly easier and more accurate.

Previously, I used web vitals libraries that lacked support for crucial metrics like Time To First Byte (TTFB), First Contentful Paint (FCP), and Interaction Next Paint (INP). This limited my ability to gain a comprehensive picture of user experience.

If you’re looking for a more advanced solution that tracks all these metrics, I highly recommend checking out Tony McCreath’s article on “Web Site Advantage Core Web Vitals Tracking.” It offers a detailed guide on setting up a comprehensive RUM (Real User Monitoring) solution using web vitals libraries.

Cloudflare’s Browser Insights

If you’re a Cloudflare user, you can leverage its built-in Browser Insights feature to seamlessly collect RUM (Real User Monitoring) data.

I switched to this solution after removing separate web vitals JS libraries, and I’ve been consistently getting similar results for over a week now. Browser Insights offers both automatic JavaScript injection and manual setup options, providing a more convenient and streamlined experience compared to the previous libraries I used.

Largest Contentful Paint

You can see which posts have bad LCP performance

LCP performance from Cloudflare's Browsers insights

Cumulative Layout Shift

CLS performance from Cloudflare's Browsers insights

After you gather all the data from real users, what are the things we can do? The best thing to do is to fix the issues and later we can compare them with the old data.

Deploying Fixes & Comparisons-

You can also see the latest version of my Page Speed Insights’ Field-data 

Page Speed Insights's field-data for 04th May

Largest Contentful Paint (LCP)


To improve the LCP metric:

  1. Optimize and serve webp images using the WebP Express plugin.
  2. Exclude feature images or “Above the fold” or critical images from the lazyloading mechanism. 

Comparisons of Lab data and PSI-field data

Webpagetest result (Lab test)- Ignore the response time

  • Before (Cloudinary/ image CDN) add an unnecessary connection time (around 600ms) to the image (number 6).
  • After: (self-hosted) no unnecessary connection is added to the image.
Webpage test waterfall after the image or critical image is been deliver from ImageCDN which make image load later in waterfall chart
Webpage test waterfall after the image is been self-hosted and make the image loads earlier

Page Speed Insights (Field-data) – We can see the improvement of PSI field data daily.

2.7 sec Largest Contentful paint which is not good Core Web Vitals
After the Largest contentful paint fixes

Cumulative Layout Shift


To fix the CLS issues:

  1. I included the latest CSS in the critical CSS process.
  2. I preloaded my self-hosted fonts. 

PSI-field data

0.11 score on Layout Shift which is bad, it means the content will be move around when the page load which is bad User Expereince
After the fix there is no Cummulative layout detected

First Contentful Paint


To improve my FCP performance:

  1. I remove most of the redundant CSS rules like the !important CSS, and duplicate style.
  2. Remove the unnecessary preconnect call by the Lite-YouTube embedded JS because I never load my YouTube video above-the-fold content.
  3. I start Removing unused CSS from all my posts and inline small CSS using Asset cleanUp Plugins which reduce unnecessary HTTP requests 
//Lite-YouTube JS add the preconnect hint to "" which is good, if the poster image are loading earlier in the viewport
initImagePlaceholder() {
    LiteYTEmbed.addPrefetch('preconnect', '');
    const posterUrlWebp = `${this.videoId}/${this.posterQuality}.webp`;
    const posterUrlJpeg = `${this.videoId}/${this.posterQuality}.jpg`;
    this.domRefImg.fallback.loading = this.posterLoading;
    this.domRefImg.webp.srcset = posterUrlWebp;
    this.domRefImg.jpeg.srcset = posterUrlJpeg;
    this.domRefImg.fallback.src = posterUrlJpeg;
    this.domRefImg.fallback.setAttribute('aria-label', `${this.videoPlay}: ${this.videoTitle}`);
    this.domRefImg?.fallback?.setAttribute('alt', `${this.videoPlay}: ${this.videoTitle}`);
// After

 initImagePlaceholder() {        
    const posterUrlWebp = `${this.videoId}/${this.posterQuality}.webp`;
    const posterUrlJpeg = `${this.videoId}/${this.posterQuality}.jpg`;
    this.domRefImg.fallback.loading = this.posterLoading;
    this.domRefImg.webp.srcset = posterUrlWebp;
    this.domRefImg.jpeg.srcset = posterUrlJpeg;
    this.domRefImg.fallback.src = posterUrlJpeg;
    this.domRefImg.fallback.setAttribute('aria-label', `${this.videoPlay}: ${this.videoTitle}`);
    this.domRefImg?.fallback?.setAttribute('alt', `${this.videoPlay}: ${this.videoTitle}`);



FCP recorded on 26th August
2 sec First contentful paint performance recorded after the fix

This does not happen once, it happens more than twice, from there I learned a lot, here are the tips and caution you need.


  1. If your featured image is a background image, consider preloading the image so browsers discover it earlier or change the design completely.
  2. Reduce your inline CSS size. Unnecessary inlining of CSS can lead to increases in Document/ HTML size which can hurt your Mobile users. Inline assets (CSS, JS, and images) cannot be cached.
  3. Use rel preload and preconnect hints sparingly.


1. The often-overlooked TTFB: A Crucial Player in Core Web Vitals

While many focus on Largest Contentful Paint (LCP) and First Contentful Paint (FCP) for Core Web Vitals, Time to First Byte (TTFB) often gets overlooked. This critical metric, representing the time it takes for the first byte of data to be received from the server, plays a crucial role.

  • Fluctuating TTFB can significantly impact LCP and FCP, as they rely on receiving data from the server first.
  • Here’s a valuable tutorial on optimizing TTFB from


2. Serve LCP Images from the Same Origin: Speed up Your LCP performance 

Serving LCP images or viewport images from different origins is a performance pitfall. Downloading from different sources adds unnecessary time, impacting your LCP score and overall user experience.

  • Always self-host LCP images or use an image CDN that supports custom domain or sub-domain functionalities. This ensures faster loading times and a smoother user experience.

With Cloudinary- Web page test

3. Critical CSS Regeneration: A Must-Do for Style Updates

Updating your website’s style brings the need for critical CSS regeneration. This ensures your pages use the most relevant styles, preventing performance issues.

  • If changing a specific page’s style, regenerate critical CSS for that page only.
  • For site-wide updates, consider regenerating critical CSS for all pages to avoid old styles slowing down the loading process.


4. Inline JavaScript and CSS: A False Friend for Page Speed

Many tutorials advocate inlining CSS and JS for improved page speed scores. However, this approach can be detrimental.

  • Inlined resources can significantly increase page size, leading to slower loading times.
  • Focus on efficient code optimization and resource management instead of inlining.
  • If you’re using Elementor, avoid setting the “CSS Print Method” to “Internal Embedding.” This unnecessarily inlines your frontend CSS, impacting performance.


By following these recommendations and continuously monitoring your Core Web Vitals metrics, you can ensure a fast and smooth user experience for your website visitors.

When I requested Massimo Villa from the altsetup to review my article. He raised an interesting question

Since you use Elementor on your site, why do you use Lite-YouTube embeded instead of the Native Facade (“overlay”) feature replacing YouTube player with local image placeholder?

The answer is quite simple-

  1. No dependencies
  2. Lightweight

What are the alternatives?

If my blog design has lots of features like motion effects ( sticky header, parallax effects, Table of Contents, etc) then there is no point in using the alternative solution.

As you can see from my article, my design is basic and there is no point in adding all the bells and whistles (features) that can only slow down my performance.

lite-Youtube embed VS Elementor Video

My website is built with Elementor and it has a video widget that supports YouTube, Vimeo, Dailymotion & Self-Hosted Video, and other features like Lazy-loading & facade (“image overlay”) as Massimo Villa suggested but the problems when you load the video widget it automatically add all the unnecessary 

YouTube Widget

Elementor Video widget settings

Image overlay (Facade)

Elementor video widget's Overlay feature

// Just to load "/elementor/assets/js/video.1234444....bundle.min.js", this JS handle playback video
// Brotli compression
// jQuery - 32KB
// Frontend - 7.6KB
// frontend-modules - 18.2KB
// webpack.runtime.min.js - 2.8KB + around 1KB for .bundle.min.js


To use all the features I will end up loading over 80KB of JS which sometimes is unnecessary for me whereas lite-youtube JS only loads 3.3KB which is substantially lower and has zero dependencies on jQuery. 

If you want to use lite-youtube embed on your website, you can download the widget from my store.

Lite YouTube embedded JS file size

Image CDN 

Here are some of the 3rd parties image CDN services that offer custom Domain/sub-domain functionalities like-

  1. Shortpixel Adaptive AI
  2. Bunny Optimizer
  3. Imgix
  4. Optimole
  5. Cloudflare images with Offload, Store, Resize & Optimize with Cloudflare Images (You don’t have to use the sub-domain functionalities) 

LuckyWP Table of Contents

Elementor has a Table of Content widget which is super flexible compared to the one I am using right now.

Elementor's Table of Content widgets

For an alternative solution, I use the LuckyWP Table of Contents and set it up to automatically insert headings not via the shortcode method. This plugin is not dependent on jQuery. If you use their shortcode then jQuery will be used to load the table of content items. 

Lucky WP Table of Content settings

Here are some of the plugins I usually recommend and most of them are affiliate links, if you purchase one of them from my links so Thank you for supporting me.

Plugin Recommendations:

All the plugins I recommend below have the feature for generating critical CSS, removing unused CSS, the ability to compress images, CSS and JS, and serving the images in Next-Gen image format automatically such as-

  1. FlyingPress
  2. Wp Rocket
  3. Swift Performance
  4. Perfmatters
  5. Autoptimize + RapidLoad + Critical CSS API + Shortpixel Adaptive AI combined (This is great if you already have Server-side caching & CDN that handle your page level caching & you don’t want any conflict).


  1. Optimizing Largest Contentful Paint- CSSWizardry
  2. A deep dive into optimizing LCP – Google Chrome Developers. (Video)
  3. Web-Vitals JS libraries – Github
  4. Measure and debug performance with Google Analytics 4 and BigQuery-

Deep dive:

  1. Pagespeed Insights – Field Data report vs CrUX
  2. RUM & CrUX difference
  3. Chrome UX report update
  4. Dear WordPress Plugin/Theme Devs, You Don’t Need jQuery by WP Speed Matters.

  5. Highly recommend reading Massimo Villa’s article on how to get 100% in speed tests.


Think your site’s flying in the lab? Wait until you see what real users experience! Yeah, that was me… twice. Trust me, a RUM solution is like a superhero for your website. It reveals the hidden villains (performance issues) that you and your visitors need to avoid. So, don’t be like me. Embrace the RUM, protect your users, and watch your website shine!

Picture of Kishorchand wearing Elementor Blue Shirt that I got it from wining Elementor Header competition

Thangjam Kishorchand Singh

Passionate about web performance, I specialize in assisting individuals and businesses in creating high-speed websites to elevate user experience, improve search rankings, and minimize bounce rates. I continually explore cutting-edge tools and techniques to optimize website performance, sharing insights through informative articles, engaging presentations, and valuable content.

Let's connect on my social media channels to engage in discussions about website speed and transform your site into a lightning-fast online experience.

Follow or chat with me -

Contact Me
Scroll up further to Load all the comments...