How to Defer Parsing of Javascript for YouTube Iframe Videos in WordPress
September 20, 2018 By Andrew GehmanOne of the best ways to improve page speed scores is to defer the parsing of your Javascript files that aren’t required for the initial page render. One of the big culprits of this render-blocking Javascript is embedded YouTube videos. When you embed a YouTube video, it will often end up loading additional external Javascript files which can significantly slow the loading of your site. We can combat this by “Lazy Loading” our YouTube videos. Here’s how to defer parsing of Javascript for YouTube iframe videos in WordPress.
How to Defer Parsing of Javascript for YouTube Iframe Videos in WordPress
The key to making this work is a little bit of editing of the YouTube embed code. This will prevent the video from loading during the initial page render.
- We need to remove the link from the iframe’s src attribute, so we are left with src=””
- add a data-src attribute
- add the link from the original src attribute to the data-src attribute
Let’s take a closer look at how to defer parsing of Javascript for a couple of methods you may use for loading videos in WordPress:
Embedding a YouTube Iframe File in Your Template
If you are embedding an iframe directly into your WordPress template file, just copy the embed code from YouTube, and follow the key steps above to create an empty src attribute and fill the new data-src attribute with the link value.
<iframe width="560" height="315" src="" data-src="https://www.youtube.com/embed/Hpv3jqmYRjk" frameborder="0" allowfullscreen></iframe>
If we leave the code as is now, the video will not load. We need a little javascript to help us out. You’ll want to add this to a .js file and enqueue it along with the rest of your Javascript files in functions.php.
function init() { var vidDefer = document.getElementsByTagName('iframe'); for (var i=0; i<vidDefer.length; i++) { if(vidDefer[i].getAttribute('data-src')) { vidDefer[i].setAttribute('src',vidDefer[i].getAttribute('data-src')); } } } window.onload = init;
After the browser window finishes loading, this code will find all the iframes on your site (or on whichever pages are loading this script), and if the data-src exists, copy that attribute to the src attribute. By default, a YouTube video embed code doesn’t have an ID or class name, so this code should work for all YouTube videos without any adjustment.
If you only have a single video on your site, you don’t need to loop through the iframes. You could just set an ID or class name on the iframe, grab the ID or class name of the video iframe, and then simply get and set the Attribute of that single item.
<iframe id=”youtube_video” width="560" height="315" src="" data-src="https://www.youtube.com/embed/Hpv3jqmYRjk" frameborder="0" allowfullscreen></iframe>
Here is an example using jQuery:
var newsrc = $("#youtube_video").attr('data-src'); $("#youtube_video").attr('src', newsrc );
Embedding Video Using Advanced Custom Fields oEmbed
Many WordPress developers rely on the popular Advanced Custom Fields (ACF) plugin to create custom fields that make adding content much easier for clients.
To add video embeds with Advanced Custom Fields, you could use a regular ACF text input and just manually set the data-src and empty src attributes. This is less than ideal as the average user may not want to have to remember this process every time they want to embed a new video. If you want to avoid having to do this manually, we can use an oEmbed field.
The downside with the oEmbed field is we need a little more code magic to copy the original src code to the data-src set the src attribute to be empty. Fortunately, the ACF documentation gives us an easy way to do this.
<?php //from https://www.advancedcustomfields.com/resources/oembed/ $iframe = get_field( 'video' ); // use preg_match to find iframe src preg_match('/src="(.+?)"/', $iframe, $matches); $src = $matches[1]; ?>
Using PHP’s preg_match function, we can identify the src and set it to the $src variable. Then we can re-create the iframe, remove the src, and set the data-src attribute to the src we grabbed form the oEmbed.
<?php $newiframe = '<iframe id="youtube_video" src="" data-src="'. $src .'" frameborder="0" allowfullscreen></iframe>'; ?>
Using these methods you should see a nice bump in your page speed scores.
Additional Resources:
And what to do if I use AMP? This project don’t allow use scripts. That’s why I can not use data-src.
That’s a bit out of scope for this post, but you might start with the AMP documentation for YouTube videos.
Is it possible to apply this for a shortcode based YouTube video? I am using YouTube Element of Fusion Builder and not able to understand how this can be implemented in a shortcode.
Thank you
Hello Hass, are you referring to this? https://theme-fusion.com/documentation/fusion-builder/elements/youtube-element/
If so, you would need to look into the source code of the function behind that fusion_youtube shortcode, to see if there is a filter you can use to modify the html it generates, or if you can overwrite it completely, in order to accommodate the method outlined in this post.
In general, yes it would be possible to apply this to a shortcode based YouTube video. The default handler for WordPress can be filtered via embed_oembed_html https://developer.wordpress.org/reference/hooks/embed_oembed_html/ so a function attached to that filter could be used to modify the iframe code (similar to the way this post describes doing it with an Advanced Custom Fields oEmbed).
Thank you very much. Yes, that is the one I am referring to. And yes, the shortcode can be overwritten in a child theme. I’ll look into this now 🙂
Hello, thanks for posting this!!
After I implemented your solution for a video on my homepage, Google PageSpeed still indicated that the page load was blocking due to a third party script (youtube). So I wrapped the javascript code that adds the src parameter in a setTimeout() function. That worked, an Google PageSpeed is no longer complaining about third party scripts. Interestingly though, a timeout of 500ms didn’t work – I had to delay it for a full second.
Loading the video immediately when the onload event is fired should be fine, since at that point the user sees the entire site. Maybe google still thinks it’s a problem because the page isn’t interactive until after the scripts are done running?
Anyway, if anyone wants to try this:
function init() {
setTimeout( function() {
var vidDefer = document.getElementsByTagName(‘iframe’);
for (var i=0; i<vidDefer.length; i++) {
if(vidDefer[i].getAttribute('data-src')) {
vidDefer[i].setAttribute('src',vidDefer[i].getAttribute('data-src'));
}
}
}, 1000);
}
window.onload = init;
Hi,
Stupid question, I’m using ACF and hitting the same issue you outline. What I don’t quite get is where I should put the additional PHP snippets if I want to do this site wise.
Thanks
If I am understanding your question correctly, the php snippets would go in any template in your theme that you are using the ACF oEmbed code.
Thanks, I’ve done that and worked – so much appreciated. Guess this could be done with filters to encourage re-use.
One thing I did differently was use preg_replace to substitute ‘src=’ with ‘src=”” data-src=”
I’ve added the code to my footer and placed the iframe src in data-src instead, but when I run my site through PageSpeed and GTmetrix, I still get a warning to defer the YouTube JS.
– Is that to be expected, or am I doing something wrong?
I tried to use the code you provided for the functions.php file When I placed in the functions section I got this syntax error Could you help me with what I am doing wrong? I have an old updated WordPress with a lot of videos and the “opportunities” are a real pain.
syntax error, unexpected ‘var’ (T_VAR)
It sounds like you added the js code directly in the functions.php file? You want to add the javascript to a .js file and enqueue it along with the rest of your Javascript files in functions.php. https://developer.wordpress.org/reference/functions/wp_enqueue_script
This solution impact youtube GTM tracking. Video tracking for youtube iframe API stops working.
I’m not too familiar with Google Tag Manager, but if you run into these issues, these posts may be helpful:
https://support.google.com/tagmanager/answer/7679325?hl=en
https://www.analyticsmania.com/post/youtube-tracking-google-tag-manager-solved/
When i add it in the functions.php file I got a syntax error, Though you said it shouldn’t be added directly. but how do i add the javascript to a .js file and enqueue in WordPress?????
https://developer.wordpress.org/themes/basics/including-css-javascript/