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

Additional options for PA Deal Support #873

Open
rdgordon-index opened this issue Oct 22, 2023 · 32 comments
Open

Additional options for PA Deal Support #873

rdgordon-index opened this issue Oct 22, 2023 · 32 comments

Comments

@rdgordon-index
Copy link
Contributor

rdgordon-index commented Oct 22, 2023

Deals (private marketplace) have been the focus of a number of issues -- #716, #682 #686 -- and I'd like to suggest some options for consideration.

buyerAndSellerReportingId and buyerReportingId are interest group attributes -- however, there's no a priori correlation between a dealID and a particular renderURL (aka creative) -- that is, in principle, a given dealID could accompany any creative for a given buyer. Furthermore, new deals can be created after a browser joins an IG, and having to update each IG with each potential dealID seems cumbersome.

Furthermore, as noted elsewhere, both scoreAd() and reportResult() need to receive the dealID (not to mention reportWin()) -- this signal must exfiltrate the device -- as it's fundamental both to revenue share calculations as well as reporting attribution.

The list of dealIDs for any given slot is also highly dynamic -- and each DSP will receive a different subset of those dealIDs for any given slot. Assuming we're talking about contextual-based deal activation (not publisher audience extension, which has been discussed elsewhere), in principle, an SSP would be able to return perBuyerSignals with a per-DSP list of potential dealIDs. Making this available to on-device bidding could follow existing API surfaces -- the challenge is how to get it 'back out' in a privacy-centric fashion.

Perhaps there's an opportunity to consider the notion of dealIDs handled like interest groups -- i.e. a "deal group" -- where the browser maintains such a list for k-anon purposes -- tied to a seller origin. Once thusly registered with the browser (i.e. via a joinDealGroup() call), the seller can return a list of dealIDs via the contextual response, linked to their buyer origins. In this model, existing IGs could be upgraded to include 'deal intent' -- a boolean indicating if a given IG ever intends to bid with a dealID -- and thus the brower would be able to deal with k-anon determination well before auction time, and for an defined set of (IG, renderURL, dealID) tuples. Once k-anon has been satisifed, exposing this to PAAPI functions shouldn't be a privacy concern anymore.

There's another potential alternative -- leveraging https://github.com/WICG/turtledove/blob/main/FLEDGE.md#6-additional-bids (#319) in order to be able to derive the creativeURL for a dealID via the contextual response. In this model, there would be some OpenRTB-powered mechanism to signal that dealID response would only be used for a PA auction (like in the additional bids workflow); but this, too, would allow for the dealID to be made visible to the PAAPI functions.

@leeronisrael
Copy link

Hi Roni,

We have received a significant amount of feedback that Deals are an important use case for the industry today. According to IAB TL: Deals, also referred to as Private Marketplace (PMP) offer curated or exclusive access, or preferred pricing for buyers on a subset of inventory. Also, referred to as “programmatic deals,” agreements for PMPs can be organized between publishers or SSPs and DSPs, agencies or advertisers. A notable, related use case is Publisher Audience Extension (issue #144). In this use case, sellers curate audience information for buyers, in some cases using Deals to package that information across sites. This latter area is currently under exploration by Chrome, but not addressed within this design.

We understand there are several components to Deals. Two of the most essential are the concept of a seat ID and deal ID. They are defined as:

  • A seat ID is an identifier that represents a buyer’s customer (typically an advertiser or agency). A seat ID may have billing implications, for example, if a given seat has a discount with a given seller.
  • A deal ID is an identifier that represents an agreement between a buyer (e.g., advertiser, agency) and seller (e.g., publisher). A deal ID may have many properties, such as a cost/price, volume commitment, audience information, exclusivity, and more
  • A seat ID may also interact with a deal ID, for example, if a deal ID is limited to a set of seat IDs for a specific buyer

Based on the feedback so far, we have identified some requirements:

  • The seat ID originates with buyers
  • The deal ID may originate with either the buyer or seller. The eligible deals are typically the intersection of the deals pre-registered by buyers in interest groups and deals sent by sellers in the contextual bid request
  • Both IDs need to be available for auction processing (i.e, generateBid and scoreAd)
  • Both ID need to be reliably available via the relevant reporting mechanisms (i.e., reportWin and reportResult)

Our proposed solution is to make some modifications to an existing field, buyerAndSellerReportingId, to accommodate the use case:

  1. Chrome modifies buyerAndSellerReporting ID to accept a string or an array. This field is located in each ads object within an interest group
    • Each element in the array is a string. For example, each string in the array may represent both a seat and deal ID
  2. generateBid selects a value from buyerAndSellerReportingId. The buyerAndSellerReportingId array is made accessible to generateBid. In generateBid, the buyer identifies the specific ID from the buyerAndSellerReportingId array that should be reported on.
    • This can be used to represent the seat ID, deal ID, or both, for the generated bid
  3. The selected value from generateBid is made accessible as an argument to scoreAd. The seller can consider the deal when selecting the winning bid.
  4. Chrome recognizes a new, optional field in the output of generateBid that buyers can use to require the buyerAndSellerReportingId to appear in the relevant reporting functions
    • This is in contrast with the current behavior, where the ID may be dropped by the browser if the ad and the ID do not jointly meet the k-anonymity threshold. With the proposed new flag, if the combination of render URL and buyerAndSellerReportingId does not meet the k-anon threshold, then the bid will be withdrawn. This is designed to ensure reliable reporting (i.e., only win the auction if the ID will pass k-anon and be reported on)

The end to end flow may look like the following:

  1. Before the auction
    1. The buyer pre-registers seat and deal IDs in the buyerAndSellerReportingId field in interest groups either when creating or updating the interest group
  2. At contextual auction time
    2. The seller sends deal IDs in the contextual bid request
    3. The buyer identifies the relevant deal IDs in the perBuyerSignal field of the contextual bid response
  3. At PA auction time
    4. The seller forwards this list of buyer-identified deal IDs into the auction via perBuyerSignals
    5. In generateBid, the buyer decides if they want to bid on a deal ID. If so, the buyer specifies an ad and a deal ID from the ad's buyerAndSellerReportingId array, indicating the bid was generated for that deal ID.
    6. The buyer optionally indicates if the selected buyerAndSellerReportingId is required to appear in the relevant reporting function.
    7. The selected deal ID is made accessible to scoreAd. The seller picks the winning bid, considering the deal ID and any special terms. (If the seller does not think the buyer-chosen deal ID applies, then the seller rejects the bid, by giving it a negative desirability in scoreAd).
  4. At PA reporting time
    8. Depending on step 3.6 and if the render URL and buyerAndSellerReportingId meet the k-anon threshold, then the deal ID is reported on in reportResult and reportWin

There are a few design plans to highlight:

  • K-anon incrementing behavior
    • We propose to use the same k-anon incrementing behavior in place for IG ads today:
      • In order for an ad associated with a given deal ID to be shown to users, it must exceed the threshold of 50 users over 30 days
      • The counter is incremented each time that the Render URL + string from buyerAndSellerReportingId would have won the auction, but was withdrawn by the browser due to not exceeding the k-anon threshold
  • Incorrect identification of ID in buyerAndSellerReportingId array
    • If generateBid identifies an ID that does not exist in the buyerAndSellerReportingId array (step 3.5 in the list above), then the browser will withdraw the bid entirely

We welcome feedback on this proposal!

@rdgordon-index
Copy link
Contributor Author

rdgordon-index commented Mar 22, 2024

Thanks @leeronisrael for the detailed proposal. I'll highlight a few challenges:

The buyer pre-registers seat and deal IDs in the buyerAndSellerReportingId field in interest groups either when creating or updating the interest group

This requires a given IG to include all the seats and all the dealIDs -- and implies that the buyer is necessarily aware of these when creating or update the IG.

The seat is associated with the advertiser and campaign, outside of the bidding process -- and generally doesn't vary per seller -- so that seems feasible; furthermore, since this bid is associated with a single seat on a given buyer, the k-anon shouldn't be impacted.

However, on the deals side, this seems problematic -- this would require somehow bringing awareness of the dealIDs to the IG creation/update process -- rather this merely being an attribute of the bidding logic JS/WASM and TBS fetched from the buyer's KV.

This can be used to represent the seat ID, deal ID, or both, for the generated bid

How would a seller know what this would represent, consistently, across buyers, in order to make sense of this value? I would prefer that we didn't combine seat and dealID into a single attribute. Furthermore, from a k-anon perspective, this would explode the cardinality -- every dealID x every seat -- which would greatly diminish the ability of these deal bids to render and win impressions.

Furthermore, as highlighted in #792, there are other reasons why seller need to know the seat for a given renderURL -- so parsing it conditionally out of this field seems brittle at best given the above.

  1. The buyer identifies the relevant deal IDs in the perBuyerSignal field of the contextual bid response

Can you elaborate further? (4) below suggests the seller should be forwarding the list, but this point seems to suggest a role for the buyer? Conceptually, the buyer might not even know in advance what dealIDs are relevant outside of the on-device auction. Of course, the buyers are welcome to pass any signals they want in buyerdata -- but I'm not sure I understand this requirement for the proposal to work.

  1. The seller forwards this list of buyer-identified deal IDs into the auction via perBuyerSignals

The sequential auction setup results in preBuyerSignals being a pass-through mechanism for the buyer to pass their buyerdata associated with their origin directly to the auctionConfig via the igbid extension. This would require all buyers and sellers to have an agreed-upon data structure to include the dealID array in a pre-determined location within buyerdata -- which, today, is just 'JSON-serializable', and not manipulated by the seller -- for use this when building the contextual response (seller) and extracting this key/array from perBuyerSignals parameter in generateBid (buyer).

In order for an ad associated with a given deal ID to be shown to users, it must exceed the threshold of 50 users over 30 days
if the render URL and buyerAndSellerReportingId meet the k-anon threshold

Unlike seat, there's no a priori relationship between a renderURL and a dealID -- so this will have a significant impact, since each combination would need to meet k-anon, rather than the renderURL and the dealID independently.

  1. The buyer optionally indicates if the selected buyerAndSellerReportingId is required to appear in the relevant reporting function.
  2. Depending on step 3.6 and if the render URL and buyerAndSellerReportingId meet the k-anon threshold, then the deal ID is reported on in reportResult and reportWin

Would the seller be aware of this decision when the bid is received in scoreAd? In other words, how can a seller know if the dealID will be available in reportResult before scoring the bid with a non-negative desirability score? If the dealID affect the scoring logic in any way, this would be a requirement for the seller's reporting function.

@bretg
Copy link

bretg commented Apr 23, 2024

It's been a month -- has there been progress outside of this issue on including seatId as a parameter that can be sent to the seller's reportResults()?

@zhuoli-fledge
Copy link

zhuoli-fledge commented Apr 30, 2024

  1. Chrome modifies buyerAndSellerReporting ID to accept a string or an array. This field is located in each ads object within an interest group

    • Each element in the array is a string. For example, each string in the array may represent both a seat and deal ID
  2. generateBid selects a value from buyerAndSellerReportingId. The buyerAndSellerReportingId array is made accessible to generateBid. In generateBid, the buyer identifies the specific ID from the buyerAndSellerReportingId array that should be reported on.

    • This can be used to represent the seat ID, deal ID, or both, for the generated bid

In case of multi bid, multiple values should be selected from buyerAndSellerReportingId.

  1. The selected value from generateBid is made accessible as an argument to scoreAd. The seller can consider the deal when selecting the winning bid.

adMetadata can be one option, but requires sync with ssp to understand the exact fields.

  1. Chrome recognizes a new, optional field in the output of generateBid that buyers can use to require the buyerAndSellerReportingId to appear in the relevant reporting functions

This likely needs to be an array to adapt multibid's use case, which serves like an allowlist. A deal id can be reported only if it shows up in this array.

@pm-harshad-mane
Copy link

sequenceDiagram
    participant Buyer
    participant Seller

    Note over Buyer,Seller: Before the auction
    Buyer->>+Seller: Pre-register seat & deal IDs in buyerAndSellerReportingId

    Note over Buyer,Seller: At contextual auction time
    Seller->>Buyer: Send deal IDs in contextual bid request
    Buyer->>Seller: Identify deal IDs in perBuyerSignal of bid response

    Note over Buyer,Seller: At PA auction time
    Seller->>Seller: Forward list of deal IDs via perBuyerSignals
    Buyer->>Buyer: Decide to bid on deal ID and specify ad and deal ID
    Buyer->>Seller: Optionally indicate buyerAndSellerReportingId requirement in reporting
    Buyer->>Seller: Selected deal ID accessible to scoreAd
    Seller->>Buyer: Pick winning bid or reject bid

    Note over Buyer,Seller: At PA reporting time
    Seller->>Buyer: If k-anon threshold met, report deal ID in reportResult and reportWin
Loading

@pm-harshad-mane
Copy link

pm-harshad-mane commented May 23, 2024

"buyerAndSellerReportingId" is a generic name , if we want to use this field only for deal-id then we can rename this field or create a new field with appropriate name and dedicated purpose. Otherwise it will be difficult to know at execution time whether this field is used for deal or some other purpose.

"The deal ID may originate with either the buyer or seller."
Is proposal only handling the seller originated deal IDs?

As per the nature of the deals, PA core logic can make it mandatory for buyers to pass seatId to make the deal work.

@rsachdev9191
Copy link

At a high level, Magnite is aligned with Google on this proposal for the basic deal use case (based on contextual targeting) but there a few caveats to this approach:

  • The proposal does not work for deals targeting component seller owned audiences
  • The proposal in contingent on generatebid being able to return multiple bids
  • It's unclear if the interaction of buyerAndSellerReportingId and buyerReportingId could have a negative impact
  • When doing it at scale, it's unclear if it impacts the k-anon requirement (more from a DSP's perspective)
  • Unclear about the impact it has on the ig size in the browser
  • General latency concerns when evaluating multiple bids in the browser for both generatebid and scoread

@leeronisrael
Copy link

Thanks @rsachdev9191 ! See our responses in-line below:

The proposal does not work for deals targeting component seller owned audiences

Yes, we acknowledge that use case is a priority, but it is out of scope for this solution.

The proposal in contingent on generatebid being able to return multiple bids

The ability for generateBid to return multiple bids has landed in Chrome 125 at 1% of traffic.

It's unclear if the interaction of buyerAndSellerReportingId and buyerReportingId could have a negative impact

We are aware that some buyers may have concurring use cases that require buyerAndSellerReportingId and buyerReportingId. Currently, the default behavior is that the former will overwrite the latter. We propose to make it possible to report on both fields, subject to a joint k-anon check. In other words, buyerAndSellerReportingId + buyerReportingId + renderURL will need to be jointly k-anonymous in order for all values to be reported on.

When doing it at scale, it's unclear if it impacts the k-anon requirement (more from a DSP's perspective)

We have received some directional feedback that k-anon will not have a material negative impact on the proposed solution's ability to support the use case. We welcome additional analysis from other DSPs on this.

Unclear about the impact it has on the ig size in the browser

We do expect this will increase the size of IGs in the browser. There is an overall size limit for all IGs. There is potential future opportunity to optimize IG size, but we do not see it as a blocker for this solution.

General latency concerns when evaluating multiple bids in the browser for both generatebid and scoread

We agree with this concern, but it is not specific to the Deals use case. That is, latency concerns may exist with multiple bids regardless of whether or not we move forward with this solution. Therefore, we do not intend to block this solution on this potential issue.

Some in the industry have expressed another concern we’d like to highlight:

There may be other use cases that utilize BuyerAndSellerReportingId, such as Seat ID.

We believe the best solution is for the industry to align on a standardized string format that can be represented in the buyerAndSellerReportingId array, and supports the various use cases. For example, this may look something like, “{d:123,s:456,o:789}”, where “d” represents deal IDs, “s” represents seat IDs and “o” represents some other ID.

@zhuoli-fledge
Copy link

@leeronisrael Would it be possible to also have sellerReportingId that fits the seller's use case. Take deals as an example, seat id is something that seller wants to know but not buyer. By moving seat id to sellerReportingId can help decrease the IG size for buyers.

The k-anon requirement would be buyerAndSellerReportingId + buyerReportingId + sellerReportingId + renderURL

@rdgordon-index
Copy link
Contributor Author

We believe the best solution is for the industry to align on a standardized string format that can be represented in the buyerAndSellerReportingId array, and supports the various use cases. For example, this may look something like, “{d:123,s:456,o:789}”, where “d” represents deal IDs, “s” represents seat IDs and “o” represents some other ID.

question: is there any reason why this proposal can't include the introduction of new fields? Can you elaborate on why it's preferable and/or advantageous to re-purpose buyerAndSellerReportingId versus simply having a dedicated fields for seatID and dealID?

@michaelkleber
Copy link
Collaborator

In general, it's better for the browser to offer a pipe with the required privacy characteristics, and let the API user put what they want to put into the pipe. If we offer a pipe that is specific to one use case, then each time you figure out a new use case, you need to come back and ask the browser to build a new pipe for it.

I guess I would ask the opposite question: Why would you rather wait for us to add a field with a new name and new complexity, rather than reuse something we added a year ago? We could indeed add new fields if there were a functional reason to do so. Or we could change the name of an existing field if a different name turns out to be better — that's not discussing functionality, it's discussing spelling :-).

@rdgordon-index
Copy link
Contributor Author

Why would you rather wait for us to add a field with a new name and new complexity, rather than reuse something we added a year ago

Well, there are a myriad of other changes required here -- it's not simply a matter of 'adopting' an existing field and using it for contextual deal targeting -- so if we're changing other things, that affords us the opportunity to revisit.

In general, it's better for the browser to offer a pipe with the required privacy characteristics, and let the API user put what they want to put into the pipe

Aligned that if we have a general-purpose 'pipe', API users can make the most of it, the naming/spelling indeed at that point is secondary.

@JensenPaul
Copy link
Collaborator

Since Leeron published the proposal listed above in his March 13th comment, we’ve explored a lot of alternatives, spoke to a lot of interested parties, and received a lot of feedback. We’ve decided this proposal satisfies most of the need for supporting deals in Protected Audience so we’ve decided to move forward with implementing it.

Noting that the proposal reuses the previously defined buyerAndSellerReportingId field, we’re including a couple tweaks to make it more ergonomic and to prevent breaking pre-existing use of this field and the buyerReportingId field. These tweaks should not break the existing functionality in Leeron's proposal.

Tweak 1: allow use of buyerReportingId and buyerAndSellerReportingId at the same time

The goal of this tweak is to allow someone adopting buyerAndSellerReportingId to support deals, to continue using buyerReportingId for pre-existing usage. Previously using buyerAndSellerReportingId took precedence over using buyerReportingId so only one field could be used at a time. To allow use of both fields (e.g. buyerAndSellerReportingId for deals and buyerReportingId for some pre-existing purpose) at the same time: when buyerAndSellerReportingId is specified as an array and buyerReportingId is specified, both buyerAndSellerReportingId and buyerReportingId will be passed to reportWin(), if they are jointly k-anonymous with the interest group owner, bidding script URL, and render URL. Leeron mentioned this tweak two weeks ago in response to Magnite’s comment.

Tweak 2: add a sellerReportingId string field that can be used with the other two reporting IDs

The goal of this tweak is to allow someone adopting buyerAndSellerReportingId to support deals, to continue having a field available to specify a field reported to sellers without having to duplicate it in each buyerAndSellerReportingId array element. This can support pre-existing use of buyerAndSellerReportingId without bloating the size of their interest group unnecessarily. If the same seat ID is always presented for bids on an ad, the seat ID could be stored in the sellerReportingId. Specified more formally: when buyerAndSellerReportingId is specified as an array and the sellerReportingId string field is specified, both buyerAndSellerReportingId and sellerReportingId will be passed to reportResult(), if they are jointly k-anonymous with the interest group owner, bidding script URL, and render URL.

To avoid a combinatorial explosion on the number of k-anonymity checks the browser must perform, when buyerAndSellerReportingId is specified as an array, the browser will do one k-anonymity check for each element in the buyerAndSellerReportingId array along with the buyerReportId (when present) and sellerReportingId (when present) and the interest group owner, bidding script URL, and render URL. This allows generateBid() to select which buyerAndSellerReportingId to report because the browser has already checked the k-anonymity of each. buyerReportingId and sellerReportingId are always passed to reportWin() and reportResult() respectively, when they’re present in the interest group and jointly k-anonymous. If a buyer wants to report the buyerReportingId and the sellerReportingId without a buyerAndSellerReportingId (e.g. if they’re not bidding on a deal) then they should include an empty string in the buyerAndSellerReportingId array, and select the empty string buyerAndSellerReportingId at generateBid() time.

As Leeron’s proposal indicates, the buyer optionally indicates at generateBid() time, with a new field, if the selected buyerAndSellerReportingId is required to appear in the relevant reporting functions. This field will now apply to all three IDs: If all three are not jointly k-anonymous, and buyerAndSellerReportingId is marked optional, then the bid can still be submitted, but the sellerReportingId, buyerAndSellerReportingId, and buyerReportingId will not appear in the relevant reporting functions. If all three are not jointly k-anonymous, and the buyerAndSellerReportingId is marked required, then the bid will be withdrawn.

@rdgordon-index
Copy link
Contributor Author

rdgordon-index commented Jun 24, 2024

If the same seat ID is always presented for bids on an ad, the seat ID could be stored in the sellerReportingId. Specified more formally: when buyerAndSellerReportingId is specified as an array and the sellerReportingId string field is specified, both buyerAndSellerReportingId and sellerReportingId will be passed to reportResult()

If all three are not jointly k-anonymous, and buyerAndSellerReportingId is marked optional, then the bid can still be submitted, but the sellerReportingId, buyerAndSellerReportingId, and buyerReportingId will not appear in the relevant reporting functions.

I'm trying to better understand the implications of the above two statements.

First question: will the sellerReportingId field also be visible to scoreAd as well as reportResult? In Leeron's original proposal, the buyerAndSellerReportingId was noted to be available, but I wanted to make sure that this applies to this new field as well.

Second question: if sellerReportingId is meant to store the seat ID, and buyers adopt this convention across the board, that implies that sellers will need to ensure that it's always available -- how would this work if it's marked optional? Do you expect an empty string to signify 'no seat', much like an empty string to signal 'no deal', in the general case? In other words, how can a seller determine if we're being subject to k-anon fields being dropped, or if they're simply omitted?

We’ve decided this proposal satisfies most of the need for supporting deals in Protected Audience so we’ve decided to move forward with implementing it.

There have been a number of tweaks / changes along the way -- is there a document with the complete revised proposal that we can review to confirm that it does indeed support deals before we proceed?

@JensenPaul
Copy link
Collaborator

First question: will the sellerReportingId field also be visible to scoreAd as well as reportResult? In Leeron's original proposal, the buyerAndSellerReportingId was noted to be available, but I wanted to make sure that this applies to this new field as well.

Yes, sellerReportingId will be available to scoreAd() as well as reportResult().

Second question: if sellerReportingId is meant to store the seat ID, and buyers adopt this convention across the board, that implies that sellers will need to ensure that it's always available -- how would this work if it's marked optional?

If the same seat ID is always presented for bids on an ad, the seat ID could be stored in the sellerReportingId. How these fields are used is up to auction participants. If sellers want to ensure it’s always available, they can require such in scoreAd() and reject any bids without it. If bids always pair a particular sellerReportingId with a particular render URL, then the render URL should reach the k-anonymity bound at roughly the same time as the pair of the render URL and sellerReportingId does.

Do you expect an empty string to signify 'no seat', much like an empty string to signal 'no deal', in the general case?

This is up to how auction participants want to use the fields. Could a seat ID be ignored by the seller if a deal ID is not present in the bid?

In other words, how can a seller determine if we're being subject to k-anon fields being dropped, or if they're simply omitted?

As proposed, a seller cannot determine if it’s omitted or dropped. If a buyer marks the buyerAndSellerReportingId as required, then the seller wouldn’t see cases where the sellerReportId is dropped. How does the seller’s response to omitted versus dropped differ?

There have been a number of tweaks / changes along the way -- is there a document with the complete revised proposal that we can review to confirm that it does indeed support deals before we proceed?

There is not yet a document that combines Leeron’s proposal and my two tweaks.

@rdgordon-index
Copy link
Contributor Author

Yes, sellerReportingId will be available to scoreAd() as well as reportResult().

Great -- sellers will definitely need access to these identifiers both during scoring and reporting.

If sellers want to ensure it’s always available, they can require such in scoreAd() and reject any bids without it.

My question relates more to the k-anon implications, and what fields are supressed -- if the buyer marks buyerAndSellerReportingId as optional, does this also impact the other reportingID fields, depending on whether or not buyerAndSellerReportingId is an array? Based on your comment above, it appears so:

If a buyer marks the buyerAndSellerReportingId as required, then the seller wouldn’t see cases where the sellerReportId is dropped

Which suggests that using this new field might complicate using sellerReportingId as the seatID, if someone it might simply be ommited due to k-anon restrictions, in which case we'd still have to 'repeat' the seat.

This is up to how auction participants want to use the fields. Could a seat ID be ignored by the seller if a deal ID is not present in the bid?

Same line of reasoning as the previous comment -- yes, auction participants can decide how to use these fields, but only if they're always visible to said participants, which based on my reading of the tweaks, might not always be the case.

There are other reasons to have the seatID always visible, even outside deals, which is why I'm trying to ascertain if this field can have broader utility.

As proposed, a seller cannot determine if it’s omitted or dropped.
How does the seller’s response to omitted versus dropped differ?

This goes back to the question about where the seatID is signalled -- so, in this case, if we had a dealID absent a seatID, we wouldn't be able to properly handle this deal bid.

@rdgordon-index
Copy link
Contributor Author

rdgordon-index commented Jun 25, 2024

The challenging part here is the supression of the dealID from reportResult after it's been scored as a deal bid, due to k-anon -- and that's the difficultly -- can we discuss this further?

@zhuoli-fledge
Copy link

As Leeron’s proposal indicates, the buyer optionally indicates at generateBid() time, with a new field, if the selected buyerAndSellerReportingId is required to appear in the relevant reporting functions. This field will now apply to all three IDs: If all three are not jointly k-anonymous, and buyerAndSellerReportingId is marked optional, then the bid can still be submitted, but the sellerReportingId, buyerAndSellerReportingId, and buyerReportingId will not appear in the relevant reporting functions. If all three are not jointly k-anonymous, and the buyerAndSellerReportingId is marked required, then the bid will be withdrawn.

Does this new field only take effect when all three are not jointly k-anonymous? If buyerAndSellerReportingId is marked optional but all three are jointly k-anonymous, does Chrome still report them?

@JensenPaul
Copy link
Collaborator

I figured some examples would help illustrate the proposal.

Today’s behavior:

joinAdInterestGroup({...
  'ads': [{renderURL: Ad1URL, 
           buyerReportingId: ‘this goes to buyer only’,
           buyerAndSellerReportingId: ‘this goes to buyer and seller’,
  ...})

Only one of buyerAndSellerReportingId, buyerReportingId, or IG name gets reported when jointly k-anonymous with IG owner, biddingLogicURL, and renderURL.

With Leeron’s March 13th issue #873 proposal:

joinAdInterestGroup({...
  'ads': [{renderURL: Ad1URL, 
           buyerAndSellerReportingId: [ ‘this goes to buyer and seller’ ],
  ...})

When buyerAndSellerReportingId is an array, generateBid() picks an array element from buyerAndSellerReportingId, and that element gets reported when jointly k-anonymous with IG owner, biddingLogicURL, and renderURL.

With Leeron’s March 13th issue #873 proposal and Paul’s two tweaks:

joinAdInterestGroup({...
  'ads': [{renderURL: Ad1URL, 
           buyerReportingId: ‘this goes to buyer only’,
           buyerAndSellerReportingId: [ ‘this goes to buyer and seller’ ],
           sellerReportingId: ‘this goes to seller only’,
  ...})

When buyerAndSellerReportingId is an array, generateBid() picks an array element from buyerAndSellerReportingId, and that element, and buyerReportingId and sellerReportingId get reported when jointly k-anonymous with IG owner, biddingLogicURL, and renderURL.

Examples:

In these examples, ‘s’ prefix might be used to connote seat ID, ‘d’ prefix might connote deal ID.

If the same seat ID is always presented for bids on an ad:

joinAdInterestGroup({...
  'ads': [{renderURL: Ad1URL, 
           buyerReportingId: ‘buyerInfo123’,
           buyerAndSellerReportingId: [ ‘d123’, ‘d234’, ‘d345’ ],
           sellerReportingId: ‘s456’,
  ...})

If different seat IDs are presented for bids on an ad:

joinAdInterestGroup({...
  'ads': [{renderURL: Ad1URL, 
           buyerReportingId: ‘buyerInfo123’,
           buyerAndSellerReportingId: [ ‘d123s456’, ‘d234s567’, ‘d345s567’ ],
  ...})

@JensenPaul
Copy link
Collaborator

The challenging part here is the supression of the dealID from reportResult after it's been scored as a deal bid, due to k-anon -- and that's the difficultly -- can we discuss this further?

This was discussed in the 6/26/2024 WICG call and it sounded like the field Leeron described as "a new, optional field in the output of generateBid that buyers can use to require the buyerAndSellerReportingId to appear in the relevant reporting functions", let's call it buyerAndSellerReportingIdRequired, can be exposed to scoreAd(), perhaps via a browserSignals field with the same name. This would allow seller to require that bids set this to true when bidding on a deal to ensure that the buyerAndSellerReportingId will always be present in reportResult().

@JensenPaul
Copy link
Collaborator

Does this new field only take effect when all three are not jointly k-anonymous?

Yes, independent of buyerAndSellerReportingIdRequired, if all three are jointly k-anonymous, the bid will continue like normal and all three reporting IDs will be present in reportWin() and reportResult(). This matches today's behavior of reporting IDs.

If buyerAndSellerReportingId is marked optional but all three are jointly k-anonymous, does Chrome still report them?

Yes, this matches today's behavior of reporting IDs. Do you foresee a problem with this behavior?

@zhuoli-fledge, would you mind adding your name to your GitHub profile?

@rdgordon-index
Copy link
Contributor Author

There is not yet a document that combines #873 (comment) and #873 (comment).

Is this now covered by #1237 ?

@JensenPaul
Copy link
Collaborator

There is not yet a document that combines #873 (comment) and #873 (comment).

Is this now covered by #1237 ?

Yes.

@JensenPaul
Copy link
Collaborator

@dmdabbs, you asked for a Chromium bug to track implementation status: https://crbug.com/356654297

aarongable pushed a commit to chromium/chromium that referenced this issue Aug 2, 2024
This field is gated by a feature flag (kFledgeAuctionDealSupport).

This is part one of multiple CLs in order to get deal id support in
auctions.

More context on the deals can be found at
WICG/turtledove#873.

Bug: 356654297
Change-Id: I777bf29cbb6c379959e8d3787becce1fce2aeeef
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5753049
Reviewed-by: Ken Buchanan <[email protected]>
Reviewed-by: Koji Ishii <[email protected]>
Reviewed-by: Orr Bernstein <[email protected]>
Commit-Queue: Youssef Bourouphael <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1336731}
aarongable pushed a commit to chromium/chromium that referenced this issue Aug 9, 2024
This new behavior is only happening when
selectable_buyer_and_seller_reporting_ids is present, which is
gated by a feature flag (kFledgeAuctionDealSupport).

This is one of many changes working towards allow for
auction deal support.

More context on the deals can be found at
WICG/turtledove#873.

Bug: 334053709
Change-Id: Ied652229cd18c2fc2bcd03faa2a1f88b902c814f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5773232
Reviewed-by: Orr Bernstein <[email protected]>
Commit-Queue: Youssef Bourouphael <[email protected]>
Reviewed-by: Maks Orlovich <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1339643}
aarongable pushed a commit to chromium/chromium that referenced this issue Aug 14, 2024
Today, a bid is allowed to win an auction only if it's k-anonymous.
There's a separate "k-anonymity for reporting" that includes the
renderURL and all of the reporting IDs conveyed to the reporting
function as part of the k-anon key. If a winning bid is not
k-anonymous for reporting, the reporting IDs are all omitted in the
call to the reporting functions.

With the change to reporting IDs to support deals, described in
WICG/turtledove#873, a new reporting ID is
added, selectedBuyerAndSellerReportingId, which adds new k-anon for
reporting keys, multiple of which may need to be fetched for each ad
as the selectedBuyerAndSellerReportingId may be any one of the
selectableBuyerAndSellerReportingIds expressed in the InterestGroup ad.

Change-Id: Ife157dfa59e4e6a8fa6421ee87a5238d57110e11
Bug: 334053709
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5782241
Reviewed-by: Daniel Cheng <[email protected]>
Reviewed-by: Maks Orlovich <[email protected]>
Commit-Queue: Orr Bernstein <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1341902}
aarongable pushed a commit to chromium/chromium that referenced this issue Aug 20, 2024
This reverts commit 4bfa1a2.

Reason for revert: Causing crash on Linux ChromiumOS MSan bots: https://ci.chromium.org/ui/labs/p/chromium/inv/build-8739104148140144497/test/ninja%3A%2F%2Fcontent%2Ftest%3Acontent_unittests%2FSellerWorkletTest.ScoreAd/variant/fc06801f1fa91dab?resultIndex=0

Original change's description:
> Add new fields to scoreAd and bids.
>
> This change also adds new fields to a bid, which would allow buyers
> participating in deals to return new fields within the output of
> generateBid():
> - selectedBuyerAndSellerReportingIdRequired
> - selectedBuyerAndSellerReportingId
>
> This in turn allows for these two fields to be passed to scoreAd,
> and also the new behavior will allow the buyerAndSellerReportingId to
> be passed along with them if they are present.
>
> More context on the deals can be found at
> WICG/turtledove#873.
>
>
> Bug: 334053709
> Change-Id: If67f0dcaac96865ea96c9e99f72f0f1bbbee4889
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5777935
> Reviewed-by: Ken Buchanan <[email protected]>
> Reviewed-by: Maks Orlovich <[email protected]>
> Commit-Queue: Youssef Bourouphael <[email protected]>
> Reviewed-by: Orr Bernstein <[email protected]>
> Cr-Commit-Position: refs/heads/main@{#1343704}

Bug: 334053709
Change-Id: Ib1578b22f82dbc4e82c8074a3eec80fd9deef299
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5796248
Bot-Commit: Rubber Stamper <[email protected]>
Auto-Submit: Adam Rice <[email protected]>
Owners-Override: Adam Rice <[email protected]>
Commit-Queue: Adam Rice <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1344006}
aarongable pushed a commit to chromium/chromium that referenced this issue Aug 21, 2024
This is a TEST ONLY fix.

This fixed an uninitialized value error found by MSAN bots, within
the seller worklet unit tests. The implementation was not an issue but
instead there was a bool that was meant to be an optional in the test,
which the latest patch solves. This change does not affect any of the production code submitted in the original CL.

This reverts commit 5377aa4.

Reason for revert: Resolved an uninitialized value error.

Original change's description:
> Revert "Add new fields to scoreAd and bids."
>
> This reverts commit 4bfa1a2.
>
> Reason for revert: Causing crash on Linux ChromiumOS MSan bots: https://ci.chromium.org/ui/labs/p/chromium/inv/build-8739104148140144497/test/ninja%3A%2F%2Fcontent%2Ftest%3Acontent_unittests%2FSellerWorkletTest.ScoreAd/variant/fc06801f1fa91dab?resultIndex=0
>
> Original change's description:
> > Add new fields to scoreAd and bids.
> >
> > This change also adds new fields to a bid, which would allow buyers
> > participating in deals to return new fields within the output of
> > generateBid():
> > - selectedBuyerAndSellerReportingIdRequired
> > - selectedBuyerAndSellerReportingId
> >
> > This in turn allows for these two fields to be passed to scoreAd,
> > and also the new behavior will allow the buyerAndSellerReportingId to
> > be passed along with them if they are present.
> >
> > More context on the deals can be found at
> > WICG/turtledove#873.
> >
> >
> > Bug: 334053709
> > Change-Id: If67f0dcaac96865ea96c9e99f72f0f1bbbee4889
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5777935
> > Reviewed-by: Ken Buchanan <[email protected]>
> > Reviewed-by: Maks Orlovich <[email protected]>
> > Commit-Queue: Youssef Bourouphael <[email protected]>
> > Reviewed-by: Orr Bernstein <[email protected]>
> > Cr-Commit-Position: refs/heads/main@{#1343704}
>
> Bug: 334053709
> Change-Id: Ib1578b22f82dbc4e82c8074a3eec80fd9deef299
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5796248
> Bot-Commit: Rubber Stamper <[email protected]>
> Auto-Submit: Adam Rice <[email protected]>
> Owners-Override: Adam Rice <[email protected]>
> Commit-Queue: Adam Rice <[email protected]>
> Cr-Commit-Position: refs/heads/main@{#1344006}

Bug: 334053709
Change-Id: I99582655c81e9c73926b0f6205d879507518a487
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5799986
Commit-Queue: Youssef Bourouphael <[email protected]>
Reviewed-by: Maks Orlovich <[email protected]>
Reviewed-by: Ken Buchanan <[email protected]>
Reviewed-by: Orr Bernstein <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1344736}
@orrb1
Copy link
Collaborator

orrb1 commented Sep 4, 2024

As some of you have noticed from Paul Jensen's recently landed explainer PR at #1237, we've proposed a couple of small ergonomic simplifications to the names of the reporting fields used to support deals in Protected Audience auctions. Paul has updated the explainer PR with all of the changes reflected below, and added tables, examples. and clarifying language to better explain how this new feature will work.

The proposed change:

In the original deals proposal, we planned to modify the InterestGroup ads structure by changing the buyerAndSellerReportingId field to allow it to accept arrays, and creating a new field called sellerReportingId, that accepts strings. We now propose swapping the purpose of two fields to make it simpler:

  • buyerAndSellerReportingId will continue to be a string field only, and it will continue to be available for both the buyer (reportWin()) and seller (reportResult()) at event-level reports; adtechs can use it to store seatIDs in cases where the same seatID is used by all deals for a given ad. This is essentially what we had previously proposed as sellerReportingId, which we later realized had the same functionality as this field, and as such, we've decided to leave the buyerAndSellerReportingId unchanged.
  • The new field we plan to create will be named selectableBuyerAndSellerReportingIds, and it will be an array of strings. Adtechs can use this field to store dealIDs. This field will also be available for both the buyer (reportWin()) and seller (reportResult()) at event-level reports.

Why we made this change:

These changes were motivated by a few factors. Most notably:

  • Reusing an existing string-valued field to convey array-typed data poses a significant risk of unexpected behavior, where in older versions of the browser that still only know it as to be a string-valued field, the array would silently be stringified and concatenated and passed along as one string.
  • Overloading a field based on its type, with two different behaviors based on which of those types is provided, is, on further consideration, an unnecessarily tricky API design. By providing a new field for the array-typed data, we resolve this, and provide a more intuitive way for users to trigger this new feature.
  • Introducing a new field named sellerReportingId that had the same semantics as the existing buyerAndSellerReportingId field is confusing, especially in that sellerReportingId would have been made available to both buyer and seller. Instead we decided to leave the buyerAndSellerReportingId field alone and get rid of the new sellerReportingId field that was redundant with it.

Additional details:

  1. The output of generateBid() would contain one new string-typed field: selectedBuyerAndSellerReportingId. This would be a way for generateBid() to indicate which of the selectableBuyerAndSellerReportingIds it would like to select. This value of selectedBuyerAndSellerReportingId - along with buyerAndSellerReportingId - would be provided to scoreAd().
  2. When selectedBuyerAndSellerReportingId is provided to scoreAd(), reportWin() and reportResult():
    a. the value of buyerAndSellerReportingId - if provided on the InterestGroup ad - would also be provided to scoreAd(), reportWin() and reportResult().
    b. the value of buyerReportingId - if provided on the InterestGroup ad - would also be provided to reportWin().
  3. As before, all of the reporting field values provided to reportWin() and reportResult() would need to be k-anonymous along with the InterestGroup owner, biddingLogicURL, and the ad's renderURL.

One other significant change is that we're now implying selectedBuyerAndSellerReportingIdRequired has the value true whenever selectedBuyerAndSellerReportingId is returned by generateBid(), and false otherwise. This greatly reduces the trickiness of this field (and how scoreAd() needed to enforce it's value) and allows us to eliminate the selectedBuyerAndSellerReportingIdRequired field entirely as it's now directly implied by the presence or lack of selectedBuyerAndSellerReportingId.

We are working on a developer guide that summarizes all the previous changes to the plan and will help you understand the full proposal; we will share this to this channel when it is ready.

@orrb1
Copy link
Collaborator

orrb1 commented Sep 4, 2024

Deals support is now available for testing on 50% of Chrome Canary/Dev channel traffic. Support can be feature detected using this logic. It can also be manually enabled using the --enable-features=FledgeAuctionDealSupport command line flag.

@kevinkiklee
Copy link
Collaborator

Hello folks, we've published some guides to help you better understand reporting IDs and deals:

@orrb1
Copy link
Collaborator

orrb1 commented Sep 20, 2024

Deals support is now available for testing on 50% of Chrome Beta channel traffic. Support can be feature detected using this logic. It can also be manually enabled using the --enable-features=FledgeAuctionDealSupport command line flag.

@rdgordon-index
Copy link
Contributor Author

One other significant change is that we're now implying selectedBuyerAndSellerReportingIdRequired has the value true whenever selectedBuyerAndSellerReportingId is returned by generateBid()

Just to confirm -- given (3) above, does this imply that the bid is not k-anon with selectedBuyerAndSellerReportingId included, then the bid will not be allowed to be the chosen winner?

@zhuoli-fledge
Copy link

One other significant change is that we're now implying selectedBuyerAndSellerReportingIdRequired has the value true whenever selectedBuyerAndSellerReportingId is returned by generateBid()

Just to confirm -- given (3) above, does this imply that the bid is not k-anon with selectedBuyerAndSellerReportingId included, then the bid will not be allowed to be the chosen winner?

From the published spec

selectedBuyerAndSellerReportingId: (optional) A string from the interest group's ad's selectableBuyerAndSellerReportingIds array; if it's not in the array, the bid is ignored. If present, this is reported to reportWin() and reportResult() along with buyerAndSellerReportingId and buyerReportingId; the resulting bid may only win the auction if the selected value is jointly k-anonymous along with buyerAndSellerReportingId, buyerReportingId, the interest group owner, bidding script URL, and render URL. If present, it indicates the reporting of this bid would not operate correctly were the selectedBuyerAndSellerReportingId not presented to reportWin() and reportResult().

So I think the answer is no.

@orrb1
Copy link
Collaborator

orrb1 commented Oct 23, 2024

Yes, that's right. If generateBid() returns a selectedBuyerAndSellerReportingId, then that bid would only be allowed to win the auction if that selectedBuyerAndSellerReportingId were jointly k-anonymous along with buyerAndSellerReportingId, buyerReportingId, the interest group owner, bidding script URL, and render URL. This is to guarantee that selectedBuyerAndSellerReportingId, when present, is presented to reportWin() and reportResult(), as referenced in the comment thread between you and Paul on the explainer PR. Recall that scoreAd() is called on the bid even if it's not k-anonymous, so that it could become k-anonymous for future auctions. The value of selectedBuyerAndSellerReportingId is always presented to scoreAd(), regardless of whether or not that value is jointly k-anonymous as described above.

@orrb1
Copy link
Collaborator

orrb1 commented Nov 12, 2024

Deals support is now available for testing on 1% of Chrome Stable channel traffic. Support can be feature detected using this logic. It can also be manually enabled using the --enable-features=FledgeAuctionDealSupport command line flag.

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

No branches or pull requests

10 participants