Skip to content

Instantly share code, notes, and snippets.

@davewalker235
Last active February 21, 2022 18:15
Show Gist options
  • Save davewalker235/e090c19cef62206b14a0fe2677168515 to your computer and use it in GitHub Desktop.
Save davewalker235/e090c19cef62206b14a0fe2677168515 to your computer and use it in GitHub Desktop.
Lazyload Google DFP ads with SRA Roadblock
<html>
<head>
<script async="async" src="https://www.googletagservices.com/tag/js/gpt.js"></script>
<script>
// This is a very basic example of Lazyloading DFP ads with an SRA roadblock.
// The example uses ES2016 javascript syntax and relies on
// IntersectionObservers. Normally in production this would be transpiled
// with babel and polyfilled for support. It also relies on DFP maintaining a
// changeCorrelator for all ad requests. Historically this correlator has
// timed out after 30 seconds, which is why this example relies on a js timer
// to force loading after 25 seconds. Our sites have been using a version of
// this code in production since late 2017, the method has been observed to
// be stable and validated by our DFP rep. Depending on your account the
// correlator may no longer time out and you might not need to use this
// method, you should consult the following article before settling on this
// method.
// See release notes for October 29th, 2018. The feature is referred to as
// "long-lived page views":
// https://support.google.com/admanager/answer/7636572
// Set up the googletag object to push cmds and slots onto array stacks
// for proper async handling
window.googletag = window.googletag || {};
window.googletag.cmd = window.googletag.cmd || [];
window.googletag.empty_slots = window.googletag.empty_slots || [];
window.googletag.cmd.push(() => {
// Set up page for SRA and disable auto loading of ads
window.googletag.pubads().enableSingleRequest();
window.googletag.pubads().disableInitialLoad();
window.googletag.enableServices();
// The empty slots attribute will hold any ad slots that haven't been
// loaded by the IntersectionObserver. DFPs changeCorrelator historically
// times out after 30 seconds. We refresh any empty slots after 25 seconds
// to ensure they use the same SRA request
setTimeout(() => {
window.googletag.my_observer.disconnect();
if (window.googletag.empty_slots) {
window.googletag.pubads()
.refresh(window.googletag.empty_slots, {changeCorrelator: false});
}
}, 25000);
});
</script>
<style>
.gdfp {
background: #CCC;
margin-bottom: 150vh;
width: 250px;
height: 250px;
}
</style>
</head>
<body>
<div class="gdfp"></div>
<div class="gdfp"></div>
<div class="gdfp"></div>
</body>
<script>
// Create an observer that will load any ad within 150px of the viewport.
// Observer is assigned to the global googletag object so it can be cleared
// after the 30 second window has passed
window.googletag.my_observer = new IntersectionObserver((items) => {
items.forEach(i => {
// Loop through possible elements to find the one currently intersecting
if (!i.isIntersecting) return;
// Stop watching this element
window.googletag.my_observer.unobserve(i.target);
// Push a function onto the cmd stack to remove this ad slot from our
// cache list and load the ad with the frozen changeCorrelator
window.googletag.cmd.push(() => {
let n = i.target.getAttribute('data-gdfp-slot');
let i = window.googletag.empty_slots.indexOf(slot);
let slot = window.googletag.pubads().getSlots()[n];
window.googletag.empty_slots.splice(i, 1)
window.googletag.pubads().refresh([slot], { changeCorrelator: false });
});
});
}, { rootMargin: '150px' });
window.googletag.cmd.push(() => {
let ads = document.querySelectorAll('.gdfp');
ads.forEach((i, n) => {
i.setAttribute('id', 'gdfp_' + n);
i.setAttribute('data-gdfp-slot', n);
let slot = window.googletag
.defineSlot('/dfpid/slot', [300, 250], i.id)
.addService(window.googletag.pubads());
// Push the slot onto the empty_slots array, will be removed as it is
// loaded. Call display to activate slot and observe with observer
window.googletag.empty_slots.push(slot);
window.googletag.display(i.id);
window.googletag.my_observer.observe(i);
});
});
</script>
</html>
@martinsvoboda
Copy link

Hi Dave, thanks for sharing this. Now, GPT supports ad lazy load. Does your solution have any advantages over the official one? https://developers.google.com/publisher-tag/samples/lazy-loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment