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>
@mbrowne
Copy link

mbrowne commented Feb 4, 2019

I am investigating how to support both ad refreshing and roadblocked ads, so thank you for this...I'm trying to determine if this is an appropriate solution for our site, and I went to the link you provided (https://support.google.com/admanager/answer/179039?hl=en) but that link just points to the most recent release notes for ad manager (which currently is the January 28, 2019 release). Which release notes were you actually linking to originally? Thanks

@davewalker235
Copy link
Author

Hi Matt, I just updated the gist with the best link I could find for the release notes, please see above for a description of where to find the information.

@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