From 4809bcb339f9011925abc3284c00270b2bdffc13 Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Tue, 19 Nov 2024 13:43:34 -0800 Subject: [PATCH 1/2] paapi: support for parallel PAAPI and contextual auctions --- dev-docs/modules/paapi.md | 97 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/dev-docs/modules/paapi.md b/dev-docs/modules/paapi.md index 71df078690..20195f49bd 100644 --- a/dev-docs/modules/paapi.md +++ b/dev-docs/modules/paapi.md @@ -44,6 +44,7 @@ This module exposes the following settings: |bidders | Array[String] |Optional list of bidders |Defaults to all bidders | |defaultForSlots | Number |Default value for `imp.ext.ae` in requests for specified bidders |Should be 1 | |componentSeller | Object |Configuration for publishers acting as component sellers | See [note](#componentSeller) | +|parallel | Boolean | If true, start PAAPI auctions in parallel with Prebid auctions when possible | See [parallel auctions](#parallel) | As noted above, PAAPI support is disabled by default. To enable it, set the `enabled` value to `true` for this module and configure `defaultForSlots` to be `1` (meaning _Client-side auction_). using the `setConfig` method of Prebid.js: @@ -132,9 +133,11 @@ Modifying a bid adapter to support PAAPI is a straightforward process and consis 1. Detecting when a bid request is PAAPI eligible 2. Responding with AuctionConfig or InterestGroupBuyer in addition to (or instead of) bids +3. (Optional, but recommended) implementing a `buildPAAPIConfigs` method to support [parallel auctions](#parallel) ### Input parameters + When PAAPI is configured, the following fields are made available to adapters' [`buildRequests`](/dev-docs/bidder-adaptor.html#building-the-request): {: .table .table-bordered .table-striped } @@ -163,6 +166,7 @@ function interpretResponse(resp, req) { } ``` + `paapi` must be an array of objects containing: {: .table .table-bordered .table-striped } @@ -176,6 +180,99 @@ Each object must specify exactly one of `igb` or `config`. An example of this can be seen in the OpenX bid adapter [here](https://github.com/prebid/Prebid.js/blob/master/modules/openxBidAdapter.js) or RTB House bid adapter [here](https://github.com/prebid/Prebid.js/blob/master/modules/rtbhouseBidAdapter.js). + +## Parallel auctions + +PAAPI auctions can be started in parallel with Prebid auctions for a significant improvement in end-to-end latency, +as long as the adapters involved provide at least part of the auction config(s) in advance, before any request is sent to their backend. + +To support parallel execution, adapters can provide a `buildPAAPIConfigs` method, taking [the same arguments as buildRequests](#paapi-input) and returning an array of PAAPI configuration objects in [the same format as `interpretResponse`'s `paapi` parameter](#paapi-output). + +```javascript +registerBidder({ + // ... + buildPAAPIConfigs(validBidRequests, bidderRequest) { + // should return an array of {bidId, config, igb} + } +}) +``` + +When provided, `buildPAAPIConfigs` is invoked just before `buildRequests`, and the configuration it returns is eligible to be immediately used to start PAAPI auctions (whether it will depends on the `parallel` config flag and the top level seller's support for it). +When /not/ provided, the adapter cannot participate in parallel auctions, and PAAPI configuration returned by `interpretResponse` are liable to be discarded when parallel auctions are enabled. For this reason we recommend implementing `buildPAAPIConfigs`. + +[Some signals](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#211-providing-signals-asynchronously) can be provided asynchronously; Prebid supports this by merging them from the return value of `interpretResponse`, using `bidId` as key. +Notably, however, at least `seller`, `interestGroupBuyers`, and `decisionLogicUrl` must be provided synchronously (i.e., they must be hard-coded). + +For example: + +```javascript +// suppose that `buildPAAPIConfigs` returns the following: +([ + { + bidId: 'bid1', + config: { + seller: 'example.seller', + decisionLogicUrl: 'example.seller/logic.js', + interestGroupBuyers: ['example.buyer'], + auctionSignals: { + foo: 'bar' + }, + perBuyerTimeouts: { + 'example.buyer': 200 + } + } + }, +]) + +// and `interpretResponse` returns: +({ + paapi: [ + { + bidId: 'bid1', // matches the bidId from `buildPAAPIConfigs` + config: { + perBuyerCurrencies: { // will be ignored; `perBuyerCurrencies` must be synchronous + 'example.buyer': 'USD' + }, + // `auctionSignals` and `sellerSignals` can be provided asynchronously + // and will be merged with those returned by `buildPAAPIConfigs` + auctionSignals: { + bar: 'baz' + }, + sellerSignals: { + foo: 'bar' + } + } + }, + { + bidId: 'bid2', // does not match. + // `config` will be used as-is, but only if no auction was already started in parallel for this slot; + // it will be discarded otherwise. + config: { + /* ... */ + } + } + ] +}) + +// the result as seen in the sandboxed auction for `bid1` will then be: + +({ + seller: 'example.seller', + decisionLogicUrl: 'example.seller/logic.js', + interestGroupBuyers: ['example.buyer'], + auctionSignals: { + foo: 'bar', + bar: 'baz' + }, + perBuyerTimeouts: { + 'example.buyer': 200 + }, + sellerSignals: { + foo: 'bar' + } +}) +``` + ## Related Reading - [paapiForGpt module](/dev-docs/modules/paapiForGpt.html) From a54264b3b88c5d8443a6bddd1c52439e071ffa5c Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Wed, 20 Nov 2024 07:35:54 -0800 Subject: [PATCH 2/2] Formatting --- dev-docs/modules/paapi.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/dev-docs/modules/paapi.md b/dev-docs/modules/paapi.md index 20195f49bd..ce29749fdb 100644 --- a/dev-docs/modules/paapi.md +++ b/dev-docs/modules/paapi.md @@ -186,7 +186,7 @@ An example of this can be seen in the OpenX bid adapter [here](https://github.co PAAPI auctions can be started in parallel with Prebid auctions for a significant improvement in end-to-end latency, as long as the adapters involved provide at least part of the auction config(s) in advance, before any request is sent to their backend. -To support parallel execution, adapters can provide a `buildPAAPIConfigs` method, taking [the same arguments as buildRequests](#paapi-input) and returning an array of PAAPI configuration objects in [the same format as `interpretResponse`'s `paapi` parameter](#paapi-output). +To support parallel execution, adapters can provide a `buildPAAPIConfigs` method, taking [the same arguments as buildRequests](#paapi-input) and returning an array of PAAPI configuration objects in the same format as `interpretResponse`'s [`paapi` parameter](#paapi-output). ```javascript registerBidder({ @@ -198,7 +198,8 @@ registerBidder({ ``` When provided, `buildPAAPIConfigs` is invoked just before `buildRequests`, and the configuration it returns is eligible to be immediately used to start PAAPI auctions (whether it will depends on the `parallel` config flag and the top level seller's support for it). -When /not/ provided, the adapter cannot participate in parallel auctions, and PAAPI configuration returned by `interpretResponse` are liable to be discarded when parallel auctions are enabled. For this reason we recommend implementing `buildPAAPIConfigs`. + +When _not_ provided, the adapter cannot participate in parallel auctions, and PAAPI configuration returned by `interpretResponse` are liable to be discarded when parallel auctions are enabled. For this reason we recommend implementing `buildPAAPIConfigs`. [Some signals](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#211-providing-signals-asynchronously) can be provided asynchronously; Prebid supports this by merging them from the return value of `interpretResponse`, using `bidId` as key. Notably, however, at least `seller`, `interestGroupBuyers`, and `decisionLogicUrl` must be provided synchronously (i.e., they must be hard-coded). @@ -224,13 +225,15 @@ For example: }, ]) -// and `interpretResponse` returns: +// and `interpretResponse` later returns: ({ paapi: [ { bidId: 'bid1', // matches the bidId from `buildPAAPIConfigs` config: { - perBuyerCurrencies: { // will be ignored; `perBuyerCurrencies` must be synchronous + // `perBuyerCurrencies` must be provided synchronously; + // this will be ignored + perBuyerCurrencies: { 'example.buyer': 'USD' }, // `auctionSignals` and `sellerSignals` can be provided asynchronously @@ -245,8 +248,8 @@ For example: }, { bidId: 'bid2', // does not match. - // `config` will be used as-is, but only if no auction was already started in parallel for this slot; - // it will be discarded otherwise. + // `config` will be used as-is, but only if no auction was already + // started in parallel for this slot; it will be discarded otherwise. config: { /* ... */ }