I need to trigger some JavaScript after DFP has finished rendering all the ads on the page - or at least when it has triggered collapseEmptyDivs (which
Check out the jQuery DFP extension I'm working on... it is still a bit of a work in progress but provides the callback you are after.
An example of how to use it is in this file.
You will see two callbacks are available... after each ad has loaded and after all ads have loaded. A class is also set on the ad unit container element, this can either be display-none (when no ad is found), display-block (when an ad is found) or display-original (for when no ad is found but the container div contained content to begin with, I use this for over riding certain parts of sites with ad content when required). These classes are of course useful to work with once inside the callback.
If you need to identify the render end of a specific slot ( useful if you are using same creative for multiple slots ) you can do the following
googleAd = googletag.defineSlot('/xxxxx/web_top_AAAxAAA', [xxx, xxx], 'div-id').addService(googletag.pubads());
googletag.pubads().addEventListener('slotRenderEnded', function(event) {
if( event.slot.W == googleAd.W ){
// your code here
}
});
I hacked googletag's debug_log.log function and pushed it through jQuery to fire events on a lot of DFP's actions. The hack does require jQuery.
https://github.com/mcountis/dfp-events
I'm pretty sure that DFP doesn't provide for a callback after the ad has rendered. I have used the following code to do this. It calls the callback function after one of the following has happened:
-The ad has loaded and the iframe has rendered
-No ad was loaded, and the ad unit was hidden by collapseEmptyDivs()
-A certain amount of time has passed (in this case, 2 seconds) with neither one happening. Like if there was some sort of network error connecting to DFP.
adId would be the id of your ad container
assumes you are using jQuery
function callback() {
//your callback function - do something here
}
function getIframeHtml(iframe) {
if(iframe.contentWindow && iframe.contentWindow.document && iframe.contentWindow.document.body && iframe.contentWindow.document.body.innerHTML) {
return iframe.contentWindow.document.body.innerHTML;
}
return null;
}
var dfpNumChecks = 20;
var dfpCheckCount = 0;
var dfpCheckTimer = 100;
function dfpLoadCheck(adId) {
var nodes = document.getElementById(adId).childNodes;
if(nodes.length && nodes[0].nodeName.toLowerCase() == 'iframe' && getIframeHtml(nodes[0])) {
//the iframe for the ad has rendered
callback();
return;
} else if($('#' + adId).css('display') == 'none' || (dfpCheckCount >= dfpNumChecks)) {
//the ad unit has been hidden by collapseEmptyDivs()
callback();
return;
} else {
dfpCheckCount++;
setTimeout(function() { dfpLoadCheck(adId) }, dfpCheckTimer);
}
}
The GPT API now has a callback that is triggered after each slot is filled.
For example:
googletag.pubads().addEventListener('slotRenderEnded', function(event) {
console.log('Creative with id: ' + event.creativeId +
' is rendered to slot of size: ' + event.size[0] + 'x' + event.size[1]);
});
See https://developers.google.com/doubleclick-gpt/reference#googletag.events.SlotRenderEndedEvent
Load script in the part of your page:
// set global variable if not already set
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
// load asynchronously the GPT JavaScript library used by DFP,
// using SSL/HTTPS if necessary
(function() {
var gads = document.createElement('script');
gads.async = true;
gads.type = 'text/javascript';
var useSSL = 'https:' === document.location.protocol;
gads.src = (useSSL ? 'https:' : 'http:') + '//www.googletagservices.com/tag/js/gpt.js';
var node =document.getElementsByTagName('script')[0];
node.parentNode.insertBefore(gads, node);
})();
Initialise google publisher tag with the following script, preferable as well in the section of your page:
// can be moved as well in the body
// if using async mode, wrap all the javascript into googletag.cmd.push!
googletag.cmd.push(function() {
// set page-level attributes for ad slots that serve AdSense
googletag.pubads().set("adsense_background_color", "FFFFFF");
googletag.pubads().setTargeting("topic","basketball");
// enables Single Request Architecture (SRA)
googletag.pubads().enableSingleRequest();
// Disable initial load, we will use refresh() to fetch ads.
// Calling this function means that display() calls just
// register the slot as ready, but do not fetch ads for it.
googletag.pubads().disableInitialLoad();
// Collapses empty div elements on a page when there is no ad content to display.
googletag.pubads().collapseEmptyDivs();
// Enables all GPT services that have been defined for ad slots on the page.
googletag.enableServices();
});
Register slots individually (can be generated with a foreach loop) and render them. The event listener can be registered as well per slot. Here the important part: make sure that you refresh them together to avoid ending up with the same ads on both slots (if the ad is assign to both slots) => googletag.pubads().refresh([slot1, slot2]]);
// this code can be moved externally to improve performance
googletag.cmd.push(function() {
// define slot1
slot1 = googletag.defineSlot(
"/1234/travel/asia/food",
[728, 90],
"banner1"
)
.addService(googletag.pubads())
.setTargeting(
"interests",
["sports", "music", "movies"]
);
// prerender the slot but don't display it because of disableInitialLoad()
googletag.display("banner1");
// define slot2
slot2 = googletag.defineSlot(
"/1234/travel/asia/food",
[[468, 60], [728, 90], [300, 250]],
"banner2"
)
.addService(googletag.pubads())
.setTargeting("gender", "male")
.setTargeting("age", "20-30");
// prerender the slot but don't display it because of disableInitialLoad()
googletag.display("banner2");
// add event to sign the slot as redered or not
googletag.pubads().addEventListener('slotRenderEnded', function(event) {
if (event.slot === slot1 || event.slot === slot2) {
// do something related to the slot
}
});
// refresh all container ads and show them
// very important to call refresh with an array to avoid
// multiple callback to the registered event
googletag.pubads().refresh([slot1, slot2]);
});
<div id="banner1" style="width:300px; height:250px;"></div>
<div id="banner2" style="width:300px; height:250px;"></div>
After the ad has been rendered, the callback gets triggered.
For more information have a look on this file: https://github.com/davidecantoni/googletag