Skip to Main Content Skip Table of 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. 

I noticed my Core Web Vitals (CWV) failing in June. Whatever optimization I have learned in the past few years, I have applied everything & from there, I have learned a lot and wanted to share with you. 

Want to know How I pass the Core Web Vitals Assessment? Just follow along, and you will learn how I did it and how I made mistakes so you can take precautions and never do it. 

CrUX/ Chrome UX Report Dashboard-

The CrUX Dashboard is built with a Data Studio feature called Community Connectors. This connector is a pre-established link between the raw CrUX data on BigQuery and the visualizations of Data Studio. It eliminates the need for users of the dashboard to write any queries or generate any charts. Everything is built for you; all you need is to provide an origin and a custom dashboard will be generated for you.

First Contentful Paint (FCP) –

First Contentful paint Performance report from Chrome User experience

Larget Contentful Paint (LCP)

Largest Contentful Paint Performance report from Chrome User experience

Cumulative Layout Shift (CLS)

Cumulative Layout Shift Performance report from Chrome User experience

If you have CrUX data/field data and wanted to access it. You can do it in multiple ways –

As you can see from the picture below I have no issue with Google Search Console – Core Web Vitals and Page experience report but the Page Speed Insights (PSI) – field data is telling me otherwise.

I have failed the Page Speed Insights assassement on 26 January 2023

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

Reasons behind the failure of field data in Page Speed Insights

Differences between Field Data in PSI and CrUX

The difference between the field data in PSI versus 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.

FCP

To improve my FCP & LCP performance, I inline web vitals JS initiator (that initiates web vitals js libraries) and lite-youtube js (lightweight YouTube embedded).

This way my LCP image (Featured image) loads earlier in the waterfall chart but when I implement this method. In a few days, the score is getting worse.

CLS

I tried to revamp my blog post design to do so I set up a Maintenance page so that I can safely create the page. While in maintenance mode all the users are hitting the page and that page has the code snippets that handle preloading the stylesheets I forget to generate Critical CSS which leads to Flash of Unstyled Content (FOUC) because of this my CLS score suddenly spikes.

LCP

I didn’t realize hosting an LCP image on image CDN is a bad idea when I first set up for two to 3 days there was no issue with my LCP score later on score started to degrade because of this my LCP score from 1.8sec to 2.7sec.

As you see from my failure listed above, this is the service I use to monitor my Real User Monitoring services like Web Vitals JS and Cloudflare analytics to pinpoint the issues that Lab data could not.

How do I collect real user data? 

What is 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.

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

Many 3rd parties services 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 alongside the codelabs.

When I start collecting the RUM data. I know exactly the issues I have, & opportunities to improve my web performance like which selectors cause the layout shift & which is the LCP element.

LCP

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

CLS

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

With these insights from the web vitals JS libraries and a combination of lab data testing tools. Identifying, analyzing & fixing the issues is so much easier compared to those who do not set up any RUM solution.

  1. The web vitals JS I was using didn’t support Time To First Byte (TTFB), First Contentful Paint (FCP), and Interaction Next Paint (INP) metrics.
  2. If you want an advanced version, you can follow Tony McCreath’s article on Web Site Advantage Core Web Vitals Tracking

Cloudflare’s Browser Insights

If you’re using Cloudflare you can use Cloudflare’s Browser insights to collect RUM data. I set it up for more than a week and have had similar results with the web vitals JS setup & it is the easiest setup compared to web vitals JS which is also free.

LCP

LCP performance from Cloudflare's Browsers insights

CLS

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.

Fixes & Comparisons-

Largest Contentful Paint (LCP)

Fixes

To improve the LCP metric:

  1. I self-hosted my images and deliver webp images using the Performance Lab plugin on the newly uploaded image.
  2. To discover the image earlier by the browsers, I am using rel=”preload” hints to preload my feature image & using fetch priorities hint to give the image higher priorities boost. (optional)

Comparisons of Webpagetest and PSI- field data

Before (Cloudinary) add an unnecessary connection time to the image (number 6)

After (Self-hosted/ Cloudflare) no added connection because it is self-hosted also you can use image CDN that offers custom domain functionalities.

Webpage test waterfall after the image is been self-hosted and make the image loads earlier

Before (PSI- field data)

2.7 sec Largest Contentful paint which is not good Core Web Vitals

After (PSI – Field data)

After the Largest contentful paint fixes

Cumulative Layout Shift

Fixes:

To fix the CLS issues:

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

Comparisons of PSI-field data

Before

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

After the fix there is no Cummulative layout detected

First Contentful Paint

Fixes

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.
  3. I start Removing unused CSS from all my posts. 
        
        //Before 


initImagePlaceholder() {
    LiteYTEmbed.addPrefetch('preconnect', 'https://i.ytimg.com/');
    const posterUrlWebp = `https://i.ytimg.com/vi_webp/${this.videoId}/${this.posterQuality}.webp`;
    const posterUrlJpeg = `https://i.ytimg.com/vi/${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 = `https://i.ytimg.com/vi_webp/${this.videoId}/${this.posterQuality}.webp`;
    const posterUrlJpeg = `https://i.ytimg.com/vi/${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}`);
}

        

Comparison

Before

FCP recorded on 26th August
First Contentful Paint (FCP) – 2.4s recorded on 26th August

After

2 sec First contentful paint performance recorded after the fix

This is not happening once, it happens more than 2 times from there here are the tips and caution you need

Tips

  1. If your featured image is a background image, consider preloading the image so browsers discover it earlier.
  2. Reduce your inline CSS size.

Caution

  1. When fixing Core Web Vitals issues, people miss the Server Response time or Time for First Byte (TTFB) metrics because it is notable metrics but if you see it properly TTFB plays a huge role (but tricky to debug), if it fluctuates a bit it can affect your Largest Contentful Paint (LCP), and First Contentful Paint (FCP) metrics even.
  2. Serving and delivering LCP images from different origins is a bad idea because it unnecessarily added time spent downloading the LCP image.
  3. If you’re changing/updating the style just make sure you regenerate Critical CSS on that specific page or if you’re updating a site-wide, consider regenerating Critical CSS for all the pages. This makes sure the Critical CSS is included in the process.
  4. Unnecessary, do not inline your CSS and JS for sake of page speed score. I saw lots of tutorials recommending this terrible approach. 
  5. If you’re using Elementor, do not set the CSS Print Method to Internal Embedding in Elementor > Settings > Advanced because It unnecessarily inlines your frontend CSS which can be over 30KB (Brotli compression) when Improved CSS loading experiments are turned off.
  6. Try to reduce 3rd parties calls as much as possible.

What are the alternatives to the Elementor widget?

If my website’s single post template has lots of features like motion effects (sticky header, parallax effects), sliders, gallery, 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 features.

When I requested Massimo Villa from the altsetup to review my article. He raised a 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 

Lite-YouTube embed VS Elementor Video

My website is built with Elementor (Affiliate) and it has its own Video Widget that supports YouTube, Vimeo, Dailymotion & Self-Hosted Video, and other amazing features like Lazy-loading, facade (“image overlay”) as Massimo Villa suggested.

YouTube Widget

Elementor Video widget settings

Image overlay (Facade)

Elementor video widget's Overlay feature

This is why I choose Lite-YouTube over the Elementor video widget-

  1. Performance – Lite-YouTube JS is only 3.3KB whereas Elementor video can go over 70 to 80KB in page size because of JS dependencies.
  2. Lite-Youtube is just a vanilla web component where Elementor video is dependent on jQuery, frontend, frontend.modules, and whole lots of JS.

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

Image CDN 

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

  1. FlyingProxy (It is integrated with Cloudflare Enterprise).
  2. Webp Express plugin preloading <picture> tag is trickier than the <img> tag.
  3. Cloudflare Pro (require no setup)
  4. Shortpixel Adaptive AI (Affiliate)
  5. Bunny Optimizer
  6. Imgix 
  7. Optimole

Table of Contents

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

Elementor's Table of Content widgets

I could use the widget but the problem is the amount of JS added to the page which can slow down website performance. 

For an alternative solution, I use the LuckyWP Table of Contents By LuckyWP and setup to automatically insert headings not via the shortcode method.

Lucky WP Table of Content settings

If you want to pass your Core Web Vitals, here are some of the plugins to improve your site performance –

Plugin Recommendations:

All the plugins I recommend below have the feature for generating critical CSS, removing unused CSS, the ability to compress images, and serving 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  (This is great if you already enabled Server-side caching & you don’t want any conflict)

Reference 

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

More information:

  1. Pagespeed Insights – Field Data report vs CrUX
  2. RUM & CrUX difference
  3. Chrome UX report update
  4. Highly recommend reading Massimo Villa’s article on how to get 100% in speed tests.

Conclusions 

Stop assuming your lab data score is enough for you to pass the Core Web Vitals Assessment that is what I thought and fail twice.

The best solution is to set up the RUM solution and start identifying the real issue and fix the problems. 

Thangjam Kishorchand

Thangjam Kishorchand

Hi there, this is my place where I write about my Elementor tips and tricks that I learned for the last 2 years. I am mostly active on Quora and Facebook. I love messing around with design trends like Variable Fonts, Dark Mode

Powered by Elementor pro

This site is powered by Elementor pro : Theme builder and it contains Affiliate links,which means that if you buy from my links, Foxscribbler will earn a small commission.This commission comes at no additional cost to you.

Scroll up further to Load all the comments...