You’ve been hard at work optimizing your site. You’ve already done things like lazy-loading Google Maps and been wondering if there was anything else you could do. For example, is there anything we can do to improve the loading of ads? Good news, there is some things you can do. You can respect the user’s mobile data plan by loading ads only when they are likely to appear in the viewport zone. You can also serve ads in the right size in accordance with the screen of the device. That would be nice of you. That would not only be responsive but also responsible.
The Problem
The nature of Google Adsense is that the ads, along with the script, file are loaded automatically: this may unreasonably slow down the appearance of the other important things, like styles, fonts, or other scripts.

Moreover, the correct ad size is determined only once right before the ad load. It means that if the user resizes the browser or rotates the tablet, the ad size remains the same and most likely doesn’t fit the context anymore.

The Arguments
- There are many factors that Google Adsense considers for monetization, but “Click Through Rate” plays a major role in revenue. Therefore, focusing on clicks rather than just views in the long term may result in increased revenue. You can get more clicks by making your site look and feel trustworthy to a user. You can get that trust by prioritizing which parts of your website to load first. Serving ads first, instead of the actual content that the user came for, is a way to the decreasing ad clicks and impressions.
- Logically, Google Adsense shouldn’t track an ad view when the ad never gets into the zone of the viewport. I don’t know if Google Adsense has this kind of tracking yet, but since the technology is JavaScript-based, they have all the means to do it.
- It is typical for smartphone and tablet users to constantly switch between portrait and landscape modes until they find the most comfortable one. Providing the most appropriate ad size for each mode improves the possibility of getting more clicks.
The Solution
I’ve made a JavaScript plugin to help. It helps to lazy loads the ads:

No matter where the ad is, above or below the viewport, it won’t get loaded if the ad is out of view.
It also helps to resize the ads:

The banner gets reloaded at particular breakpoints.
JavaScript
The plugin itself is a tiny piece of JavaScript code, and I made two versions of it: vanilla and jQuery. I called it adsenseLoader. You can grab the files here:
- adsenseloader.js; no dependencies (IE 9+).
1.1KB when minified and gzipped. - jquery.adsenseloader.js; jQuery dependency.
835 bytes when minified and gzipped.
This is how you initialize it:
// vanilla
var instance = new adsenseLoader( '.adsense' ); // accepted argument types: Selector String, Element, NodeList, Array
// jQuery
$( '.adsense' ).adsenseLoader();
You can also customize it. The default options are:
var options =
{
laziness: 1,
/*
@int (<=0)
This sets the laziness of loading the ads: (viewport height) * laziness . For example:
0 – ad load starts when at the least a tiny part of it gets in the viewport;
1 – ad load starts when the distance between the ad and the viewport is no more than the height of the viewport;
2 – 2x viewports, etc.
*/
onLoad: false
/*
@bool
A callback function which is fired when the ad is fully loaded.
A single argument (object) of the ad element is passed. For example:
onLoad: function( ad )
{
alert( ad.getAttribute( 'data-ad-slot' ) + ' ad is loaded' );
}
*/
};
// vanilla
var instance = new adsenseLoader( '.adsense', options );
// jQuery
$( '.adsense' ).adsenseLoader( options );
Moreover, there’s a methodical function destroy
, which does as it’s named: destroys the ad and brings back the corresponding DOM fragment to the default state. You can call the function for the whole instance as well as for single elements:
// vanilla
var instance = new adsenseLoader( '.adsense', options );
instance.destroy();
// or
document.querySelectorAll( '.adsense' )[ 0 ].adsenseLoader( 'destroy' );
// jQuery
$( '.adsense' ).adsenseLoader( options );
$( '.adsense' ).adsenseLoader( 'destroy' );
// or
$( '.adsense' ).eq( 0 ).adsenseLoader( 'destroy' );
Lastly, you can change a few more options that have a global impact across all of the plugin instances. You can call the function anywhere, but it’s designed to be used before creating any instance of the plugin. The default options are:
var options =
{
scriptUrl: '//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js',
/*
@string (url)
URL for Google Adsense's executive script file
*/
throttle: 250
/*
@int (miliseconds)
This defines how often the plugin should make
calculations during the processes such as resize
of a browser's window or viewport scroll.
250 means that this happens 4 times in a second.
*/
};
// vanilla
adsenseLoaderConfig( options );
// jQuery
$.adsenseLoaderConfig( options );
HTML
Here we have to simplify Adsense code snippet by leaving only two parameters and put it all into a container element:
<div class="adsense">
</div>
CSS
This part is responsible for controlling the size of ads. Using CSS, we will define the width and the height of the container element with the exact dimensions for the expected ad. With the help of media queries and a pseudo element, we’ll set the guides for the plugin which will later be able to determine when to resize/reload an ad.
.adsense {
width: 970px;
height: 90px;
display: block;
}
.adsense:before { display: none !important; }
.adsense ins { width: 100%; height: 100%; display: block; }
@media screen and ( max-width: 1024px ) {
.adsense { width: 728px; height: 90px; }
.adsense:before { content: '1024'; }
}
@media screen and ( max-width: 800px ) {
.adsense { width: 468px; height: 60px; }
.adsense:before { content: '800'; }
}
/* etc. */
Luckily, Adsense itself is able to pick the right banner size according to the given dimensions. The width
and height
properties for selector .adsense
determine whatpseudo-element expecting.
Using media queries and the pseudo element ::before
, we tell the plugin when it is supposed to reload the ad. The JavaScript part checks for differences for content
values. An ad is automatically reloaded when a difference is detected. You can use any different integers across the media queries. In my examples, I equated the values to the media queries’ width parameters for an easier maintenance.
Resizing the banners is a job split across two disciplines: CSS is the logic and JavaScript is the execution.
Demo
Remember that if you’re using an ad blocker that blocks AdSense, you may not see this work correctly.
See the Pen Lazy-Loading Responsive Adsense Ads by Osvaldas (@osvaldas) on CodePen.
You are welcome to follow and contribute to the project on GitHub.
Disposing Multiple Ads
Here’s a quick tip on how to manage multiple differently sized ads. Say we have two banners: one in the content area and another in the sidebar. We can assign different class names for each:
<div class="adsense adsense--main">...</div>
<div class="adsense adsense--side">...</div>
Now we can define common styles for .adsense
and individual styles for .adsense--main
and .adsense--sidebar
, like this:
.adsense{
display: block;
}
.adsense:before { display: none !important; }
.adsense ins { width: 100%; height: 100%; display: block; }
.adsense--main { width: 728px; height: 90px; }
.adsense--side { width: 336px; height: 280px; }
@media screen and ( max-width: 1024px ){
.adsense--main { width: 468px; height: 60px; }
.adsense--main:before { content: '1024'; }
}
@media screen and ( max-width: 800px ){
.adsense--side { width: 250px; height: 250px; }
.adsense--side:before { content: '800'; }
}
Ad Loading Indication or Taking Advantage of onLoad()
You can indicate the loading process in a few ways: provide a placeholder image, add text, border, background or anything else that best meets your design direction and is visible until the ad loads:

To start with, let’s add extra an HTML element and some styling, which basically adds an overlay with text “Loading…” above the ad:
<div class="adsense">
<ins data-ad-client="ca-pub-4676533344420647" data-ad-slot="5741144487"></ins>
<p class="adsense__loading"><span>Loading…</span></p>
</div>
.adsense {
position: relative;
}
.adsense__loading {
width: 100%;
height: 100%;
background-color: rgba( 255, 255, 255, .9 );
display: table; /* for vertical centering */
position: absolute;
top: 0;
left: 0;
}
.adsense--loaded .adsense__loading { display: none; }
.adsense__loading span {
text-align: center;
vertical-align: middle; /* for vertical centering */
display: table-cell; /* for vertical centering */
}

Using the callback function onLoad()
we can add the class adsense--loaded
which is responsible for hiding the .adsense__loading
element:
// vanilla
var instance = new adsenseLoader( '.adsense',
{
onLoad: function( ad )
{
if( ad.classList )
ad.classList.add( 'adsense--loaded' ); // IE 10+
else
ad.className += ' ' + 'adsense--loaded'; // IE 8-9
}
});
// jQuery
$( '.adsense' ).adsenseLoader(
{
onLoad: function( $ad )
{
$ad.addClass( 'adsense--loaded' )
}
});

Thanks for reading and being a responsible web designer/developer.
I thought loading ads dynamically was against the Adsense terms of service?
Also, overriding the default css styles of Adsense is definitely in violation of their TOS.
There are no default CSS styles of Google Adsense.
^ Can you guys cite your sources? I’ve read through the AdSense TOS and other guidelines and nothing seems to go against the (pretty sweet!) techniques in this article.
See here: https://support.google.com/adsense/answer/1354736 – the techniques in this article seem to fall under the acceptable category of modifications.
I remember there being issues with Ajax loading and having ads that could be seen as ‘auto refreshing’. Can’t seem to find it anymore though so maybe it was changed when they updated their support.google.com site.
The plugin does no Ajax loading. The ‘Ajax’ was mentioned in the article by mistake, sorry, we’ll fix that soon.
The plugin technically uses official ad initiation code by Google Adsense. But the difference is that it fires it one by one when it’s meaningful to do that, rather then then firing them all at once, no matter what.
It’s against Google Adsense’s rules to automatically refresh ads when this is not related to user’s actions. This could be interpreted differently, but resizing browser’s window or rotating device is a completely conventional action taken by a user. Google Adsense already did a responsive improvement, and I believe it’s just a matter of time when they will come up with real-time responsiveness of the ads.
It definitely seems they have changed (or at least better worded) their policies. Can this dynamically load more ads within infinite scrolling content? I think that was one of the big issues I found. Google would only ever serve 3 adverts to the page and would ignore any future requests even if you dynamically deleted off screen ads. I think I even tried moving the DOM node with JS which it didn’t allow.
Looks cool! Would love to see this as a WordPress plugin! ;)
Yeah, waiting too for WP plugin :) And infinity load articles support. Great job, thanks!
I always wondered why Google couldn’t do a better implementation of their “responsive” ads and this plugin seems that it could be a good solution until google comes up with something better.
However I am a bit reluctant to use it because I am not 100% convinced that Google would be OK with it and I don’t want to risk getting banned from AdSense. It would be nice if the author could get somebody from google (e.g. Matt Cutts) to confirm that this technique is fine with them.
The first thing I’m thinking about while adding widgets like Google Maps, Facebook Like Widget, etc. is how to make async lazy loading. Especially after moment when I figured that Google Page Speed diminish dramatically when adding some of Facebook widget (from 98% to 88% in my case). That was shock for me that adding such a common widget bring such performance trouble.
Thanks for the article. You are doing a great job.
I suppose you have a little mistake in your jQuery code here
“Get” method returns DOM element but not jQuery object. And DOM element object don’t have any “adsenseLoader” method, that’s why this code shall return an error. Use “eq” method instead to get proper result:
Thanks for the get/eq remark.
Great work here.
It would be interesting if this can be done with DFP ads as well.
Hi,
can you edit article so we can see HTML codes? Now I can see only empty black boxes. I need code for multiple ads (sidebar + horizontal ads). Thanks :)
Hi,
You can see the HTML codes here on the Pen of this plugin!
I hope that help you!
Yes, but there is no code for multiple size ads :)
Thank you for a great script! But I have not displayed advertisements in mobile browsers. On my computer, everything works fine, even if I do width 300px browser. How do I fix this error? (P.S. site delpc.ru)