Let’s journey together from facing challenges to achieving success in optimizing Core Web Vitals (CWV) and enhancing user experiences. With a nod to Massimo Villa for insightful guidance, here’s what you need to know:

  • Accessing CWV Reports: Learn how to access CWV reports and understand the differences between tools like Page Speed Insights (PSI) and Chrome User Experience Report (CrUX).
  • Identifying CWV Issues: Discover common CWV issues like First Contentful Paint (FCP), Cumulative Layout Shift (CLS), and Largest Contentful Paint (LCP), along with effective solutions to address them.
  • Harnessing Real User Monitoring (RUM): Explore the power of Real User Monitoring (RUM) for gaining insights from real-world data and refining CWV tracking with advanced solutions.
  • Prioritizing User Experience: Above all, prioritize user experience and CWV optimization to ensure your website excels in the digital realm.

With these insights, you’ll be better equipped to navigate CWV optimization and elevate your website’s performance.

I was taken aback to witness a significant drop in my Core Web Vitals (CWV) metrics back in June. Despite diligently implementing all the optimization techniques I had acquired over the years, it seemed insufficient. However, this setback transformed into a profound learning experience, and I’m enthusiastic about sharing my journey with you.

Are you intrigued to discover how I successfully navigated the Core Web Vitals assessment? Join me as I delve into the ups and downs of my journey, providing actionable steps you can implement while steering clear of the obstacles I faced. Together, let’s fortify your website’s CWV performance to ensure it remains consistently exceptional!

CrUX Insights and Google Search Console CWV Report:

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 Chrome User Experience (CrUX) report.

Latest CrUX data for

Search Console: 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 data
I have failed the Page Speed Insights assassement on 26 January 2023

If you want to access your CrUX data/field data. You can do it in multiple ways – Keep in mind, that to access the data you must have the field data otherwise you can’t.

(Before) Navigating Page Speed Insights Discrepancies:


First Contentful Paint (FCP):

  • Initially, moving the web-vitals JS initiator and lite-YouTube JS to the footer seemed to improve my FCP and LCP by giving priority to loading the main image. However, over time, these changes led to declining scores. It appears that the early execution of these Javascript might be negatively impacting performance in other areas.

Cumulative Layout Shift (CLS):

  • When I activated maintenance mode to redesign the blog page, it unexpectedly caused a spike in CLS.
  • Visitors were directed to a non-optimized version of the page, lacking critical CSS or using CSS that resulted in Flash Of Unstyled Content (FOUC), causing elements to briefly jump around before styling fully loaded.
  • As a result, the CLS score, which measures visual stability, significantly increased, signaling a poor user experience.

Largest Contentful Paint (LCP):

  • Initially, I thought optimizing by offloading images and videos and serving images from an image CDN (Cloudinary) would be beneficial. Cloudinary automatically optimizes and serves images in .avif format for faster performance, seeming like a win-win. However, after a few days, my LCP score dropped from 1.8 seconds to 2.7 seconds, highlighting the unintended consequences of this approach. This can be solved if you’re on Advanced Plan because it supports Custom Domain.


To identify the real issues, I started using the Real User Monitoring (RUM) analytics 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 BigQuery free available quotas) so I switched to Cloudflare Web analytics which is free to pinpoint the issues that Lab data could not.

Harnessing Real User Monitoring (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.

You can learn why RUM is so important from the New Relic article.

Many 3rd parties services also offer RUM analytics solutions to help you gather real data from real users and these are the 3 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: 

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.

(After) How I Fix the Issues & its 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. I use the Webp Express plugin to optimize and serve my images in .webp image format.
  2. I exclude the feature images or “Above the fold” or critical images from the Autoptimize 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 web font.

Page Speed Insights (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 started 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.
  2. Use an image tag instead of a background image because the browsers put the background image in lower priority.
  3. Reduce your inline CSS size. Unnecessary inlining of CSS can increase Document/ HTML size which can affect your Mobile users because inline assets (CSS, JS, and images) cannot be cached.
  4. 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.
    • If your response time/ TTFB is 3 seconds, you can’t expect your LCP will be under 2 seconds.
    • 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: Serving LCP images or viewport images from different origins is a performance pitfall. Downloading from different sources adds unnecessary time impacting the 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.
    • Image CDN:

With Cloudinary- Web page test

      • Image CDN that supports sub-domain:

No total connection time added

      • Self-host or Proxy

No total connection time added like image CDN without sub-domain integration

  1. Critical CSS or used CSS Regeneration: Updating your website’s style brings the need for critical CSS or used CSS regeneration. This ensures your pages use the most relevant styles, preventing performance issues.
    • If changing a specific page’s style, regenerate critical or used CSS for that page only.
    • For site-wide updates, consider regenerating critical CSS or regenerating used CSS for all pages to avoid old styles slowing down the loading process.
  1. Inline JavaScript and CSS: 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.
    • Inline critical JS like the navigation.

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. Super Lightweight only less than 4KB.

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 vs Elementor’s Video widget

lite-Youtube embed

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 scripts.

Only 3.2KB of JS is loaded on page when using lite-youtube js libraries

Video Widget

Elementor Video widget settings

Image overlay (Facade)

Elementor video widget's Overlay feature

To load “video.1234444….bundle.min.js“, the scripts have to be called webpack.runtime.min.js which depends on frontend-modules and depend on frontend then jQuery.


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.


Do you 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!