prebid / Prebid.js

Setup and manage header bidding advertising partners without writing code or confusing line items. Prebid.js is open source and free.
https://docs.prebid.org
Apache License 2.0
1.28k stars 2.05k forks source link

Plugin Architecture #326

Closed nickjacob closed 7 years ago

nickjacob commented 8 years ago

I don't know if this has already been talked about, but I had a couple different ideas that I think could benefit from some kind of plugin API:

E.g., based on Forensiq/IAS output or DMP segment, etc, disable certain bidding partners. Just something like:


function BotDetectionPlugin(options) {
  this.biddersByRisk = options.biddersByRisk || {
    highRisk: ['riskyBidder', 'aggregateDemandSource'],
    lowRisk: ['premiumDemandSource']
  };
}

// es6 syntax
BotDetectionPlugin.prototype = {
  [EVENTS.BID_REQUESTED](bidder) {
    return this.getRiskLevel().then(risk => {
      if (this.biddersByRisk[risk].indexOf(bidder.bidderCode) !== -1) {
        return Promise.resolve(bidder);
      }
      return Promise.reject(bidder);
    });
  },
};

pbjs.registerPlugin(new BotDetectionPlugin({}));

or another idea -- use received bids to put additional ads on the page (like postbidding):

function RemantDemandRendererPlugin(options) {
  this.eligibleBids = {};
  // places on the page we could put additional ads
  // beyond what comes in through the adserver
  this.remnantSlots = document.querySelectorAll(ADDL_SLOT_SELECTOR);
}

RemnantDemandRendererPlugin.prototype = {
  [EVENTS.BID_RESPONSE](bidResponse) {
    // add to eligible bids
  },
  [EVENTS.BID_WON](renderedBid) {
    // remove from eligable bids
  },
  [EVENTS.BID_TIMEOUT]() {
    setTimeout(this._finish.bind(this), DFP_RESPONSE_TIME);
  },
  _finish() {
    // maybe DFP returned a 300x250 where we have room for 300x600?
    if (!this.hasAvailableSpaceForAds()) return;
    utils._each(this.remnantSlots, (slot) => {
      const bids = this.eligibleBids[slot.size].sort(sortByCPM);
      slot.renderAd(bids.shift());
    });
  },
};

Of course this uses promises (which I know we don't right now), The plugin registration would basically just add event listeners for all methods defined. Then we just need to do a Promise.all() or equivalent on the return values of the handlers when we emit() the events in the lifecycle.

eg:

// (in it utils/events/emit)
function emit(event, ...args) {
  return Promise.all(
    utils.map(
      events._handlers[event],
      fn => fn(event, ...args)
    )
  );
}

Just one idea for an API w/ minimal footprint. But I think a flexible plugin API would be really great, esp for other 3rd parties in the ecosystem that want to adapt to header (e.g., viewability, traffic/fraud measurement, DMPs), could also let someone build a DIY in-image solution (make-your-own gumgum) etc

mkendall07 commented 8 years ago

Hey @nickjacob -need to wrap my head around this a bit... will review and add some comments later.

mkendall07 commented 8 years ago

@nickjacob Have you had any chance to work on this?

mkendall07 commented 7 years ago

These ideas will be incorporated into prebid 1.0.