Open stguav opened 2 years ago
This is tricky. There does not seem to be any great solution to this problem. I have a few suggestions below, but none is really satisfying.
Given that advertisement rendering and reporting in your proposal go through the same controlled channels that normal FLEDGE interest group advertising does (i.e. Fenced Frames and reporting worklets), and that the interest group and auction configuration information flow from the same places they do in normal FLEDGE operation, I think the privacy aspects of your proposal seem reasonable. I like that your proposal encourages contextual advertising to go through the FLEDGE auction as this potentially decreases the entropy leaked by the null versus non-null auction promise result (decreasing #211 concerns).
In FLEDGE today, the person using an interest group’s information to bid (represented by the origin of biddingLogicUrl
) is required to match the interest group’s owner. By passing bids into the auction via negativeTargetingAds
, the browser cannot enforce this restriction. Essentially the browser cannot answer the question “how do we know the person adding people to the interest group wants their interest group to be used when targeting the contextual ad?” I think there are a few potential ways to solve this problem but none is particularly simple or efficient:
Option 1: Use bidding scripts
Instead of passing the bid value and ad URL in as part of negativeTargetingAds
, pass in the URL of a generateBid()
script that can return the bid value and ad URL. The bidding script’s origin can be required to match that of the interest group owner.
Option 2: Use a signed exchange (SXG) or signed WebBundle
Instead of passing the bid value and ad URL in as part of negativeTargetingAds
, pass in a SXG or signed WebBundle that specifies the bid value and ad URL, or contains a generateBid()
script. The signature’s origin can be required to match that of the interest group owner.
Option 3: Use an iframe
Instead of passing the bid value and ad URL in as part of negativeTargetingAds
, provide an API for an iframe to pass in the bid value and ad URL into the auction. The iframe’s origin could be required to match that of the interest group owner.
Option 4: Limit to runAdAuction()
caller
We could require the caller of runAdAuction()
’s origin match that of the interest group owner. This is likely to be prohibitively limiting.
It should be noted that several of these solutions are similar to solutions considered in #119.
The interest group could list other origins they are willing to allow using this interest group for negative targeting. The listed origins would have to match one of the origins from Options 1-4.
For Options 1 and 2 - normally only the IG owner can add a user to an IG, or a 3rd party explicitly delegated permission by the owner. Even forcing the bidder script to be loaded from a same-origin URL to the interest group, we're still potentially asking a bidder to bid unexpectedly. We'd probably need the bidding script to explicitly opt-in to this behavior, likely be returning an additional field in the return value to explicitly allow this use case.
There are a also a rather large number of design decisions that would need to be made (Do we support bidding signals? What's the priority of the pseudo-IG? Do we need to check for k-anonymity, and if so, how do we do it? Do we have an API to also set a WASM url? What IG would we pass in to generateBid()).
We would like to propose the following option for supporting negative Interest Group targeting.
If the ad owner and IG owner do not match, the ad will be shown regardless of whether the browser has joined IG or not. With this option, the matching of the owners needs to occur only if the browser has joined the negatively targeted IG.
Suppose that advertiser A wants to target users who have not joined G - an interest group belonging to advertiser B. The browsers that did not join G will unconditionally allow negative targeting of G. The browser that joined G, however, will not show the ad only if the owners match.
This will make A negatively targeting G fail, since the exclusion of browsers that joined G will be prevented.
Instead of passing the bid value and ad URL in as part of negativeTargetingAds, pass in a SXG or signed WebBundle that specifies the bid value and the ad URL, or contains a generateBid()
script, and signed with IG owner’s private key. The signature will be validated by Chrome with the IG owner’s public key on the client.
It is SSP owned code that receives the negative IG targeting DSP data. This arrangement allows SSPs to filter and rank negative IG targeted ads before the FLEDGE auction.
DSPs need to provide two categories of negative IG targeting data to the SSP.
SSP code will be able to use category 1 data to perform filter or other processing. If SSP decides that negative IG targeting metadata can proceed to the auction, it will move category 2 data into the auction config prior to initiating FLEDGE auction.
DSPs could provide metadata about negative interest group targeting of ads to SSPs through the regular OpenRTB bid response (see https://iabtechlab.com/wp-content/uploads/2022/04/OpenRTB-2-6_FINAL.pdf section 4) with custom Bid object extension fields, for example (negative_targeting_metadata
):
{
"id": "Vb8ttXOO",
"seatbid": [{
"seat": "buyer",
"bid": [{
"id": "L8QmgECv",
"impid": "1",
"price": 2.3,
"nurle": "win_notice_url",
"adm": "<img src=\"https://adnetwork.example/ads?id=9nLHIRIb&wprice=${AUCTION_PRICE}\">",
"adomain": "shoes.advertiser.example",
"cid": "running_shoes_campaign",
"crid": "running_shoes_creative",
"ext": {
"negatively_targeted_interest_group": "running_shoes",
"signed_metadata_for_chrome": "signed_metadata_for_running_shoes"
}
"w": "361",
"h": "203"
},
{
"id": "9nLHIRIb",
"impid": "2",
"price": 3.2,
"nurle": "win_notice_url",
"adm": "<img src=\"https://adnetwork.example/ads?id=5vAyHHZS&wprice=${AUCTION_PRICE}\">",
"adomain": "watches.advertiser.example",
"cid": "sports_watch_campaign",
"crid": "sports_watch_creative",
"ext": {
"negatively_targeted_interest_group": "sports_watch",
"signed_metadata_for_chrome": "signed_metadata_for_sports_watches"
}
"w": "320",
"h": "320"
}]
}]
}
Chrome will validate signed_metadata_for_chrome
. signed_metadata_for_chrome
contains buyer domain or some other information that will help to verify that the buyer providing negative IG targeting metadata has permissions to negatively target the specified interest group.
If an SSP decides that a given ad can participate in the FLEDGE auction, it will add the following to the auction config:
const myAuctionConfig = {
negativeTargetingAds: {
negative_targeting_metadata.seatbid(0).seat(): [{
buyer_ad_metadata: negative_targeting_metadata.seatbid(0).bid(0),
desirability: desirability_score1,
sellerReportingURL: seller_reporting_url,
signedMetadata: negative_targeting_metadata.seatbid(0).bid(0).ext()
.signed_metadata_for_chrome(),
},
...
],
negative_targeting_metadata.seatbid(1).seat(): [{
buyer_ad_metadata: negative_targeting_metadata.seatbid(1).bid(2),
desirability: desirability_score2,
sellerReportingURL: seller_reporting_url,
signedMetadata: negative_targeting_metadata.seatbid(1).bid(2).ext()
.signed_metadata_for_chrome(),
},
...
}
}
Here, buyer_ad_metadata
corresponds to the Bid object of the bid response and contains ad data needed by the buyer in order for the ad to enter the auction. Desirability
is the seller’s desirability score for the ad that will be used to compare a negatively targeted ad against other FLEDGE bids (which are assigned their desirability score by the scoreAd function), and sellerReportingURL
is the URL that the browser will request if the ad wins and gets rendered. These fields are to be provided by the SSP.
contains ad data needed by the buyer in order for the ad to enter the auction
What does this mean? Can you clarify intent of buyer_ad_metadata
above and how it could be used in the on-device auction? Who or what (some of on-device bidding or reporting functions? something else?) would be consuming this metadata?
buyer_ad_metadata will be initially consumed by the seller on the serverside. It will contain the data required by the seller to decide whether the ad can enter the auction, and the data required by the seller to optionally log information about the ad. If the seller decides to pass the ad to the browser-side auction, it will add the metadata to the auction config, possibly modifying "price" (since "price" should be seller's desirability score).
On the browser, Chrome owned code will use the data to decide whether the ad wins the auction. If the ad wins, Chrome will use "nurl" to notify the buyer about the outcome of the auction. Currently, the rendering mechanism is underspecified. Nevertheless, Chrome code will also initiate the rendering if the ad wins.
Using a WebBundle from the DSP that owns the IG being negatively targeted to fully generate the bid, and identify the IG being negatively targeted (or at least confirm it) does sound like it could be viable to me, from privacy and security standpoints.
@MattMenke2 can you clarify what you mean by 'WebBundle from the DSP' in this context - assuming for now it is an SSP that returns an ad response to the device?
I mean the IG owner. I don't think we can expose IGs to 3P scripts without buy-in from the IG owner. Using ads generated by the IG owner is the way FLEDGE currently accomplishes that.
Hi everyone. I've been thinking about this problem for a bit, and I have a design I'd like to propose, which is mostly aligned with the comments above. With this design, it's possible to pass additional bids into runAdAuction()
, and for those additional bids to specify a negative InterestGroup that would behave as described above — a user's membership in that negative InterestGroup would indicate that the associated additional bid should not participate in the auction.
There are a few subtle differences worth noting between these additional bids and InterestGroup-based bids (those produced by calls to generateBid()
).
Each additional bid would be represented by a JSON object containing all of the data we need for that bid to participate in the auction alongside InterestGroup-based bids. Each of the additional bids would need to be enclosed in a signed exchange (SXG, https://web.dev/signed-exchanges/) — a data structure that bundles together a URL, its associated response, and a signature for validation — so that the auction can verify that the additional bid came from the buyer, unmodified.
The response payload of each additional bid's corresponding signed exchange would contain the JSON object representing that bid. That object would include the following fields, split into three categories:
interestGroup
: values normally passed to joinAdInterestGroup()
,bid
: values normally returned as part of the response of generateBid()
, and{
"interestGroup": {
// These would be passed to reportWin()
"name": "campaign123",
// This is used for its definition of reportWin()
"biddingLogicURL": "https://example-dsp.com/bid_logic.js"
},
"bid": {
// Fields analogous to those returned by generateBid()
"ad": 'ad-metadata',
"adCost": 2.99,
"bid": 1.99,
"bidCurrency": "USD",
"render": "https://example-dsp.com/ad/123.jpg",
"adComponents": [adComponent1, adComponent2, ...],
"allowComponentAuction": true,
"modelingSignals": 123,
},
// These fields are described in more detail below
"negativeInterestGroup": "campaign123_negative_interest_group",
"auctionNonce": "1234567890abcdeffedcba0987654321",
"seller": "https://www.example-ssp2.com",
"topLevelSeller": "https://www.another-ssp.com"
}
This design implements a series of protections to ensure that additional bids may be used only for the auction for which the buyer intended.
navigator.createAuctionNonce()
JavaScript method, setting the returned value in a new auctionNonce
field on the auctionConfig
, and ensuring that all additional bids have the same value set in their auctionNonce
fields. Any additional bid for which the nonce is missing or different from that of the auction will be ineligible from participating in the auction.seller
to ensure that only the seller for which it was intended may use that bid. For multi-seller auctions, this further ensures that the additional bid may only be used by the specific component auction for which it was intended. Any additional bid for which the seller is missing or different from that of the auction/component auction will be ineligible from participating in that auction/component auction.topLevelSeller
alongside the seller
, the latter being associated with the seller of the component auction. Any additional bid in a multi-seller auction for which the topLevelSeller
is missing or different from that of the auction will be ineligible from participating in that auction.For each additional bid, the URL associated with the signed exchange must have the origin of the associated buyer, but may otherwise have any path or query string that uniquely identifies that bid. The owner of the additional bid is implied by the origin of the signed exchange, and it must be this owner whose certificate is used to sign the exchange. This URL is only used in the user's browser as an identifier, and no attempt will be made to fetch an additional bid from its origin. As is the case for InterestGroups, the biddingLogicURL
field of an additional bid must be same-origin with the buyer of that additional bid, "and must point to URLs whose responses include the HTTP response header X-Allow-FLEDGE: true
," as described in the explainer.
To get these additional bids into the auction, we'll add a new additionalBids
field onto the auction config. The value of additionalBids
will be a JavaScript Array of Uint8Array instances, each containing the encoded bytes of a single signed exchange representing a single additional bid. As with several other fields on the auction config, additionalBids
can be passed in either as its actual value or as a Promise to that value. The buyer of each additional bid must be included in the auction's interestGroupBuyers
if that additional bid specifies a negativeInterestGroup
.
For each additional bid, the auction will first check to see if the user is a member of the specified negativeInterestGroup
, if the additional bid provides one. Because only the name of the negative InterestGroup is specified, this implicitly enforces that the additional bid buyer can use only those InterestGroups for which it is the owner. Any InterestGroup may be used as a negative InterestGroup. An InterestGroup specifically intended for use as a negative InterestGroup only needs to provide two of the InterestGroup attributes - owner
and name
. If the user is a member of the specified negativeInterestGroup, the additional bid will not participate in the auction.
The auction will call scoreAd()
for that additional bid that remains after validation and negative targeting have been applied. Each such additional bid can then compete against both InterestGroup-based bids and other additional bids in the auction. For additional bids that win the auction, event-level win reporting is supported via reportWin
, just as it is for stored InterestGroups.
One clarification based on feedback received on the proposal above. This design is only intended to address the use case of negatively targeting contextual ads and other ads not triggered by the presence of a positive InterestGroup (non-remarketing). One thing that led to this confusion is that, among the data provided for each additional bid, a bid needs to specify an "InterestGroup name" via the interestGroup.name field. This InterestGroup name does not map to an existing InterestGroup, and it's only needed/used when reporting the win of an additional bid. Thanks for the feedback.
@orrb1 thank you for the design proposal follow-up. Interesting stuff. Would be great to discuss in this week's Wednesday PAAPI call. I added it to end of tomorrow's agenda. Hope you or @morlovich are available to field questions & suggestions.
One piece of feedback received on the design above is that the option to specify only a single negativeInterestGroup is overly limiting. In order to improve the usability of this feature, we're expanding it to allow multiple negativeInterestGroups, with the restriction that, when multiple negativeInterestGroups are specified, all must have been joined from a single origin specified as part of the additional bid.
This restriction won't apply to additional bids that specify only a single negativeInterestGroup. When a single negativeInterestGroup is specified, that InterestGroup may have been joined from any origin, or even from multiple origins. To support this, we'll use a syntax that distinguishes the single negativeInterestGroup case from the multiple negativeInterestGroups case. For a single negativeInterestGroup, we use the same syntax expressed in the design above:
{
"interestGroup": {
// existing fields
},
"bid": {
// existing fields
},
"negativeInterestGroup": "example_advertiser_negative_interest_group"
// remaining fields
}
To specify multiple negativeInterestGroups, buyers would use the following syntax:
{
"interestGroup": {
// existing fields
},
"bid": {
// existing fields
},
"negativeInterestGroups": {
joiningOrigin: "https://example-advertiser.com",
interestGroupNames: [
"example_advertiser_negative_interest_group_a",
"example_advertiser_negative_interest_group_b",
]
},
// remaining fields
}
Edit(8/23/23): Modified the joining origin to include the protocol.
As we worked to implement our previous design, we ran into some headwinds with our use of Signed Exchanges (SXGs). It’s unclear if we needed all the comprehensiveness of SXGs, so we’re considering a somewhat simpler approach that involves the following tweaks to the previous proposal:
additionalBids
is no longer a JavaScript Array of Uint8Array instances of SXGs. Instead, it’s a JavaScript Array of Ed25519 signed bids, each looking like this:
{
"bid": <stringified JSON of the bid mentioned before>
"signatures": {
{
"key": <Uint8Array of 32 bytes>,
"signature": <Uint8Array of 64 bytes>
},
{
"key": <Uint8Array of 32 bytes>,
"signature": <Uint8Array of 64 bytes>
},
}
}
Note that bid
needs to be a string to ensure that its hash is identical during signing and signature verification.
Interest groups used for negative targeting would need to contain an additional field:
"additionalBidKey": <Uint8Array of 32 bytes>
Within the bid, we add a new field, interestGroup.owner
, to indicate the buyer. This wasn't needed in the previous design because it was implied by the SXG's request URL.
When the browser considers whether to block an additional bid based on whether its negativeInterestGroup
exists, the blocking only occurs if the interest group’s additionalBidKey
matches one of the key
s in the additional bid's signatures
field, and it’s verified as having signed the additional bid's bid
string into the signature
. If the signature does not match, the bid is not blocked and continues as if the negativeInterestGroup
didn’t exist.
It should be noted that the browser has less verification that the additionalBids
originated from the named bidders, and thus bidders should be sure to verify that billing for rendered ads matches their logs for these additionalBids
. This is made easier by the fact that additionalBids
are contextual bids so they only contain single-site information, so they can report unique bid identifiers linked to particular bid prices and ads.
Because the browser is no longer verifying the additional bid's signature in cases where the negative interest group is present, it could be tampered with. This represents a difference with the interest group that is normally passed to reporting functions reportWin()
and reportResult()
, so to ensure that adtechs are aware of this difference in inputs to the reporting functions, we’re changing the names of the reporting worklets that are called for additionalBids to reportAdditionalBidWin()
and reportAdditionalBidResult()
.
I think @orrb1 meant "is not present" when he said "is present" in the last comment.
With the shift away from signed exchanges, we no longer can verify that the additional bids are untampered with by other JavaScript in the context that calls runAdAuction
. One way to increase the security of the additional bids is to ensure that they arrive at the auction directly from ad tech servers without passing through the JavaScript context. To address this, we're applying the same response header mechanism to protect additional bids that's already in use for the Bidding & Auction response blob and directFromSellerSignals.
To use response headers to convey the additional bids, the request to fetch additional bids will first need to specify the adAuctionHeaders
fetch flag.
fetch("https://...", {adAuctionHeaders: true});
The response will then need to include the additional bids not as part of the body of the HTTP response, but rather as response header values. Each instance of the Ad-Auction-Additional-Bid
response header will correspond to a single additional bids. The response may include more than one additional bids by specifying multiple instances of the Ad-Auction-Additional-Bid
response header. The structure of each instance of the Ad-Auction-Additional-Bid
header must be as follows:
Ad-Auction-Additional-Bid:
<auction nonce>:<base64-encoded additional bid JSON>
These HTTP response headers are intercepted by the browser, diverted to participate in the auction, but removed from the HTTP response headers seen in JavaScript. The additionalBids field on the auction config will be a Promise of type undefined, since it needs no value, but rather is only used to express that all additional bids for that auction have arrived. When all of the header-based additional bids for an auction have been received, the additionalBids Promise should be satisfied. The browser will use this to accept the bids provided by the Ad-Auction-Additional-Bid
response headers into the auction.
Owners providing addtional bids must also pass the enrollment gating, yes?
Owners providing addtional bids must also pass the enrollment gating, yes?
Yes, that's correct. An additional bid's owner has to satisfy the same requirements as the owner of a bid created from a generateBid()
call, including the enrollment gating and inclusion in auction config's interestGroupBuyers
field.
The negative targeting design described above has been implemented and documented in the Protected Audience explainer at https://github.com/WICG/turtledove/blob/main/FLEDGE.md#6-additional-bids.
There's one upcoming change to the implementation. The only field of a negative targeting interest group that can currently be updated is additionalBidKey
. However, the additionalBidKey
needs to be rotated for security only every 30 days. As such, key rotation can happen as part of the expiration of negative targeting interest groups. Therefore, negative targeting interest groups will not be updatable via the updateURL.
Supporting a 30 day key rotation, each additional bid should be signed with both the current and previous additionalBidKey
s. (The exception is when a buyer is first using additional bids, when they don't yet have a previous additionalBidKey
.) The process would work as follows:
In Chrome versions M119 and later, joinAdInterestGroup
will return an error if called with an interest group that provides both an additionalBidKey
- which makes it usable as a negative targeting interesting group - and updateURL
. The explainer will be updated to reflect this, and to specify the procedure for rotating the additionalBidKey
described above.
@orrb1 Does the seller pass the auctionNonce to buyer in contextual call request? It seems this is not documented in https://github.com/orrb1/turtledove/blob/main/FLEDGE.md#6-additional-bids. My understanding of the auctionNonce flow is:
navigator.createAuctionNonce()
to generate a new auctionNonce.Ad-Auction-Additional-Bid:<auction nonce>:<base64-encoding of the signed additional bid>
as header.navigator.runAdAuction({
// ...
'auctionNonce': auctionNonce,
'additionalBids': ...,
});
https://github.com/WICG/turtledove/blob/main/FLEDGE.md#63-http-response-headers mentioned the need to send a fetch request with adAuctionHeaders specified. However, some of our ad tags uses iframe navigation. Changing the default rendering mode of it would be a significant product and engineering lift. Could Chrome support an iframe-based version of the adAuctionHeaders API, e.g., create an iframe attribute,
@ryanluz: That's correct. Beyond that, the auction nonce also needs to appear in the JSON of the additional bid, as described at https://github.com/orrb1/turtledove/blob/main/FLEDGE.md#61-auction-nonce: "The same nonce value will need to appear in the auctionNonce field of each additional bid associated with that auction config."
@xxia2021: Thanks for the feedback. We're exploring this.
FYI to all: negative targeting has been launched for testing to 50% on Chrome's canary and dev releases.
the need to send a fetch request with
adAuctionHeaders
specified
Question: How will the seller in the contextual auction know if this fetch flag was specified in the fetch
request? Based on the spec and the explainer, there doesn't seem to be any additional HTTP request header passed to the seller -- and without this signal, how would a seller be able to convey the on-page support for additional bids to the buyers in the contextual auction?
@rdgordon-index - The adAuctionHeaders
fetch flag triggers the browser to send the Sec-Ad-Auction-Fetch
HTTP request header. This is described in the spec - https://wicg.github.io/turtledove/#request-capture-ad-auction-headers - but not in the explainer. I'll update the explainer to reflect that. Thanks.
Thanks, @orrb1.
FYI to all: negative targeting has been launched for testing to 50% on Chrome's canary and dev releases.
@orrb1 I'm wondering what is the flag to enable this in canary/dev?
@ryanluz - The flag is FledgeNegativeTargeting. Thanks.
Update: Additional bids and negative targeting have now been ramped to 100% of traffic in all Chrome release channels. Those who plan to rely on these features should continue to do so conditionally using feature detection to ensure that their experience works for users using all versions of Chrome. More details on how to feature detect negative targeting can be found at https://github.com/WICG/turtledove/blob/main/PA_Feature_Detecting.md#negative-targeting.
Hi - will there be any solution for a suppression campaign outside the retargeting flow? For example, when an advertiser is uploading a CSV of IDs, it wishes to exclude or when a DSP wants to serve/not serve an ad to excluded user contextually (outside the retargeting flow)?
@omriariav The Negative Targeting work that Orr described is indeed a "solution for a suppression campaign outside the retargeting flow." To exclude a user from a particular contextually-targeted campaign, you add the user to a Negative Interest Group and then include the contextually-targeted ad as an Additional Bid. For details see https://github.com/WICG/turtledove/blob/main/FLEDGE.md#62-negative-targeting
https://github.com/WICG/turtledove/issues/319#issuecomment-1699789430 Could not understand this properly. Please explain how additionalBid (correction - signedAdditionalBid(s)) will be passed in on-device auctions? In the explainer, it says:
Additional bids are commonly triggered using contextual signals.
Contextual signals refers to what? Do you mean the "Server side auction" part of this workflow? https://developers.google.com/authorized-buyers/rtb/protected-audience-api#serving_flow_summary
Additional bids are not provided through the auction config passed to runAdAuction(), but rather through the response headers of a Fetch request or iframe navigation.
Who is responsible for invoking the fetch request (or iframe logic)? Please explain where & how this happens in the workflow: https://developers.google.com/authorized-buyers/rtb/protected-audience-api#serving_flow_summary
We are confused as to how
The explainer & other documentation is not very helpful in the details of negative targeting workflow.
Thanks for the question about how additional bids are returned from buyers back to the on-device auction. This paragraph in the explainer aims to provide a high-level overview of this flow:
Buyers compute the additional bids, likely as part of a contextual auction. Buyers need to package up each additional bid using a new data structure that encapsulates all of the information needed for the additional bid to compete against other bids in a Protected Audience auction. Sellers are responsible for passing additional bids to the browser at Protected Audience auction time.
From the perspective of the browser, additional bids must be fetched from a Fetch request or iframe navigation to the seller's server, but the browser is not opinionated as to when this Fetch request or iframe navigation would need to happen. This is why the explainer isn't more explicit on how this interaction should happen.
Using https://developers.google.com/authorized-buyers/rtb/protected-audience-api#serving_flow_summary as a framework for how additional bids could be sent to the browser, additional bids would appear in the following places. To your point from above, when an additional bid is in transit between the buyer and browser, it's a signed additional bid.
In the "Server side ad Auction":
In the "In browser Auction" section:
scoreAd()
for each additional bid.reportAdditionalBidWin()
, as opposed to reportWin()
.Are seller
and topLevelSeller
required fields? From this thread it sounds like they are:
For multi-seller auctions, the additional bid will need to specify the topLevelSeller alongside the seller
but it's not clear to me from the explainer:
The seller and topLevelSeller fields echo those present in the browserSignals argument to generateBid() as described in section 3.2 On-Device Bidding. In generateBid(), these are meant to ensure that the buyer acknowledges and accepts that their bid can participate in an auction with those parties. Additional bids don't have a corresponding call to generateBid(), and so the seller and topLevelSeller fields in an additional bid are intended to allow for the same acknowledgement as those in browserSignals.
AFAIK, generateBid()
does not have to check browserSignals.topLevelSeller
; can an additional bid allow any TLS by omitting it?
It's a mandatory field in additionalBid. I'll defer to Orr on the motivation behind this (whether it's to prevent replay attacks, or make sure the bidder is fully informed of the context of the auction, since there is no generateBid() call where that normally happens, or something else).
The current FLEDGE API only supports positive Interest Group targeting: allowing advertisers to show ads to users that have interacted with their site. Advertisers are not just interested in re-engaging existing customers; advertisers are also interested in attracting new customers. Within FLEDGE, targeting this group of users requires an API change to support negative IG targeting: showing ads only if a user does not belong to an IG. Here we are specifically proposing a mechanism for negative IG targeting for non-FLEDGE ads.
This can be made to work in a way that is compatible with the privacy sandbox principles. We propose something like the following extension of FLEDGE.
In the
auctionConfig
, we add a new optional fieldnegativeTargetingAds
:where each
externalAd
is only eligible if the user does not have the corresponding IG. TheexternalAd
object has adesirability
field, a 'bid' field for reporting purposes, and arender
field. Note that server-side the SSP can vet the DSPs' ads, apply any sellside specific logic, and select the top one per negative IG. Then, the externally supplied ads that are eligible can compete with the positive IG ads'desirability
output fromscoreAd
.To maintain privacy, if one of the negative IG ads wins, then it goes through the FLEDGE rendering and reporting flow; that is, it will be rendered via the FLEDGE
auctionResultPromise
being passed into a Fenced Frame. A null response fromrunAdAuction
will indicate neither a positive nor negative interest group ad won the browser auction. The seller reporting would be unchanged, except perhaps from some 'browserSignals' field indicating that it was negative targeting. TheexternalAd
provides a 'reportingLogicUrl', which provides the buyer reporting functionreportWin
. ThereportWin
function should follow the same spec as when a regular IG ad wins in FLEDGE.Furthermore, the ad would be subject to the same k-anonymity requirements.