How to defer parsing of YouTube iFrames via JavaScript

YouTube videos cause render-blocking javascript errors when I test my Blocs web pages in PageSpeed Insights or GTMetrix. There are numerous sites like this that recommend changing the iFrame embed code’s “src” to “data-src” and then use JavaScript in the footer to defer loading of that iFrame. Problem is, I simply cannot get this to work at all. None of the sites talking about it mention Bootstrap though, so perhaps something in Bootstrap is causing that trick not to work?

Surely, I cannot be the only person who has tested a Blocs webpage in PageSpeed Insights that has a YouTube video on it and have seen the error.

I’m basically looking for the solution not only to get a higher score on the page speed checkers but to boost the actual page loading speed of pages with embedded YouTube videos. On some pages, I have more than one video embedded too.

Thank you.

Surely someone other than myself has used a YouTube video on at least of of your web pages before. If you have, your page loads are slowed because the JS isn’t deferred.

Again, I’m interested in hearing from anyone who has either solved the problem of how to defer the JS using Blocs or who can intelligently speculate on how it might be done.

Thanks!

James

Hello @JDW

Tryed this and work, don’t know if helps you:

<iframe src="" width="560" height="315" frameborder="0" allowfullscreen="allowfullscreen" data-src="https://www.youtube.com/embed/tgbNymZ7vqY"></iframe>

<script>
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;
</script> 

As this:

@Pealco

With your YouTube video on the Canvas selected, how do you add “data-src” using the Embed Code field of the right sidebar?

I can easily delete the “src” URL, but after I add “data-src” and then click away, when I click back on my video, the embed code shows “src=’’” but the “data-src” part is missing.

Separately from that, there is another problem too…

Here’s the Embed Code in the right sidebar BEFORE I make any changes:

<iframe class="embed-responsive-item" src="https://www.youtube.com/embed/hwIvUI0ome0" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>

When I Export and view the page HTML, I see this code:

<iframe class="embed-responsive-item lazyload" src="img/lazyload-ph.png" data-src="https://www.youtube.com/embed/hwIvUI0ome0" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>

That is a problem because it means that Blocs is adding “data-src” to accommodate Lazy Loading. How do you resolve that?

I have the exact same problem. Just to let you know!

@JDW did you see my early post? I don’t use the address in SRC I put the address in data-src.

So probably I don’t understand what you meaning … please explain more detailed…

I read your answer to @JDW. The thing is, that I bought blocs, because I have no idea of code. I mean I understand how I could change the code in a widget like @JDW does, but I have no idea where you put the javascript code in…

Isn’t there maybe a third party solution (bric?). I have lots of embedded videos on my page, so it gives me a real bad score at google.

Hello @JDW and @Martin there is a quick tutorial explaining all process:

1º - Go to YT select the video you want and select “Share” then “Embed” (Thank you @Eldar):

2º - Then press copy in the right button:

3º - You end with this code (That need to be changed - see point 4º):

<iframe width="560" height="315" src="https://www.youtube.com/embed/hpHno-HgM3w" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

4º - We need to add src="" in the beginning of the iframe and where you have actually the src= you need to change to data-src= so the final code will be like this:

<iframe src="" width="560" height="315" data-src="https://www.youtube.com/embed/hpHno-HgM3w" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

  • In this point what we do is we disabled the loading of the iframe when the page loads, but we need to load it when the iframe is loaded, (defer the loading), and for that we need to add javascript code to accomplish that, so let’s go to point 5.

5º - We need this code to make the defer loading:

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;

So now you are asking how the hell can I make this in blocs??? :roll_eyes: :face_with_thermometer: :roll_eyes:

There you go:

Lets say you have this structure: 2 columns:

And you want to add the iframed YT video in the left column:
So you press that little “plus” icon when you hover in the left column, and add a bric called: “Code Widget” NOT the “Code Embed”:
image

Then you will end with this:

Some times the snippets codes don’t work very well with “Preview Content” option activated (right side under the button “Edit Code”) so normally I unselect it, then you end with this:

Ok now lets do the trick:
1º - Press the “Edit Code” on the right or click twice in the blue bar “Code Widget Content” then you will have the following box:

2º Look up on the left and you will see “Code Widget” selector, and with this option selected you will add the changed iframe code:

<iframe src="" width="560" height="315" data-src="https://www.youtube.com/embed/hpHno-HgM3w" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

3º - Now we need to add the code to defer the src, so we have two options:

  • You only have the YT iframe in one page (This page) on the selector on the left top you select: “Page Footer”
  • You have YT iframe in more then one page, then on the selector on the left top you select: “Project-Footer”

By default I use “Project” because I never know the future and in this way is all covered, so selecting the “Project-Footer” you add the defer code, but in Blocs the way you tell Blocs it is a script is by taking code inside <script> </script> tags, so there you have the code you need to insert in “Project - Footer”:

<script>
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;
</script>

Then when you preview, voila there is everything working:

Even @Eldar is saying is working. :+1:

Hope it helps you… and all users that need this too…

6 Likes

@Pealco I knew everything up to the point where you start the trick :wink: Thank you!

1 Like

@pealco and @Eldar for president! :pray: :muscle:

2 Likes

I followed your path - and it worked but now I have some responsive issues - I could not place the videos and have an overflow in the mobile breakpoint - seems I am to much of a musician and to less of a website designer :wink:

OK, no problem, next stop, responsiveness of iframe using bootstrap:

1º In code, in the Code Widget part replace this:

<iframe src="" width="560" height="315" data-src="https://www.youtube.com/embed/hpHno-HgM3w" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

With this (mainly for you to understand you remove the default size from YT code width and height:

<iframe src="" data-src="https://www.youtube.com/embed/hpHno-HgM3w" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

Next we need to add some default bootstrap classes, and you ask how can I do it?

Lets go then:

You have two things the container of the iframe and the iframe itself and is represented in here:

So you select the container Column on the left and it turns blue, and on the right side in Classes you add these classes:
embed-responsive
and
embed-responsive-16by9

You type both classes, first you type “embed-responsive” then you press enter and then you type “embed-responsive-16by9” and press enter again:

Then you select the iframe itself clicking in “Code Widget” on the left it will turn blue and in the right side under classes you add these class:

embed-responsive-item

Then you will have the item responsive,

Check if it works for you…

1 Like

@Norm, please regarding this when you have the two classes I refer in my reply to @Martin, there is something strange happening in Blocs, I can’t select in the tree the “Code Widget” without remove both classes from the parent column. Please check here what I say:

Please @PeteSharp and @Eldar can you check if is happening to you too?

Manu thanks

I will check this out. Thank you for your quick reply!

I just tried it. Same happens with me. Doesn’t work.
I managed to do everything you said by first giving the frame the class and then the container. But it all ends in a completely disorder in the structure of the layers. The column were named videos and became a completely new order and were not clickable any more (like in your video)…

Maybe there will be a solution in a next update for this, because it will be an issue if you want a good google score, I think.

Nevertheless, thank you very much for your help - in the end I learned a lot!

Ok, so @Martin instead of that, there is a simple solution while @Norm don’t fix that…

Forget all the steps in my last post and in the “Code Widget” insert this code:

<div class="embed-responsive embed-responsive-16by9">
  <iframe class="embed-responsive-item" src="" data-src="https://www.youtube.com/embed/hpHno-HgM3w" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>

And in “Project - Footer” insert this one:

<script>
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;
</script>

Note 1: Don’t forget to delete all classes you created if you follow my last post.
Note 2: the 16by9 is the aspect ratio, you can select different aspect ratios if you like:

21:9 = embed-responsive embed-responsive-21by9
16:9 = embed-responsive embed-responsive-16by9
4:3 = embed-responsive embed-responsive-4by3
1:1 = embed-responsive embed-responsive-1by1

Hope it helps you…

2 Likes

Thank you, worked fine. But I hope a future update will make this a bit easier.

1 Like

You cannot display a lot of websites inside an iFrame. Reason being that they send an “X-Frame-Options: SAMEORIGIN” response header. This option prevents the browser from displaying iFrames that are not hosted on the same domain as the parent page.

I faced the same error when displaying YouTube links. For example: https://www.youtube.com/watch?v=8WkuChVeL0s

I replaced watch?v= with embed/ so the valid link will be: https://www.youtube.com/embed/8WkuChVeL0s

It works well. (Reason : /embed has the required header)

Try to apply the same rule on your case.

Why is X-Frame-Options

It is there for user security. Prevents clickjacking : https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options

The embed endpoint is desinged to be safer to show on external websites (not youtube.com).

SAMEORIGIN

The page can only be displayed in a frame on the same origin as the page itself. The spec leaves it up to browser vendors to decide whether this option applies to the top level, the parent, or the whole chain, although it is argued that the option is not very useful unless all ancestors are also in the same origin.