Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: previous auction info module #3333

Open
bretg opened this issue Dec 4, 2023 · 4 comments
Open

Proposal: previous auction info module #3333

bretg opened this issue Dec 4, 2023 · 4 comments

Comments

@bretg
Copy link
Contributor

bretg commented Dec 4, 2023

Over the years, the Prebid Server team has gotten requests to support "loss notifications" so bidders can refine their bidding algorithms. Whenever the request comes up, we decline with 3 objections:

  • Prebid Server does not define the winner or loser of an auction and is not in the notification path. The ad server could choose a non-Prebid bid to win, there could be bid caching, there could be client-side price adjustments, etc. Bottom line is that Prebid cannot commit to knowing the "min bid to win".
  • Hosting Prebid Server is expensive already - we do not want to support a 'real-time' notification because that adds to outbound network traffic.
  • Putting some kind of info in a subsequent auction request would be ok, but the IAB has not seen fit to define a location to put it, and Prebid does not want to be in the business of defining OpenRTB extensions used as important conventions by other parties.

But the issue comes up again periodically, so in the spirit of trying to move the conversation forward, here's an option for Prebid Server to offer a relatively inexpensive way to provide the info that is available. Bidders need to be willing to (A) read from a Prebid extension, (B) accept incomplete info and (C) be flexible about the timing of getting the data.

  1. Define a prebid-specific "previous auction info" object on bid requests for which the bidder had actually successfully bid above the floor. The idea is that we need to avoid sending info to bidders are weren't serious about actually bidding.
$.ext.prebid.previousauctioninfo: ]{
source: "pbs",
auctionId: STRING, // $.id of the previous auction
impid: STRING,       // $.imp[].id of the previous auction
bidresponseid: STRING, // seatbid[].bid[].id of the previous auction
targetedbidcpm: FLOAT,          // the bid targeted as the 'winner' within PBS targeting. Not specified if includewinners flag not present
highestcpm: FLOAT,        // the highest bid seen by Prebid in the publisher's requested currency
cur: STRING,
biddercpm: FLOAT,    // the price submitted by this bidder
biddererrorcode: INTEGER,  // if the bidder's bid was rejected, let them know the seatnonbid code
timestamp: INTEGER
}]

In the future PBS could also forward PBJS previous auction info in a separate object. (?)

$.ext.prebid.previousauctioninfo: ]{
source: "pbjs",
auctionId: STRING, // $.id of the previous auction
impid: STRING,       // $.imp[].id of the previous auction
bidresponseid: STRING, // seatbid[].bid[].id of the previous auction
targetedbidcpm: FLOAT,          // the bid targeted as the 'winner' within PBS targeting. Not specified if includewinners flag not present
highestcpm: FLOAT,        // the highest bid seen by Prebid in the publisher's requested currency
cur: STRING,
biddercpm: FLOAT,    // the price submitted by this bidder
biddererrorcode: INTEGER,  // if the bidder's bid was rejected, let them know the seatnonbid code
timestamp: INTEGER
}]
  1. Create a module that caches auction results and forwards them on the next auction

Runs at 2 stages:

  • All Processed Bid Response Stage: if a bidder provides an actual bid, append them to a data structure:

However this is efficiently implemented in the code, logically, it's just a queue for each bidder:

{
   "bidderA": [{
      auctionId: "1111",
      impid: "medrect",
      bidresponseid: "2222",
      highestcpm: 1.00,
      cur: "USD",
      biddererrorcode: -1        // no error
   },{
      auctionId: "1111"
      impid: "top-banner",
      bidresponseid: "3333"
      highestcpm: 1.25,
      cur: "USD",
      biddererrorcode: 301    // did not meet floor
   }],
   "bidderB" : [{
      ...
    }]
}

NoBids (seatnonbid code 0) are not added to the data structure.

  • Bidder Request Stage: when a request is about to go out to a bidder, pull all previous auction info blocks off the bidder's queue and add them to the ORTB request.

That's it. Configuration of the module would define which bidders to do this for and max queue length.

To minimize mutex contention, I would propose very loose timing requirements. It would be ok for every thread to have it's own copy of the bidresponse queue, or for there to be a configurable number of queues per server that are processed round-robin. The implication is that there's absolutely no guaranteed about when the bidder would receive the additional information. e.g if there are 1000 threads in a large server and traffic is declining, the previous auction info in thread 999 might get stuck there until traffic rises the next day.

  1. Make sure there's a configurable max size

We'll need an approach to removing older auction info that hasn't yet gotten reported.


Discuss.

@bretg
Copy link
Contributor Author

bretg commented May 8, 2024

Discussed in committee. This is still of some interest, but not a high priority. This addresses only a "min bid to win" use case, not a "pacing improvement" use case.

@bretg
Copy link
Contributor Author

bretg commented May 8, 2024

Discussed in committee: keeping this on hold until there's enough interest to push it further.

@bretg
Copy link
Contributor Author

bretg commented Jul 26, 2024

There's a Prebid.js pull request open around this general topic -- prebid/Prebid.js#11086. So apparently there's some interest out there. I believe from pubmatic. The pull request isn't aligned with the proposal here.

@bretg
Copy link
Contributor Author

bretg commented Dec 6, 2024

Update: there's been work on on this done for Prebid.js in prebid/Prebid.js#11086

I've requested that the community take this up and debate the details.

              bidderRequestId: bidderRequest.bidderRequestId,          // not sure what this ID is.
              minBidToWin: highestCpmBid?.cpm || 0,                            // replaces highestcpm?
              rendered: 0,                                                                           // new
              transactionId: bid.ortb2Imp.ext.tid || bid.transactionId,    // only when transmitTid allowed
              source: 'pbjs',
              auctionId: auctionDetails.auctionId,                                   // only when transmitTid allowed
              impId: bid.adUnitCode,
              bidResponseId: FLOAT, // don't think this is available client side?
              targetedbidcpm: FLOAT, // don't think this is available client side?
              highestcpm: highestCpmBid?.cpm || 0,
              cur: bid.ortb2.cur,
              bidderCpm: receivedBidsMap[bid.bidId] ? receivedBidsMap[bid.bidId].cpm : 'nobid',
              biddererrorcode: rejectedBidsMap[bid.bidId] ? rejectedBidsMap[bid.bidId].rejectionReason : -1,
              timestamp: auctionDetails.timestamp,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Research
Development

No branches or pull requests

1 participant