How to lazy load Google ads using native javascript!

I recently made a post on how I lazy load my Disqus comments. I did this because my website was performing poorly when I analysed it using Google pagespeed. Disqus was not the only thing that was performing poorly, Google Adsense was killing my load time! I therefore decided to try and find a way to lazy load Google ads. On a side note I also disabled and removed the script for auto ads, as this was slowing down my website even further.

DISCLAIMER: I do not know how Google stands on this method for lazy loading their ads. They seem to have their own way. Whether this can lead to action against you and your Adsense account I do not know, so far nothing has happened to me. If you have any information or suggestions on this, please let me know in the comments down below. I am writing this, as I would very much dislike if my attempt to help you achieve better loading time leads to actions against you.

Let us get right into it, the only thing I add to my HTML to make this work is this:

<div class="lazy-load-ad"></div>

This of course also requires some javascript to work. However I like to keep this HTML element as simple as possible so if I ever decide to switch out Adsense I hopefully can do this easier. Above I have made a simple div element with a class called lazy-load-ad, the magic happens in the javascript:

var elements = document.getElementsByClassName('lazy-load-ad');
if (!elements.length)
    return;

setTimeout(function () {
    var scriptElement = document.createElement("script");
    scriptElement.src = "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js";
    document.body.appendChild(scriptElement);

    initVisibleAds();

    window.addEventListener('scroll', function (e) {
        initVisibleAds();
    }, false);
}, 0);


var initVisibleAds = function () {
    var currentScroll = document.scrollingElement.scrollTop;
    var elements = document.getElementsByClassName('lazy-load-ad');

    for (var i = 0; i < elements.length; i++) {
        var element = elements[i];
        if ((currentScroll > element.getBoundingClientRect().top - 100)) {
            if (window.adsbygoogle) {
                element.classList.remove('lazy-load-ad');
                element.classList.add('lazy-loaded-ad');
                element.innerHTML = getAdsenseCode();
                loadAd();
            }
        }
    }
};

//TODO change this to your ad unit!
var getAdsenseCode = function () {
	return '<div class="addsense-add">' +
              '<ins class="adsbygoogle"' +
                    'style="display:block; text-align:center;"' +
                    'data-ad-format="fluid"' +
                    'data-ad-layout="in-article"' +
                    'data-ad-client="ca-pub-2997413406307797"' +
                    'data-ad-slot="2538409688">' + 
              '</ins > ' +
           '</div>';
};

var loadAd = function () {
	(adsbygoogle = window.adsbygoogle || []).push({});
};

The above is written in native javascript and requires no external libraries. It goes as this: I first check if there are to be any ads on the page by checking if there are any elements with the lazy-load-ad class. I run this script on all my pages and some may not contain ads, therefore I have this check. If there are ads I add the Google Adsense script as that is needed for adsense to work. I then attach an event to the scroll bar and if we are a 100 pixels from an ad it is loaded. When I load the ad I change the class to lazy-loaded-ad so it is not loaded several times. Everything is wrapped in a setTimeout so the loading of the adsense script does not slow everything down - it queues the execution in a simple manner (it is not truly asynchronous as it does not execute concurrently see this post for explaination).

You may think that it is a huge waste to have the loadAd() method separate as it is just one line. My reason for this is that it is very hard to understand what that line does, so I try to make it explicit. The (adsbygoogle = window.adsbygoogle || []).push({}); line in the code is actually what loads the ad, it tells the Adsense API that there is an ad to load on the page.

In the above you need to change the ad unit. The above ad unit is mine which you also can see on this page if you inspect the HTML, it is lazy loaded as you will see as you scroll down the page.

That is it!

Please let me know what you think in the comments down below!