prebid-server: Analytics enhancement: return nobids, errors, and removals

Client-side analytics adapters don’t have access to what actually happened with PBS bids unless they’re successful.

The ORTB protocol was designed to carry just actual successful bids, not information about the status of all bid attempts. However, with the Prebid world being part client-side and part server-side, holisitic analytics is made more difficult. It’s quite complicated to log auction info/results separately: some client-side, some server-side and then sew them all together at scale on the backend.

e.g. say a request contains calls to bidderA, bidderB, and bidderC. If only bidderA responds, then the resulting seatbid[].bid[] contains only bidderA. The client doesn’t know what happened to bidderB or bidderC: no bid? error? GDPR removal? Price floor removal?

So we would like to propose a new optional request flag that instructs PBS to include the status of all bid attempts in the response.

Proposal

  1. Support a new request flag ext.prebid.returnallbidstatus: true - this causes PBS to create special entries in the response for every imp+bidder in the request, even nobids and errors.

This is independent from the debug/test option.

  1. When the flag is set and a bidder doesn’t have a bid for any reason, create a ‘non-bid’ response just before “Stage 8 - Auction Response”
ext.seatnonbid: [{
     seat: "bidderA",               // required - biddercode to be processed by client
     ext.prebid: {
         origseat: "bidderC"         // optional - aligning with issue #2424
         meta.adaptercode: "bidderM"  // optional - aligning with issue #2174
     },
     nonbid: [{
         impid: STRING.              // required, $.imp[].id
         statuscode: ENUM,           // required
         ext: {  },                  // for future extension
     }]
}]

We considered just collating this data in seatbid.bid, but we can’t be sure that that all clients will know what to do with the extra info: e.g. SDK, SSAI servers, etc. Sure, they shouldn’t be passing ext.prebid.returnallbidstatus if they can’t handle the response, but it seems safer to place the non-bids in a different location.

We also considered whether to put this extension in ext.prebid.seatnonbid but decided that reporting on the non-bids is not prebid-specific.

  1. The bids list included should be the list of imps+bidders present just before Stage 3 - Processed Auction Request.

  2. Some reasons a bidder might not have a bid response include:

  • nobid
  • bidder error
  • request removed
    • “gdpr”: GDPR removed the bidder
    • “moduleA”: a module removed the bid request before being sent out
  • response removed
    • “floor”: bid removed due to pricefloor
    • “currency”: bid removed because it was in a currency PBS couldn’t convert
    • “moduleB”: a module removed the bid response after the request. e.g. “ortb2block”, “creativevalidation”

Each of these scenarios should be considered test cases. It’s not necessary for PBS-core to be able to immediately be able to distinguish these. If there are scenarios where there’s not enough info currently available to detail why a bid request/response was removed, it can supply a reason of “unknown” for now.

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Comments: 26 (24 by maintainers)

Commits related to this issue

Most upvoted comments

@pm-harshad-mane : I have already added my comments on that PR. here is the link - https://github.com/prebid/prebid-server/pull/2505#discussion_r1158834062

@ShriprasadM has proposed adding bid fields to the nonbid object. This covers the case where there was an actual bid that was rejected (e.g. floors) and the client-side analytics wants to have insight into the key bid parameters.

{
ext.seatnonbid: [{
     seat: "bidderA",
     ext: {
       origbidcpm: FLOAT, // optional
       origbidcur: STRING, // optional
       prebid: {
         origseat: "bidderC"
         meta.adaptercode: "bidderM"
       }
     },
     nonbid: [{
         impid: STRING.              // required, $.imp[].id
         statuscode: ENUM,           // required
         // optional bid params
         price: FLOAT,
         cur: STRING,
         adomain: STRING,
         cattax: INTEGER,
         cat: STRING_ARRAY,
         dealid: STRING,
         w: INTEGER,
         h: INTEGER,
         dur: INTEGER,
         mtype: INTEGER,
         ext: {  },                  // for future extension
     }]
}]
}

Thanks @SyntaxNode - thumbs up from me.