Back to Blog

How to lazy load YouTube videos in WordPress to improve Core Web Vitals

December 30, 2022

How to lazy load YouTube videos in WordPress to improve Core Web Vitals

Introduction

One of the projects required us to put more than twenty YouTube videos on a WordPress page. They had various videos showcasing their expertise, which were to be added to the website.

But the problem is that embedded YouTube videos slow down web page load times. It also has an impact on the Core Web Vitals

After embedding the YouTube videos, we conducted the PageSpeed test, and as you could anticipate, the result was poor. We were dissatisfied with it because page load time is an important factor in the user experience of a web page.

So let’s discuss the problem in detail and the solution.

The Problem 

Let’s create a simple page consisting of six videos. We are using the built-in Youtube Embed block in Gutenberg, where we just copy and paste the video’s URL into the editor. 

Screenshot 1: YouTube embeds Gutenberg Block

Here is a demo page that is similar to the client’s video gallery page, which we discussed before.

Screenshot 2: A page with six videos in a video gallery.

The PageSpeed score is 49 (Lighthouse data), which is very low. 

Screenshot 3: Low PageSpeed score

Let’s understand why the page load time is so high.

When a YouTube video is embedded on a page, it requires many resources (mostly javascript files) to render it, which slows down the loading of the page. These resources are required to style the video player along with its functionality, such as pause, play, etc.

Screenshot 4: Number of JS requests

As we can see, fifty or more JS requests are made for the six videos embedded on the page (excluding the WordPress theme and third-party JS library requests).

In general, the more videos that are embedded on a page, the heavier the page becomes, which makes the performance even worse.

Solution

So now that we know the problem, let’s discuss the solution.

To embed YouTube videos on a WordPress page, we are going to use the <lite-youtube> web component. It’s a custom HTML element that renders YouTube embeds faster. The awesome part is that it’s just a vanilla web component with no dependencies. 

Let’s integrate this web component into WordPress.

Step 1: Register and Enqueue Scripts


add_action( 'wp_enqueue_scripts', 'init_assets' ) ;

/**
 * Enqueue required assests.
*/
function init_assets(){
   $handle = 'lite-youtube';
  //You can also load this JS only for YouTube video-specific pages
   wp_register_script( $handle, 'https://cdn.jsdelivr.net/npm/@justinribeiro/lite-youtube@1.4.0/lite-youtube.js', '', '', true );
   wp_enqueue_script( $handle );   
}

add_filter('script_loader_tag', 'add_type_attribute' , 10, 3);
function add_type_attribute($tag, $handle, $src) {
   // if not your script, do nothing and return original $tag
   if ( 'lite-youtube' !== $handle ) {
       return $tag;
   }
   // change the script tag by adding type="module" and return it.
   $tag = '';
   return $tag;
}

The above code registers and includes the JS file loaded via the CDN.

Step 2: Using the <lite-youtube> web component 

Now let’s use this web component. Pass in the video id as a parameter.

<lite-youtube videoid="guJLfqTFfIw"></lite-youtube>

Copy and paste this code into Gutenberg HTML blocks, as seen in the below screenshot.

Screenshot 5: <lite-youtube> custom HTML block

The page looks like this.

Screenshot 6: A video gallery displayed using <lite-youtube> component

In comparison to the original page’s 48 PageSpeed score, this page has a 99 PageSpeed score on mobile devices (Lab data from Lighthouse). On the surface, the page looks similar to screenshot 2, but the story behind the scenes is different.

Screenshot 7: High PageSpeed score

Let’s see how this PageSpeed score was achieved.

Instead of the YouTube iframe, the <lite-youtube/> web component only loads a thumbnail image of the video (as a placeholder) with a play button. Notice the slight difference between both play buttons in screenshots 2 and 4. Here is the code snippet.

<div id="frame">
 <picture>
  <source id="webpPlaceholder" type="image/webp" srcset="https://i.ytimg.com/vi_webp/wmuEzcz3ebo/hqdefault.webp">
  <source id="jpegPlaceholder" type="image/jpeg" srcset="https://i.ytimg.com/vi/wmuEzcz3ebo/hqdefault.jpg">
  <img id="fallbackPlaceholder" referrerpolicy="origin" loading="lazy" src="https://i.ytimg.com/vi/wmuEzcz3ebo/hqdefault.jpg" aria-label="Play: Video" alt="Play: Video">
 </picture>
 <button id="playButton" aria-label="Play: Video"></button>
</div>

Now, when a user clicks the play button, the video loads and begins to play in the placeholder. Notice the iframe that is injected when the play button is clicked in the following code snippet.

<div id="frame" class="activated">
 <picture>
  <source id="webpPlaceholder" type="image/webp" srcset="https://i.ytimg.com/vi_webp/wmuEzcz3ebo/hqdefault.webp" />
  <source id="jpegPlaceholder" type="image/jpeg" srcset="https://i.ytimg.com/vi/wmuEzcz3ebo/hqdefault.jpg" />
  <img id="fallbackPlaceholder" referrerpolicy="origin" loading="lazy" src="https://i.ytimg.com/vi/wmuEzcz3ebo/hqdefault.jpg" aria-label="Play: Video" alt="Play: Video" />
 </picture>
 <button id="playButton" aria-label="Play: Video"></button>

 <!-- iframe is injected--> 
 <iframe frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" src="https://www.youtube.com/embed/wmuEzcz3ebo?autoplay=1&amp;start=0&amp;null"></iframe>
</div>

So, in short, when the page loads, the video has not been rendered. Instead, when the user clicks on the thumbnail image, only that video is dynamically inserted into the placeholder. This is known as lazy loading.

Now let’s look at the number of requests made.

Screenshot 8: Less number of JS requests

On page load, the web components JS library is included (excluding the theme and third-party JS files). On subsequent play button clicks, requests are made to load the corresponding video.

Here is the result of a visual comparison test performed on both pages.

Screenshot 9: Timings compared of the two pages

It can be seen in the above screenshot, the timings are less for the <lite-youtube> web component compared to plain YoutTube embeds.

Screenshot 10:The number of requests compared between the two pages

The number of requests for the <lite-youtube> web component is lower than for plain YouTube embeds, as shown in the above screenshot.

Conclusion

When you embed YouTube videos directly on a web page, it takes longer for the page to load, so it fails the Core Web Vitals test. 

The page load time is drastically reduced by using a lightweight web component <lite-youtube>.

We compared Lighthouse (Lab) data from two pages: one with a direct YouTube embed and one with the <light-youtube> web component. Having said that, it’s important to test and evaluate the Real User Monitoring (RUM) data, which represents the load times on actual user devices (over a 28-day period).

That’s it for this tutorial.

If you need any help optimizing the Core Web Vitals of your WordPress website, talk to our web experts.