WICG / turtledove

TURTLEDOVE
https://wicg.github.io/turtledove/
Other
521 stars 222 forks source link

Is it possible to run PAA (Protected Audience API) auction in parallel to Header Bidding and publisher’s adserver call? #851

Open wojciech-bialy-wpm opened 11 months ago

wojciech-bialy-wpm commented 11 months ago

We have tried to test an approach in which PAA auction is initiated by the publisher - using modified fledgeForGPT prebid module and componentAuctions received from RTB House bidder.

Our test setup - with standalone PAA auction - can be described as follows:

PAA auction activated by the publisher

For more detailed information about our experiment, please see: https://github.com/grupawp/PAapi

Experiment conclusions:

Our experiment shows that this integration option may result in a significant revenue drop for the publisher.

The revenue drop reasons are:

  1. PAA auction always extends the time needed to receive and render the ad. Our statistics show that:

    • median duration time of empty PAA auctions is 52ms (161ms for the 80th percentile)

    • median duration time of PAA auctions that return URN / fenced frame config is 733ms (1773ms for the 80th percentile)

Additional significant delay caused by a PAA auction (especially for non-zero results) decreases adslot viewability – reducing ad slot value and negatively impacting user experience – affecting user retention and overall business success. Please see: https://web.dev/fast-ads-matter/ for more information about the impact of ad latency on publisher’s revenue.

  1. Since neither PAA, nor Google Ad Manager returns comparable ad value, the publisher cannot select best (highest valued) ad between those two demand sources. Publisher is forced to select an ad randomly or always prefer one of those sources over the other. This results in a significant publisher’s revenue drop.

Solution:

Running PAA auction in parallel to Header Bidding and publisher’s adserver would be possible if PAA auction would return comparable ad value (with precision preserving k-anonymity). Parallel architecture would minimize PAA impact on ad latency and would not force the publisher to choose demand sources randomly.

thegreatfatzby commented 11 months ago

I believe the parallelization could be achieved if the final ranking didn't have to occur inside the private auction. One thing we've talked about internally is having a final opaque function that could run in the browser, that takes opaque winner but also other winners, and then turn out the final winner. We could add additional opaque callbacks to minimize the bit leaks, so something like "onPrivateWin" that handles FF rendering, "onOtherWin", etc.

thegreatfatzby commented 11 months ago

Couldn't you actually just re-run the scoreAd process, just with only the winner from the Private Auction, and then winner from the other auction?

dmdabbs commented 11 months ago

Chrome is working on improving IG retrieval latency, but that's not going to be a silver bullet.

michaelkleber commented 11 months ago

Hello @wojciech-bialy-wpm,

We would not recommend the approach of randomly selecting between two different auctions. We designed the Protected Audience API so that information from multiple sources could flow into the PA auction and decision process. If the best ad is not one that comes from inside the PA auction, then the PA auction should return no ad at all, and the caller should instead render the best non-PA ad they know about. This logic is the job of the script in the seller's decisionLogicURL.

The bidding inside the PA auction generally depends on contextual signals that are returned by other servers (for both Header Bidding and GAM). That means it's impossible for the PA auction to finish before those signals are available. We have indeed built ways that the PA auction can be started in parallel, though: see Section 2.1.1 Providing Signals Asynchronously for details on this feature.

Regarding latency, the seller who initiates the auction is again the party in control of what resources it is allowed to consume. Please look at the auction config options perBuyerTimeouts, perBuyerCumulativeTimeouts, and perBuyerGroupLimits (perhaps along with perBuyerPrioritySignals, if buyers use the priorityVector feature) for ways that the seller can control the time allocated to each buyer during the auction.

wojciech-bialy-wpm commented 11 months ago

Hello @thegreatfatzby,

Regarding final ranking / function, we thought about a structure like that. A service, that would take winning bids/ads from different channels (including the PAA), compare them and then send win/loss signal to buyers, and winning ad to the seller. There are ways to make it secure, such as running in safe environment (a browser worklet?), or allowing only limited amount of comparisons (to prevent information leakage via multiple win/loss tests).

As for - re-running scoreAd, how would it be possible? Would it be a solution where PAA and non-PAA channels are running in parallel, PAA bids are generated and scored (based on ad metadata, trusted scoring signals etc.) and finally, the winning non-PAA ad value is used to re-score (apply floor price) the PAA auction result?

wojciech-bialy-wpm commented 11 months ago

Hello @michaelkleber,

I wholeheartedly agree that the publisher should never have to select ads randomly. In our setup, this is due to the fact that two channels do not return ad value. In our test environment we have:

If we'd run all the following in parallel, then we'd potentially end with two results that cannot be compared with each other.

Regarding using promises in PAA auction config, do I understand correctly that we can:

I'll add it to the test, and we'll see how much of auction duration is taken by buyer / seller workflows.

wojciech-bialy-wpm commented 10 months ago

Hello @michaelkleber,

We have ran tests, where PAA auction initiation and buy-side logic is executed in parallel with header bidding and adserver calls. PAA sell-side logic is blocked by sellerSignals promise, that is resolved when adslot is executed and winning bid / ad (from header bidding and adserver, respectively) are known.

This setup can be described as follows:

async PAA example

From what we've seen, the auction duration (a median of ~730ms) is split into:

Since in our setup header bidding timeout is 800ms, only sell side impacts ad rendering time - meaning that delay incurred by PAA auction is reduced by ~95% (from 740ms to 40ms).

However, this will only work as long as we can control when PAA auction starts (and start it concurrently with other demand channels). As seen in Privacy Sandbox Progress Report for Q3 (https://assets.publishing.service.gov.uk/media/653a491d80884d000df71b70/Google_s_Q3_2023_report_.pdf), Google Ad Manager intents to maintain control over top-level PAA auction, and execute it (plus all component Auction) only after receiving response from the adserver.

This unfortunately means that such optimization is not achievable in any ad stack that includes the Google Ad Manager, and without it the publisher cannot monetize the demand that is unique to Google.

michaelkleber commented 10 months ago

Thank you for reporting back! It sounds like our past parallelization work is a great success when it gets used. I agree that the essential question now is how GAM can also start feeding into the parallelization mechanism as well.