Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent YouTube js calls from slowing down page load

I am using https://gtmetrix.com to diagnose issues with my page speed.

The page in question has one embedded YouTube video and GTMetrix is saying that this video's JS calls are slowing down page load speed.

This is the call being made:

<iframe width="640" height="360" src="https://www.youtube.com/embed/PgcokT0AWHo" frameborder="0" allowfullscreen></iframe>
like image 239
Genadinik Avatar asked May 18 '18 11:05

Genadinik


People also ask

Does embedding YouTube videos slow down your website?

Researchers often say that it is possible that YouTube embeds can slow down the site loading and reduce the page speed score given by search engines called Search Engine Optimization(SPO).

How do you make an embedded YouTube video load faster?

Your "ajax-y method"s will be the only way to speed this up. Large sites are going to be using a CDN and have good caching. There is no way around large files taking a long time... Keeping the object or video tag out of the HTML and then adding it after page load, will improve perceived page load performance.


3 Answers

EDIT: as of October 2019, this is not working anymore (Thanks to @CpnCrunch for the update). For the cases where it's not impacting the user experience, you can apparently add a 1000ms timeout after the page load for it to take effect.

This is an example of attibuting the src dynamically on page load, using a pure JS solution. Using event listeners instead of window.onload because with the latter, only one event can be set and it would override any precedent window.onload event:

<iframe id="videoFrame" width="640" height="360" src="" frameborder="0" allowfullscreen></iframe>
<script>
function setVideoFrame(){
  document.getElementById('videoFrame').src = 'http://example.com/';
}
if (window.addEventListener)  // W3C DOM
  window.addEventListener('load', setVideoFrame, false);
else if (window.attachEvent) { // IE DOM
  window.attachEvent('onload', setVideoFrame);
}else{ //NO SUPPORT, lauching right now
  setVideoFrame();
}
</script>

Note that the script can be anywhere in the code, but in case of no support for event listeners (which is highly unlikely with nowadays browsers), the function is launched right away, so it should be at least after the iframe element.

like image 155
Kaddath Avatar answered Oct 25 '22 01:10

Kaddath


I was having the same problem for a website I was doing and I stumbled upon this link How to "Lazy Load" embedded youtube videos

What it essentially does is, upon page load, it'll show a fake youtube player section (made out of css and your video image thumbnail) on the webpage and when the user clicks on it, it'll replace that fake player section with the Iframe and that's when the player will be loaded.

Code from the website

(function() {

  // get's all video wrapper divs
  var youtube = document.querySelectorAll(".youtube");

  // iterates through all the divs
  for (var i = 0; i < youtube.length; i++) {

    /* 
    gets the video id we mentioned in the data-embed attribute
    to generate image thumbnail urls, youtube has several
    resolutions.
    - mqdefault 320 x 180
    - hqdefault 480 x 360
    - sddefault - 640 x 480
    - maxresdefault - 1920 x 1080
    */
    var source = "https://img.youtube.com/vi/" + youtube[i].dataset.embed + "/sddefault.jpg";

    /*
    creates new image and sets the source attribute to the thumbnail
    url we generated above and sets it to load the image on page load
    */
    var image = new Image();
    image.src = source;
    image.addEventListener("load", function() {
      youtube[i].appendChild(image);
    }(i));

    /*
    below is where the magic happens, we attach click listeners to the 
    video embed divs and when clicked we create a new iframe and sets
    it inside the video wrapper div and only then will the js files
    associated with the embedded video be loaded
    */

    youtube[i].addEventListener("click", function() {

      var iframe = document.createElement("iframe");

      iframe.setAttribute("frameborder", "0");
      iframe.setAttribute("allowfullscreen", "");
      iframe.setAttribute("src", "https://www.youtube.com/embed/" + this.dataset.embed + "?rel=0&showinfo=0&autoplay=1");

      this.innerHTML = "";
      this.appendChild(iframe);
    });
  };

})();
html {
  background-color: #f3f3f3;
}

.wrapper {
  max-width: 680px;
  margin: 60px auto;
  padding: 0 20px;
}

.youtube {
  background-color: #000;
  margin-bottom: 30px;
  position: relative;
  padding-top: 56.25%;
  overflow: hidden;
  cursor: pointer;
}

.youtube img {
  width: 100%;
  top: -16.82%;
  left: 0;
  opacity: 0.7;
}

.youtube .play-button {
  width: 90px;
  height: 60px;
  background-color: #333;
  box-shadow: 0 0 30px rgba( 0, 0, 0, 0.6);
  z-index: 1;
  opacity: 0.8;
  border-radius: 6px;
}

.youtube .play-button:before {
  content: "";
  border-style: solid;
  border-width: 15px 0 15px 26.0px;
  border-color: transparent transparent transparent #fff;
}

.youtube img,
.youtube .play-button {
  cursor: pointer;
}

.youtube img,
.youtube iframe,
.youtube .play-button,
.youtube .play-button:before {
  position: absolute;
}

.youtube .play-button,
.youtube .play-button:before {
  top: 50%;
  left: 50%;
  transform: translate3d( -50%, -50%, 0);
}

.youtube iframe {
  height: 100%;
  width: 100%;
  top: 0;
  left: 0;
}
<!-- (1) video wrapper,  data-embed contains ID of the Youtube video-->
<div class="youtube" data-embed="AqcjdkPMPJA">

  <!-- (2) the "play" button -->
  <div class="play-button"></div>

</div>
like image 25
Ajmal Hassan Avatar answered Oct 25 '22 02:10

Ajmal Hassan


Just need to add a single line of code and its lazy loaded!

For example earlier it might be like :

  <iframe
      width="400"
      height="200"
      src="https://www.youtube.com/embed/sh0EGUheef8"
      frameborder="0"
      allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
      allowfullscreen
  ></iframe>;

Just need to change

src with srcdoc

srcdoc="<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img,span{position:absolute;width:100%;top:0;bottom:0;margin:auto}span{height:1.5em;text-align:center;font:48px/1.5 sans-serif;color:white;text-shadow:0 0 0.5em black}</style><a href=https://www.youtube.com/embed/sh0EGUheef8/?autoplay=1><img src=https://img.youtube.com/vi/sh0EGUheef8/hqdefault.jpg alt='AltTagContent'><span>▶</span></a>"

The trick is rooted in srcdoc, a feature of where you can put the entire contents of an HTML document in the attribute. It’s like inline styling but an inline-entire-documenting sort of thing.

The only problem is that the frame. The user will have to click it again. Since the first click was only to load the video. It still saves the junk that would get downloaded otherwise, and specially for mobile, those 500KB could hurt.

like image 39
Arijit Kundu Avatar answered Oct 25 '22 03:10

Arijit Kundu