Using Standard Google Publisher Tag as Dynamic Size Passbacks (Builder & Code Snippet)

On November 4th 2019 Google quietly released a new set of release notes recommendations, included within this release is a new GPT passback recommendation that may cause concern for some publishers.

The use of definePassback() and defineOutOfPagePassback() is now actively discouraged, since these functions behave synchronously and may be blocked by certain browsers. The new recommendation for those looking to passback from a 3rd party ad server, use a standard Google Publisher Tag written into an iframe.

We’ve updated and created a new Dynamic Size Passback that utilises the standard Google Publisher Tag, you can copy the code snippet below or use our New Dynamic Passback Generator.

The below code snippet will dynamically request ads based on the Ad slot size (e.g Ad Slot: 300×250, Ad requested 300×250), this can be used to passback when you are unsure what slot the passback will be served into.

This method supports iframes and safe frames, replace the variables within advertisingConfig with those of your adserver.

<!-- Google Ad Manager AdSlot Dynamic Size Passback (by AdTech.dev) ### Size: [[winW,winH]]-->
<script id = 'script-gpt-ad-injected-passback-slot'async src = 'https://securepubads.g.doubleclick.net/tag/js/gpt.js' ></script> 
<script>
  var advertisingConfig = {
    pageURL: window.location.host,
    googleads: {
      networkCode: 21834569717, //GAM network code
      adunitId: 'adtech.dev/test-adunit/', //GAM adunit id
      slotsTargeting: {
        origin: 'goog', //impressions origin
        originsrc: 'adtech', //impressions source
        originSite: 'unknown_undefined', //auto set by script
        passbackName: 'goog_passback_multiplatform__multisize', //name
        passbackType: 'multiplatform', //platform
        passbackRefresh: 'true', //passback true/false
      }
    },
    features: {
      refresh: {
        enabled: true, //passback true/false
        gadsViewabilityTime: 30 // Seconds to wait after impression viewable
      },
      headerBidding: {
        enabled: false //header bidding enabled true/false     
      }
    },
    script: {
      winW: window.innerWidth || window.document.documentElement.clientWidth || 0,
      winH: window.innerHeight || window.document.documentElement.clientHeight || 0,
      adslotW: '',
      adslotH: '',
      supportedAdW: [300, 320, 728, 970],
      supportedAdH: [],
    }
  };
  
  (function init() {
    advertisingConfig.script.adslotW = closestSize(advertisingConfig.script.winW, advertisingConfig.script.supportedAdW);
    if (advertisingConfig.script.adslotW == 0) {
      advertisingConfig.script.supportedAdH = [0]
    } else if (advertisingConfig.script.adslotW == 300) {
      advertisingConfig.script.supportedAdH = [50, 100, 155, 250, 480, 600];
    } else if (advertisingConfig.script.adslotW == 320) {
      advertisingConfig.script.supportedAdH = [50, 100, 480];
    } else if (advertisingConfig.script.adslotW == 728) {
      advertisingConfig.script.supportedAdH = [90]
    } else if (advertisingConfig.script.adslotW == 970) {
      advertisingConfig.script.supportedAdH = [250]
    }
    advertisingConfig.script.adslotH = closestSize(advertisingConfig.script.winH, advertisingConfig.script.supportedAdH);
    if (advertisingConfig.script.adslotW == 0 || advertisingConfig.script.adslotH == 0) {
      return;
    }
    createDiv(advertisingConfig);
    hostDomain(advertisingConfig);
    requestAd(advertisingConfig);
  })();
  
  function closestSize(size, arr) {
    var value = match = 0;
    for (var i = 0; i < arr.length; i++) {
      value = arr[i];
      if (value <= size) {
        match = value;
      }
    }
    return match;
  }
  
  function createDiv(advertisingConfig) {
    var d = document.createElement('div');
    d.setAttribute('class', 'gpt gpt-ad-injected-passback-slot');
    d.setAttribute('id', 'div-gpt-ad-injected-passback-slot');
    d.style.width = advertisingConfig.script.adslotW + 'px';
    d.style.height = advertisingConfig.script.adslotH + 'px';
    var s = window.document.getElementById('script-gpt-ad-injected-passback-slot');
    s.parentNode.insertBefore(d, s);
  }
  
  function hostDomain (advertisingConfig){
    if (window.location.host == 'tpc.googlesyndication.com' || window.location.host == 'partner.googleadservices.com'){
      advertisingConfig.googleads.slotsTargeting.originSite = 'unknown_safeframe';
    } else {
      try {
        var a = window.document.createElement('a');
        a.href = location;
        var hostName = a.hostname;
        var patharray = a.hostname.split('.').reverse();
        if (patharray !== null && patharray.length > 1) {
          advertisingConfig.googleads.slotsTargeting.originSite = patharray[1] + '.' + patharray[0];
          if (hostName.toLowerCase().indexOf('.co.uk') !== -1 && patharray.length > 2) {
            advertisingConfig.googleads.slotsTargeting.originSite = patharray[2] + '.' + advertisingConfig.googleads.slotsTargeting.originSite;
          }
        } 
      } catch(e){}
      }
      return advertisingConfig.googleads.slotsTargeting.originSite;
  }
  
  function requestAd(advertisingConfig) {
    window.googletag = window.googletag || {cmd: []};
    // Set-up adslot and add eventlistener if slot targeting includes refresh=true
    googletag.cmd.push(function () {
      googletag.defineSlot('/' + advertisingConfig.googleads.networkCode + '/' + advertisingConfig.googleads.adunitId, [advertisingConfig.script.adslotW, advertisingConfig.script.adslotH], 'div-gpt-ad-injected-passback-slot')
      .setTargeting('origin', [advertisingConfig.googleads.slotsTargeting.origin])
      .setTargeting('originsrc', [advertisingConfig.googleads.slotsTargeting.originsrc])
      .setTargeting('originsite', [advertisingConfig.googleads.slotsTargeting.originSite])
      .setTargeting('originsz', [advertisingConfig.script.winW + 'x' + advertisingConfig.script.winH])
      .setTargeting('passback', [advertisingConfig.googleads.slotsTargeting.passbackName])
      .setTargeting('passbacktype', [advertisingConfig.googleads.slotsTargeting.passbackType])
      .setTargeting('passbackrefresh', advertisingConfig.googleads.slotsTargeting.passbackRefresh)
      .addService(googletag.pubads());
      googletag.enableServices();
      googletag.display('div-gpt-ad-injected-passback-slot');
      
      if (advertisingConfig.features.refresh.enabled == true) {
      googletag.pubads().addEventListener('impressionViewable', function(event) {
        var slot = event.slot;
        if (slot.getTargeting('passbackrefresh').indexOf(advertisingConfig.googleads.slotsTargeting.passbackRefresh) > -1) {
          setInterval(function() {
            googletag.pubads().refresh([slot]);
          }, advertisingConfig.features.refresh.gadsViewabilityTime * 1000);
        }
      });
    }
  });
  } 
</script>

Set page URL

Because it is served in an iframe, GPT may not be able to determine the URL where the tag is being served. If you are using Ad Exchange or AdSense to fill these passback impressions, then without a URL, these systems can’t send contextual information about the page to buyers. This can lead to lower fill rates or lower CPMs (and in some cases, rejected ad requests). To avoid this, we recommend that you have your third-party network or ad server append .set("page_url", "URL") to the passback tag.

To pass the URL to a third-party ad network or ad server, use the PATTERN macro (for example, %%PATTERN:url%%) to insert the URL in a third-party tag.

Use passback tags to serve ads on another publisher’s website

Passback tags can be used to serve ads from your network to another publisher’s website. In these cases, the passback tag would be trafficked by the other publisher and would return an ad from your own Ad Manager network.

Additional information about passbacks can be found here.