Prebid.js: How to use a tag as passback if no bidder wins

Created on 8 Oct 2016  路  26Comments  路  Source: prebid/Prebid.js

If we have 7-8 bidders but they do not fill above our price floor, how do we set a standard JS or async JS tag to be the default passback?

Currently in our testing we see the House Ad when no bidders win.

We are also not using DFP or any adserver.

Thanks

question

Most helpful comment

You say that you don't use DFP... but you keep all the code of DFP! And you didn't even have the iframeDoc.

Here's the example you should test (sorry, I didn't found it before, almost every example is based on DFP):
http://prebid.org/dev-docs/examples/postbid.html

Test with this one, that should work :-)

All 26 comments

There is no built in way to do this... you could manually invoke a tag after the auction runs if you don't get any bids but that would require a bit of custom code.

What in the prebid.js code should be customized to allow a tag passback? Any suggestions or advice on best practices? Thanks

If you don't use DFP, then you should have a piece of code like:

pbjs.requestBids({
bidsBackHandler: function() {
  // callback when requested bids are all back
}
});

So, in this function, you may also have:

if (params && params['hb_adid']) {
  pbjs.renderAd(iframeDoc, params['hb_adid']);
}

If it's the case: just add an else statement, where you'll put your passback code. If you have a tag (such as a <script> tag), you can handle it this way (still with the iframe already created):

iframeDoc.open();
iframeDoc.write(tag); // this is your tag
iframeDoc.close();

Thanks @dugwood

I tried with your code and still see the House ad. Just for testing instead of a script tag to open a iframe, I inserted google.com as iframe, but still see House ad

Here is my code. I would appreciate it if you could give me some guidelines and let me know what I did wrong:

  <script>

    var PREBID_TIMEOUT = 3000;

    var adUnits = [{
        code: 'div-gpt-ad-1460505748561-0',
        sizes: [[300, 600], [300,250]],
        bids: [
          {
            bidder: 'aol',
            params: {
               placement: '7652173',
               network: '12763.1',
            }
          },
          {
            bidder: 'defymedia',
            params: {
               placementId: '4367693'
            }
          }
        ]
      }
    ];

    var pbjs = pbjs || {};
    pbjs.que = pbjs.que || [];

  </script>
 <script type="text/javascript" src="http://mydomain.com/prebid/prebid.js" async></script> 
  <script>

    var googletag = googletag || {};
    googletag.cmd = googletag.cmd || [];
    googletag.cmd.push(function() {
        googletag.pubads().disableInitialLoad();
    });

    pbjs.que.push(function() {
        pbjs.addAdUnits(adUnits);
        pbjs.requestBids({
          bidsBackHandler: function() {
            // callback when requested bids are all back
            if (params && params['hb_adid']) {
              pbjs.renderAd(iframeDoc, params['hb_adid']);
            } else {
              //tag = 'https://www.google.com';
              iframeDoc.open();
              iframeDoc.write(tag); // this is your tag
              iframeDoc.close();
            }
          }
        });
    });

    function sendAdserverRequest() {
        if (pbjs.adserverRequestSent) return;
        pbjs.adserverRequestSent = true;
        googletag.cmd.push(function() {
            pbjs.que.push(function() {
                pbjs.setTargetingForGPTAsync();
                googletag.pubads().refresh();
            });
        });
    }

    setTimeout(function() {
        sendAdserverRequest();
    }, PREBID_TIMEOUT);

  </script>
  <script>

    (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);
    })();


  </script>
  <script>

    googletag.cmd.push(function () {
        googletag.defineSlot('/19968336/header-bid-tag-0', [[300, 250], [300, 600]], 'div-gpt-ad-1460505748561-0').addService(googletag.pubads());

        googletag.pubads().enableSingleRequest();
        googletag.enableServices();
    });


  </script>
<div class="row">
  <div id="div-gpt-ad-1460505748561-0"> 
    <script>
      googletag.cmd.push(function() { googletag.display('div-gpt-ad-1460505748561-0'); });
    </script>
  </div>
</div>

Im not using DFP either and want to achieve same goal.

Thanks in advanced!

You say that you don't use DFP... but you keep all the code of DFP! And you didn't even have the iframeDoc.

Here's the example you should test (sorry, I didn't found it before, almost every example is based on DFP):
http://prebid.org/dev-docs/examples/postbid.html

Test with this one, that should work :-)

Yeah every example that I found was based on DFP so I assumed that I need that :)
Thanks a bunch @dugwood 馃憤

Yep, postbid was the example you want. Thanks @dugwood

Thank you @mkendall07 and @dugwood !

One final question, is the iframeDoc considered transparent or friendly - or how can we make it so? Are we able to pass the domain and URL through the iframe? Because we will be serving a standard JS tag behind it and that partner's tag will need to see the page info otherwise non-transparent impressions can cause monetization issues.

@jakczuhang, there should be no iframe restriction, as there's no src= in the frame. So basically, all browsers should let the inside script access the parent page. Give it a try with a simple script as:

<script>top.document.body.style.backgroundColor='red';</script>

It should set the parent with red background. Note that some partners' won't handle the fact that they are loaded within an iframe, so that may be an issue even if there's no domain restriction.

Great 馃憤

Thanks @dugwood for all your help 馃憤 I have one more question I hope you can answer.

In this Basic-example from prebid.org, under var adUnits we can have different codes/slots and sizes which means you can have all your prebid settings for whole page under one file, where as in this Postbid Example example I can see you have only one size var tagWidth = 300; var tagHeight = 250; and one code/slot.

Im a wrong or we can do the same thing as Basic-example from prebid.org and add different sizes & code under same code?

What I mean is that Wouldn't it be many duplications? And how to add sizes: [[300, 250], [300,600]] & sizes: [[728, 90], [970, 90]] as the Basic example?

Thanks in advanced!

You could run either one or two calls. If you want to run only one call to requestBids(), you just have to send two different objects in the same array adUnits. The basic example is the way to go for populating adUnits, and the postbid example is good for the requestBids() part. But you need to declare your 2 divs before running the call.

Also I doubt that you'll have any overhead by running two calls to requestBids(), so if it's easier to you, do it. That's what I'm doing as I don't always have the 2 slots with Prebid on the page (running after an adserver, which may load Prebid in the leaderboard, but not in the square slot).

Thanks again, @dugwood !

On the passback tag, because it's an iframe it won't be holding up the page as prebid is working? Would there be any benefit in running asynchronous javascript as a passback anyways or would there be negative effects in doing so?

If we went with Async JS tags, there is also a single header tag we run on the page once. If we used it in this case, can that header tag remain on the site or would it have to be included inside each and every iframe as well?

You can't run synchronous javascript (including 芦document.write禄) as you don't know if the page has finished loading or not. If you're talking about the script you'll set in the iframe, synchronous or asynchronous will work. So do as you please in this case.

Not that the iframe hasn't got any domain restriction (because there's no src), so you can communicate from within. So maybe you can access your header tag (using top.your_variable), and run the code this way.

I now use Postbid Example in my application (since I don't have/want DFP).

If you look at the code (jsfiddle section), I have added lines [4-38] & [44-76], in same .js file and included it that file to my head. For adding prebid.js, I use this In same file:

window.onload = function() {
  var imported = document.createElement('script');
  imported.src = 'http://domain.com/assets/prebid.js';
  imported.setAttribute("type", "text/javascript");
  imported.async = true;
  document.head.appendChild(imported);
}

Here is my complete code:

var tagWidth = 300;
var tagHeight = 250;

var bids = [{
    bidder: 'appnexus',
    params: {
       placementId: '4799418'
    }
  }, {
    bidder: 'aol',
    params: {
        placement: '12837',
        network: '123'
    }
  } 
];

var bidTimeOut = 1000;

// Define the passback HTML tag here. Note that this tag 
// is usually in either script tag form or iframe form. 
var passbackTagHtml = '<scr ' + ip src='My/Pass/Back.js'><scr' + 'ipt>';


window.onload = function() {
  var imported = document.createElement('script');
  imported.src = 'http://domain.com/assets/prebid.js';
  imported.setAttribute("type", "text/javascript");
  imported.async = true;
  document.head.appendChild(imported);
}

var pbjs = pbjs || {};
pbjs.que = pbjs.que || [];

var doNotChange = 'doNotChange';

pbjs.que.push(function() {
  var adUnits = [{
    code: doNotChange,
    sizes: [[tagWidth, tagHeight]],
    bids: bids
  }];

  pbjs.addAdUnits(adUnits);

  pbjs.requestBids({
    timeout: bidTimeOut,
    bidsBackHandler: function() {
      var iframe = document.getElementById('postbid_if');
      var iframeDoc = iframe.contentWindow.document;
      var params = pbjs.getAdserverTargetingForAdUnitCode(doNotChange);
      if (params && params['hb_adid']){
        pbjs.renderAd(iframeDoc, params['hb_adid']);
      } else {
        // If no bidder return any creatives, run passback.
        iframe.width = tagWidth;
        iframe.height = tagHeight;
        iframeDoc.write(passbackTagHtml);
      }
    }
  });
});

Everything works fine and I can see the ads. I first tested the prebid with my code on a page with no other ads (only prebid ads) and prebid loads fast BUT the problem is that, when I have the file inside a page with other _ads_, my prebid loads/shows after all other ads. It takes around 5-6 second before loading the prebid ads.

What can I do to make the performance better?

Why do you enclose the http://domain.com/assets/prebid.js in the window.onload? That's your issue.

You should run the code with something like:

(function(d, s) {
  var imported = d.createElement('script');
  imported.src = s;
  imported.setAttribute("type", "text/javascript");
  imported.async = true;
  d.head.appendChild(imported);
})(document, 'http://domain.com/assets/prebid.js');

As the document.head already exists. You can even remove the whole 芦function禄 part, that can work too (but your imported variable will be visible everywhere).

Thanks @dugwood, with that the ad loads faster, much faster, but page itself seems to just loading and loading, even after when all the ads where loaded.

skjermbilde 2016-10-21 kl 14 12 39

What causes that?

Appreciate all your help

Under Google Chrome, just open the Console with F12, then look at the Network tab, you'll easily find the culprit.

Thanks @dugwood, It looks like its this file http://omnieye.io/assets/prebid-586fcbadda2d53729605dac03e2fc903e5ba5916702c45aab13893c9b13c1977.js. When I removed it, loading was fine.

This the prebid.js file I downloaded from prebid.org and I only added AOL and DefyMedia.

I appreciate it, if you can confirm or let me know how to fix it.

You can see it here in action

I add the prebid.js with your code below:

(function(d, s) {
  var imported = d.createElement('script');
  imported.src = s;
  imported.setAttribute("type", "text/javascript");
//  imported.async = true;
  d.head.appendChild(imported);
})(document, 'http://omnieye.io/assets/prebid-586fcbadda2d53729605dac03e2fc903e5ba5916702c45aab13893c9b13c1977.js');

Why don't you serve the prebid.js from your own server? You need to keep the 芦async禄 flag, else if the file is slow to load, it will block other resources.

I removed the async only for test to see if does help with loading. Reason is we will have all our assets load from that website and it has to be there since we are doing some background ops there as well.

Is it anyway we can load the file from other source then our own website and fix the loading thing?

Thanks

I can't see any issue with this resource, hence I can't help you... It loads fine to me (from France). Removing async will just add some more time and blocking.

Okei Thanks for you help @dugwood 馃憤

Hi again @dugwood One last thing. I got some other friends from USA and India to test.

The loading doesn't stop even when we the prebid.js from my own website.

Thanks for your help

Try it with: https://www.webpagetest.org/
And you'll have the waterfall of requests, what you don't seem to interpret well on your browser.

Thank you so much 馃憤

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Rubioli picture Rubioli  路  3Comments

marvinferreira picture marvinferreira  路  6Comments

mkendall07 picture mkendall07  路  5Comments

dugwood picture dugwood  路  4Comments

jdwieland8282 picture jdwieland8282  路  5Comments