Prebid Integration


Prebid Integration

The Rumble player can support Prebid thanks to two sets of functionalities in the player:

  1. api.clearAds() / api.insertAd( [timecode] , [waterfall] ) This allows you to setup what ad stacks you want to run, in a simple set up you can use these to set up the ads within the player when the bidding is completed.

  2. api.on(‘adRequest’, function( [ad] ) { … } ); This allows you to intercept an ad request before it is called, where you can replace the tag with a new one. You can also ask the player to wait if the bidding has not completed yet.

Simple pre-roll Setup

The following is an example of implementing a pre-roll ad with Prebid.

This example uses a test version of Prebid.js and is not recommended for production use. You should build Prebid from source or use their Download page to make sure only the necessary bidder adapters are included.

Also make sure to replace [PUBID] with your publisher ID, this can be found in any of the embed codes you are provided on Rumble.com while being logged into your account.

<div id="videoplayer"></div>

<script async src="//acdn.adnxs.com/prebid/not-for-prod/prebid.js"></script>

<script>!function(r,u,m,b,l,e){r._Rumble=b,r[b]||(r[b]=function(){(r[b]._=r[b]._||[]).push(arguments);if(r[b]._.length==1){l=u.createElement(m),e=u.getElementsByTagName(m)[0],l.async=1,l.src="https://rumble.com/embedJS/u[PUBID]"+ /* replace [PUBID] */ (arguments[1].video?'.'+arguments[1].video:'')+"/?url="+encodeURIComponent(location.href)+"&args="+encodeURIComponent(JSON.stringify([].slice.apply(arguments))),e.parentNode.insertBefore(l,e)}})}(window, document, "script", "Rumble");
</script>

<script>
  /* Rumble player code */
  var preroll_ad;

  function setRumblePlayerAd(url){
    if( typeof(preroll_ad) == 'function' ) {
      return preroll_ad( url );
    }
    preroll_ad = url;
  };

  Rumble("play",{
    video: "[VIDEO]", /* replace this with the video you want to use */
    div:   "videoplayer",
    api:   function(api){
      var ad_timeout;

      var clear_ad_timeout=function(){
        if(ad_timeout) {
          clearTimeout(ad_timeout);
          ad_timeout = 0;
        }
      };

      /* clear the ad stack loaded from "Ad Integrations" */
      api.clearAds();
      /* set up a pre-roll (timecode = 0), if you leave the text the player will just skip over it if Prebid fails, otherwise it will use this tag */
      api.insertAd(0, [ "fallback vast URL" ]);

      /* intercept the ad request so we can change it */
      api.on('adRequest', function(ad){
        clear_ad_timeout();

        /* if the ad is ready, use it */
        if ( typeof(preroll_ad) == 'string' ){
          var url = preroll_ad;
          preroll_ad = 0;

          return url;
        }

        /* set up the callback function for when the ad is ready */
        preroll_ad = function(url){
          clear_ad_timeout();

          ad.callback(url);
          preroll_ad = 0;
        };

        /* have the player wait a max of 2 seconds */
        ad_timeout = setTimeout(function(){
          /* use what was originally defined */
          ad.callback();
        }, 2000);

        /* ask the player to wait */
        return true;
      });
    }
  });


  /* Prebid code */
  var pbjs = pbjs || {};
  pbjs.que = pbjs.que || [];

  /*
   Prebid Video adUnit
   */

  var videoAdUnit = {
    code: 'video1',
    sizes: [640,480],
    mediaTypes: {
      video: {
        context: "instream"
      }
    },
    bids: [
      {
        bidder: 'appnexus',
        params: {
          placementId: '13232361', // Add your own placement id here

          video: {
            skipppable: true,
            playback_method: ['auto_play_sound_off']
          }
        }
      }
    ]
  };

pbjs.que.push(function(){
    pbjs.addAdUnits(videoAdUnit); // add your ad units to the bid request

    pbjs.setConfig({
      debug: true,
      cache: {
        url: 'https://prebid.adnxs.com/pbc/v1/cache'
      }
    });

    pbjs.requestBids({
      bidsBackHandler: function(bids) {
        var videoUrl = pbjs.adServers.dfp.buildVideoUrl({
          adUnit: videoAdUnit,
          params: {
            iu: '/19968336/prebid_cache_video_adunit',
            cust_params: {
              section: "blog",
              anotherKey: "anotherValue"
            },
            output: "vast"
          }
        });

        setRumblePlayerAd( videoUrl );
      }
    });
  });
</script>

The above code can easily be modified to support more ads, and use mid or post rolls.

More robust example (advanced)

The following example shows a more advanced Prebid integration strategy. This example does not include the Prebid code as it is dependent on when you want to do the bidding.

<div id="videoplayer"></div>

<script>!function(r,u,m,b,l,e){r._Rumble=b,r[b]||(r[b]=function(){(r[b]._=r[b]._||[]).push(arguments);if(r[b]._.length==1){l=u.createElement(m),e=u.getElementsByTagName(m)[0],l.async=1,l.src="https://rumble.com/embedJS/u[PUBID]"+ /* replace [PUBID] */ (arguments[1].video?'.'+arguments[1].video:'')+"/?url="+encodeURIComponent(location.href)+"&args="+encodeURIComponent(JSON.stringify([].slice.apply(arguments))),e.parentNode.insertBefore(l,e)}})}(window, document, "script", "Rumble");
</script>

<script>
/* In this function you return the URL to the ad. The 'ad' variable will be the ad requested, which in this example can be 'preroll_1', 'preroll_2', etc.
 * This function gets called in bursts, with all the waterfall IDs of a given ad in succession
 * It will be called again with the next ad unit 5 seconds after the first waterfall ad is needed by the player in the current ad
 */
function request_ad(ad, callback){
    console.log("prepare ad "+ad);

    /* when ad is ready you use the callback function with the vast tag URL */
    callback(ad);
}

(function(){
    /* configuration section */
    var DEBUG = true;
    var player_id = 'videoplayer'; /* player div ID */
    var ad_timeout = 1500; /* number of ms the player will wait for an ad, not the same as prebid timeout */
    var player_div = document.getElementById(player_id);

    var setup_ads = function(){
        /* set up ad points for each new video, you can change this based on your needs, this is just an example */

        /* in the array of ads you can provide a URL or an ID to signify which ad we need */
        insert_ad(0, [
            'preroll_1',
            'preroll_2'
        ]);

        insert_ad('25%', [
            'midroll_25_1',
        ]);

        if(player_div.clientWidth > 600){
            insert_ad('50%', [
                'midroll_50_big_1',
                'midroll_50_big_2',
            ]);
        }else{
            insert_ad('50%', [
                'midroll_50_1',
            ]);
        }
    }


    /* Do not change below: code implementing prebid support, you should not have to change what is below */

    var api;
    var ads_queue = []; /* all ads defined, we will request next set of ads as the previous one is done */
    var ready_ads = {}; /* as ads become ready, we will populate this for the player to use */
    var prepare_on;

    var loaded_new_video = function(){
        if(DEBUG) console.log("Setting up ad cuepoints");
        ready_ads = {};
        ads_queue = [];

        api.clearAds();
        setup_ads();

        prepare_next_ads();
    };

    var insert_ad = function(timecode, waterfall){
        if(DEBUG) console.log("insert_ad timecode: " + timecode + "  , waterfall: " + waterfall.length + " ads");

        ads_queue.push(waterfall);
        api.insertAd(timecode, waterfall);
    };

    var ads_request = function(ad){
        var id = ad.url;
        var timeout;

        if(DEBUG) console.log("player is ready for: " + id);
        if( prepare_on && prepare_on == id ){
            prepare_on = false;
            setTimeout(function(){
                prepare_next_ads();
            }, 5000);
        }

        if( typeof(ready_ads[id]) == "string" ){
            /* ad is ready, let the player use it */
            return ready_ads[id];
        }

        ready_ads[id] = function(url){
            if(timeout){
                clearTimeout(timeout);
                timeout = 0;
            }

            ad.callback(url);

            ready_ads[id] = true;
        };

        timeout = setTimeout(function(){
            if(DEBUG) console.log("Ad : " + id + " has timed out");
            ready_ads[id] = true;

            ad.callback(false);
        }, ad_timeout);

        /* ask the player to wait */
        return true;
    };

    var prepare_next_ads = function(){
        if(ads_queue.length == 0) return;

        var next_ads = ads_queue.shift();

        if(DEBUG) console.log("Preparing next ad");

        /* we will prepare next set of ads based on this ad gets requested by the player */
        prepare_on = next_ads[0];

        /* go through the waterfall asking for ads */
        for(i=0; i<next_ads.length; i++){
            simple_request_ad(next_ads[i]);
        }
    };

    var simple_request_ad = function(id){
        request_ad(id, function(url){
            ad_ready(id, url)
        });
    }

    var ad_ready = function(id, url){
        if( typeof(ready_ads[id]) == 'function') {
            /* looks like the player is already waiting for an ad */
            ready_ads[id](url);
        }else if( ready_ads[id] ){
            /* already an ad defined with that id, or the player timed out on it */
            return;
        }

        /* have it ready for the player when its needed */
        ready_ads[id] = url;
    };

  /* You can configure the player as you see fit, just leave the player_id and api lines intact */
  Rumble("play",{
    video: "[VIDEO/PLAYLIST?]",
    div: player_id,
    api: function(api_object){
        /* the following 4 lines are required and should not be changed */
        api = api_object;
        api.on('loadVideo', loaded_new_video);
        api.on('adRequest', ads_request);
        loaded_new_video();
    }
  });

}());
</script>