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

Pre-Auction Filters and the Prebid Ad Slot #4149

Closed bretg closed 4 years ago

bretg commented 5 years ago

Feature Overview

The Prebid AdUnit 'code' is a mixed attribute that can be either the GPT slot name or the div ID. The undecided nature of this value makes the 'code' harder to utilize for reporting and targeting.

This feature proposes a resolution to the long-running issue of the confusing AdUnit code value by establishing conventions for passing in something more descriptive and stable. It's optional for publishers to use it, and Bid Adapters and Analytics Adapters will not need to change unless they want to take advantage of the more stable field.

Details

  1. Some publishers utilize the same 'slotname' in the page for multiple holes-in-the-page, differentiating in the ad server by size. e.g.
    • defineSlot('/1111/homepage', [[300,250]], 'div-293rj893p9wje9we9fj');
    • defineSlot('/1111/homepage', [[728,90]], 'div-j98s9u9usj987665da');
    • defineSlot('/1111/homepage', [[160,600]], 'div-B2q3s4gseshekhsei9sh');
  2. In order to be able to display the right ad in the right hole, the Prebid AdUnit therefore sets the 'code' to the div ID instead of the slotname.
  3. A div ID is sometimes a random number, and in any case, can change over time as refactoring happens
  4. Therefore, to get a stable ID that's useful from a business perspective to identify a hole-in-the-page, we need to add yet another identifier to the world... introducing the Prebid Ad Slot, or pbAdSlot

Currently, Prebid.js doesn't link the adunit to ad ad server slot until after the auction -- it happens during the call to set the targeting. But since the pbAdSlot may be the ad slot name, we need to know the GPT slot before the auction.

What's proposed is a new Prebid.js hook that gives publishers the option to define and utilize a pbAdSlot. A possible source of the pbAdSlot is a hunt-path like:

However, publishers are likely to want to customize the definition of Prebid Ad Slot in a number of ways, e.g.

So any approach will need to be flexible. Instead of defining a complex module that implements a mini-compiler capable of delivering the necessary flexibility, we propose providing a generic hook in Prebid.js auction processing and reference functions that publishers can modify to work for their scenarios.

Business Case

Prebid has come a long way from its humble beginnings as a set of open-source javascript tools for header bidding. Today, Prebid is a core system within the ad stack, and publishers are asking Prebid to be able to do more: provide robust reporting, centralize common functions like pricing and ad quality controls, and target PMP deals. Power users of Prebid are learning that the wrapper performs best when its configuration can be fine tuned to suit the inventory it serves, and want the wrapper to be able to respond dynamically to the characteristics of each page view.

This set of enhancements require a system for inventory classification and segmentation that resembles what one would find in an ad server or exchange. Publishers, for example, maintain different pricing restrictions for differing segments of inventory, and therefore construct detailed pricing control schemes using inventory targeting. Today, these controls must be duplicated across multiple demand partner interfaces, and publishers are looking to see it be centralized to the wrapper. To provide this feature, the wrapper must also be able to address specific segments of inventory and set unique pricing controls for each.

There are many use cases for Ad Slot; the primary near term use is reporting. The growth of Prebid-centric analytics solutions such as Roxot, Pubwise, Rivr, and many others demonstrates the value that Prebid offers as a home for consolidated reporting on the a publisher’s programmatic business.

Where Prebid falls short today in reporting is its limited ability to provide granular, flexible inventory segmentation. Prebid’s existing inventory object, the adUnit, cannot meet these requirements because it contains a verbose list of required inventory and bidder attributes. Each ad unit created adds a significant amount to Prebid’s overall payload. For publishers with large and complex networks, segmenting inventory with adUnit is not feasible.

Prebid clearly needs a more robust inventory management structure in order to meet the use cases stated above, but developing it and driving its adoption is no small task. For that reason, the initial implementation is highly flexible, allowing publishers to insert any string that they use to identify inventory for inventory segmentation today. For the majority of users, this will be the Google Ad Manager Ad Unit Path. The GAM Ad Unit has the benefit of being easily parseable, allowing reporting and targeting systems to take advantage of its hierarchy to allow publishers to group and subdivide inventory quickly and easily. Over time, the Prebid Ad Slot could evolve into a more robust, stand alone system.

Requirements

  1. Supporting the Prebid Ad Slot should be an optional hook in Prebid.js. A function can be registered to run as a pre-auction filter that can modify the AdUnit array.
  2. The hook function should be able to add the Prebid Ad Slot to the AdUnits ad adunit-specific first party data. i.e. AdUnit.context.pbAdSlot.
  3. The hook function should be able to obtain the pbAdSlot from at least these locations: a. AdUnit.code b. AdUnit.context.pbAdSlot c. div data elements d. ad server slotname
  4. The hook function must be able to update the AdUnit context data.
  5. The Prebid Ad Slot must be available to client-side and server-side adapters as First Party Data.
  6. Publishers should be able to add other functions that modify the AdUnit array before the auction.

Proposed Interfaces

1) The pbAdSlot attribute is added to the Prebid Ad Unit in the First Party Data context.

var AdUnit={
   code: "40989gjr9e98ajrosiero",
   fpd: {
      context: {
        pbAdSlot: "/1111111/homepage/med-rect-2"
        ...
      }
   },
   ...
};

2) Configuration allows the page to define pre-auction filter functions:

        var setPbAdSlot = function setPbAdSlot(adunits) {
            console.log('setPbAdSlot called');
            ... logic to find and set fpd.context.pbAdSlot for each AdUnit ...
        };

        pbjs.onEvent('onBeforeRequestBids', setPbAdSlot);

3) The Prebid Server Bid Adapter must be able to pass the Prebid AdSlot through the OpenRTB request in imp[].ext.context.data.pbadslot:

{
  imp: [{
    ...
    ext: {
      ...
      context: {
        data: {
          pbadslot: "/1111111/homepage/med-rect-2"
        }
      }
    }
  }]
}
stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

bretg commented 4 years ago

We discussed this last week and determined that we would add a “onBeforeRequestBids” external event and pass through args for mutation.

The proposal is that this event will be fired after conditional adunit processing but before adunits are copied to bidrequests. It will pass in the array of adunits and allow the page function to alter the contents.

For example:

        var setPbAdSlot = function setPbAdSlot(adunits) {
            console.log('setPbAdSlot called');
            ... logic to find and set context.pbAdSlot for each AdUnit ...
        };

        pbjs.onEvent('onBeforeRequestBids', setPbAdSlot);
bretg commented 4 years ago

Proposal is that we limit this to cover just the stated use case. We call the event onBeforeRequestBids and it fires just before copying the adunits to the bidRequest object.

If there are other use cases in the future that require updating the ad units before conditional logic, that person can figure out the details.

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

bretg commented 4 years ago

For the record, this is done in PBJS. PBS doesn't need changes unless an adapter wants to pass the value through their endpoint on a different attribute.

bretg commented 4 years ago

For the record, just found that the implementation was slightly mismatched from the original spec.

Originally the openrtb definition was imp[].ext.context.data.adslot, but it got implemented in pbsBidAdapter as imp[].ext.context.data.pbadslot.

Changing the spec and PBS because that's easier than upgrading clients to a patched PBJS.