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

Explainer changes for how currency-related things work #571

Merged
merged 20 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 49 additions & 4 deletions FLEDGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ See [the in progress FLEDGE specification](https://wicg.github.io/turtledove/).
- [3.3 Metadata with the Ad Bid](#33-metadata-with-the-ad-bid)
- [3.4 Ads Composed of Multiple Pieces](#34-ads-composed-of-multiple-pieces)
- [3.5 Filtering and Prioritizing Interest Groups](#35-filtering-and-prioritizing-interest-groups)
- [3.6 Currency Checking](#36-currency-checking)
- [4. Browsers Render the Winning Ad](#4-browsers-render-the-winning-ad)
- [5. Event-Level Reporting (for now)](#5-event-level-reporting-for-now)
- [5.1 Seller Reporting on Render](#51-seller-reporting-on-render)
- [5.2 Buyer Reporting on Render and Ad Events](#52-buyer-reporting-on-render-and-ad-events)
- [5.2.1 Noised and Bucketed Signals](#521-noised-and-bucketed-signals)
- [5.3 Losing Bidder Reporting](#53-losing-bidder-reporting)
- [5.3 Reporting in Multi-Currency Auctions](#53-reporting-in-multi-currency-auctions)
- [5.4 Losing Bidder Reporting](#54-losing-bidder-reporting)


## Summary
Expand Down Expand Up @@ -239,6 +241,10 @@ const myAuctionConfig = {
'https://www.another-buyer.com': 345,
'*': 456,
...},
'perBuyerCurrencies': {'https://example.co.uk': 'GBP',
'https://example.fr': 'EUR',
'*': 'USD'},
'sellerCurrency:' : 'CAD',
'componentAuctions': [
{'seller': 'https://www.some-other-ssp.com',
'decisionLogicURL': ...,
Expand Down Expand Up @@ -279,6 +285,8 @@ Optionally, `sellerExperimentGroupId` can be specified by the seller to support

Optionally, `perBuyerPrioritySignals` is an object mapping string keys to Javascript numbers that can be used to dynamically compute interest group priorities before `perBuyerGroupLimits` are applied. See [Filtering and Prioritizing Interest Groups](#35-filtering-and-prioritizing-interest-groups) for more information.

Optionally, `perBuyerCurrencies` and `sellerCurrency` are used for [currency-checking](#36-currency-checking). `sellerCurrency` is also used to [homogenize reporting in multi-currency auctions](#53-reporting-in-multi-currency-auctions).

Optionally, `resolveToConfig` is a boolean directing the promise returned from `runAdAuction()` to resolve to a `FencedFrameConfig` if true, for use in a `<fencedframe>`, or if false to an opaque `urn:uuid` URL, for use in an `<iframe>`. If `resolveToConfig` is not set, it defaults to false.
If the `window.FencedFrameConfig` interface is not exposed (because e.g., the script is running in an older version of Chrome that does not yet implement `FencedFrameConfig`, then the auction will _always_ yield a URN.
Therefore, when requesting a `FencedFrameConfig` for use in a fenced frame element, you have two options:
Expand Down Expand Up @@ -338,6 +346,7 @@ The function gets called once for each candidate ad in the auction. The argumen
'https://cdn.com/next_ad_component_of_bid',
...],
'biddingDurationMsec': 12,
'bidCurrency': 'USD', /* bidCurrency returned by generateBid, or '???' if none */
'dataVersion': 1, /* Data-Version value from the trusted scoring signals server's response */
}
```
Expand All @@ -348,6 +357,7 @@ The function gets called once for each candidate ad in the auction. The argumen
The output of `scoreAd()` is an object with the following fields:
* desirability: Number indicating how desirable this ad is. Any value that is zero or negative indicates that the ad cannot win the auction. (This could be used, for example, to eliminate any interest-group-targeted ad that would not beat a contextually-targeted candidate.) The winner of the auction is the ad object which was given the highest score.
* allowComponentAuction: (optional) If the bid being scored is from a component auction and this value is not true, the bid is ignored. If not present, this value is considered false. This field must be present and true both when the component seller scores a bid, and when that bid is being scored by the top-level auction.
* incomingBidInSellerCurrency: (optional) Provides a conversion of a bid in a multi-currency auction to seller's own currency. Please see [the section on this functionality](#53-reporting-in-multi-currency-auctions) for more details.
JensenPaul marked this conversation as resolved.
Show resolved Hide resolved

If `scoreAd()` returns only a numeric value, it's equivalent to returning {'score': numericValue, `allowComponentAuction`: false}.

Expand All @@ -369,6 +379,7 @@ Seller scripts in component auctions behave a little differently. They still ex
* desirability: Numeric score of the bid. Must be positive or the ad will be rejected.
* allowComponentAuction: If this field is not true, the bid will be rejected.
* bid: (optional) Modified bid value to provide to the top-level seller script. If present, this will be passed to the top-level seller's `scoreAd()` and `reportResult()` methods instead of the original bid, if the ad wins the component auction and top-level auction, respectively.
* bidCurrency: (optional) Annotates the currency of the modified bid provided by `bid`. Please see the [Currency Checking section](#36-currency-checking)

Once all of a component auction's bids have been scored by the component auction's seller script, the bid with the highest score is passed to the top-level seller to score. For that bid, the top-level seller's `scoreAd()` method is passed the `ad` value from the component auction seller's `scoreAd()` method, and there is an additional `componentSeller` field in the `browserSignals`, which is the seller for the component auction. All other values are the same as if the bid had come from an interest group participating directly in the top-level auction. In the case of a tie, one of the highest scoring bids will be chosen randomly and only that bid will be passed to the top-level seller to score. The seller of a component auction may reject all bids by giving them scores <= 0. In that case, no bid from that component auction will be passed to the top-level auction.

Expand Down Expand Up @@ -504,6 +515,7 @@ generateBid(interestGroup, auctionSignals, perBuyerSignals,
return {'ad': adObject,
'adCost': optionalAdCost,
'bid': bidValue,
'bidCurrency': 'USD',
'render': renderURL,
'adComponents': [adComponent1, adComponent2, ...],
'allowComponentAuction': false,
Expand Down Expand Up @@ -544,6 +556,7 @@ The output of `generateBid()` contains the following fields:
* ad: (optional) Arbitrary metadata about the ad which this interest group wants to show. The seller uses this information in its auction and decision logic. If not present, it's treated as if the value were null.
* adCost: (optional) A numerical value used to pass reporting advertiser click or conversion cost from generateBid to reportWin. The precision of this number is limited to an 8-bit mantissa and 8-bit exponent, with any rounding performed stochastically.
* bid: A numerical bid that will enter the auction. The seller must be in a position to compare bids from different buyers, therefore bids must be in some seller-chosen unit (e.g. "USD per thousand"). If the bid is zero or negative, then this interest group will not participate in the seller's auction at all. With this mechanism, the buyer can implement any advertiser rules for where their ads may or may not appear.
* bidCurrency: (optional) The currency for the bid, used for [currency-checking](#36-currency-checking).
* render: A URL which will be rendered to display the creative if this bid wins the auction.
* adComponents: (optional) A list of up to 20 adComponent strings from the InterestGroup's adComponents field. Each value must match an adComponent renderURL exactly. This field must not be present if the InterestGroup has no adComponent field. It is valid for this field not to be present even when adComponents is present. (See ["Ads Composed of Multiple Pieces"](#34-ads-composed-of-multiple-pieces) below.)
* allowComponentAuction: If this buyer is taking part of a component auction, this value must be present and true, or the bid is ignored. This value is ignored (and may be absent) if the buyer is part of a top-level auction.
Expand Down Expand Up @@ -633,6 +646,16 @@ The `BidFor240Minutes` interest group will have a positive priority if it was jo

The `FilterOnDataFromServer` interest group will result in fetching `https://buyer1.com/bidder_signals?publisher=<...>&interest_groups=FilterOnDataFromServer,<...>`, and then if that result has a `perInterestGroupData.FilterOnDataFromServer.priorityVector` object, then that is used just like the `priorityVector` field from the other two examples, except that it's only used for filtering, not to set the priority (unless the group has a true `enableBiddingSignalsPrioritization` field). A [user defined function](https://github.com/privacysandbox/fledge-docs/blob/main/key_value_service_trust_model.md#support-for-user-defined-functions-udfs) could be used on the FLEDGE Key-Value server to calculate that `priorityVector` value, and hence to decide if `FilterOnDataFromServer`'s `generateBid()` method is invoked or if it's filtered out.

### 3.6 Currency Checking

If participants in the auction need to deal with multiple currencies, they can optionally take advantage of automated currency checking. All of it operates on currency tags, which are required to contain 3 upper-case ASCII letters.

If the `generateBid()` method returns a `bidCurrency`, and the `perBuyerCurrencies` for that buyer is specified, their consistency will be checked, and if there is a mismatch, the bid will be dropped. Both the configuration and the returned tag must be present for checking to take place. The returned `bidCurrency` will be passed to `scoreAd()`'s `browserSignals.bidCurrency`, with unspecified currency rendered as `'???'`.

Currency checking after `scoreAd()` happens only inside component auctions. If `scoreAd()` modifies the bid, the modified bid's currency will be checked; if not, the passed-through bid from the original buyer's currency will be. In either case, the currency will be checked both against the component auction's `sellerCurrency` and top-level auction's `perBuyerCurrencies` as applied to the component auction. As before, both the bid and the configuration in question must be specified for the checking to take place. If there is a mismatch, the bid will not take part in the component auction.
morlovich marked this conversation as resolved.
Show resolved Hide resolved

`sellerCurrency` also has an extensive effect on how reporting behaves. Please see the section on [Reporting in Multi-Currency Auctions](#53-reporting-in-multi-currency-auctions) for more details.

### 4. Browsers Render the Winning Ad

The winning ad will be rendered in a [Fenced Frame](https://github.com/shivanigithub/fenced-frame): a mechanism under development for rendering a document in an embedded context which is unable to communicate with the surrounding page. This communication blockage is necessary to meet the privacy goal that sites cannot learn about their visitors' ad interests. (Note that the microtargeting prevention threshold alone is not enough to address this threat: the threshold prevents ads which could identify a single person, but it allows ads which identify a group of people that share a single interest.)
Expand Down Expand Up @@ -683,14 +706,17 @@ The arguments to this function are:
'componentSeller': 'https://www.some-other-ssp.com',
'interestGroupOwner': 'https://www.example-dsp.com/',
'renderURL': 'https://cdn.com/url-of-winning-creative.wbn',
'bid:' bidValue,
'bid': bidValue,
'bidCurrency': 'USD',
'desirability': desirabilityScoreForWinningAd,
'topLevelSellerSignals': outputOfTopLevelSellersReportResult,
'dataVersion': versionFromKeyValueResponse,
'modifiedBid': modifiedBidValue,
'highestScoringOtherBid': highestScoringOtherBidValue
'highestScoringOtherBid': highestScoringOtherBidValue,
'highestScoringOtherBidCurrency': 'EUR'
}
```
* `bidCurrency` and `highestScoringOtherBidCurrency` provide (highly redacted) information on what currency the corresponding numbers are in. Please refer to the section on [Reporting in Multi-Currency Auctions](#53-reporting-in-multi-currency-auctions) for more details.
JensenPaul marked this conversation as resolved.
Show resolved Hide resolved
* directFromSellerSignals is an object that may contain the following fields:
* sellerSignals: Like auctionConfig.sellerSignals, but passed via the [directFromSellerSignals](#25-additional-trusted-signals-directfromsellersignals) mechanism. These are the signals whose subresource URL ends in `?sellerSignals`.
* auctionSignals: Like auctionConfig.auctionSignals, but passed via the [directFromSellerSignals](#25-additional-trusted-signals-directfromsellersignals) mechanism. These are the signals whose subresource URL ends in `?auctionSignals`.
Expand Down Expand Up @@ -747,7 +773,26 @@ When `joinCount` is passed to `generateBid()`, no noising or bucketing is applie

These signals were requested in [issue 435](https://github.com/WICG/turtledove/issues/435). The signals are intented to ship in Chrome M114, they will no longer be available for event level reporting when event level reporting is retired.

#### 5.3 Losing Bidder Reporting
#### 5.3 Reporting in Multi-Currency Auctions

In auctions that involve multiple currencies, there may be values with different units floating around, which makes aggregated information incomprehensible, and event-level information hard to process, potentially requiring participants to interpret currencies of jurisdictions they do no business in.

To help deal with this scenario, an optional mode is available that converts all bid-related information to seller's preferred currency (in component auctions, reporting for it is for that component's seller). This is configured via the `sellerCurrency` setting in each auction configuration.

Regardless of configuration, the bid passed to `reportWin()` and `reportResult()` is always the bid that participated in that particular level of the auction (which, for top-level auction `reportResult()`, may be the bid altered by the component auction), subject to the usual rounding rules. Since passing the returned currency tags around could leak an unacceptable amount of information, the values provided for `browserSignals.bidCurrency` to those methods are the currencies required by the auction configuration in this context, or `'???'` if there isn't one.
morlovich marked this conversation as resolved.
Show resolved Hide resolved

(Warning: `reportResult` did not follow this rule in Chrome earlier than M116)

All other values, including `highestScoringOtherBid` and winning bids provided to private aggregation and debug event-level loss reporting depend on the `sellerCurrency` setting.

If `sellerCurrency` is not set, all bids in those other ("mixed currency") contexts are passed as-is, and all the corresponding currency tags (`bidCurrency`, `highestScoringOtherBidCurrency`) are redacted to `'???'`.
JensenPaul marked this conversation as resolved.
Show resolved Hide resolved

If `sellerCurrency` is set, `scoreAd()` for an auction is responsible for converting bids not already in that currency to `sellerCurrency`, via the `incomingBidInSellerCurrency` field of its return value. A bid already explicitly in the seller's currency can not be changed by `incomingBidInSellerCurrency`. If neither the original bid is explicitly in proper currency nor an `incomingBidInSellerCurrency` is specified, a value of 0 is used. All currency tags for reporting in those "mixed currency" contexts will be set to `sellerCurrency`.
morlovich marked this conversation as resolved.
Show resolved Hide resolved
JensenPaul marked this conversation as resolved.
Show resolved Hide resolved

Note that `incomingBidInSellerCurrency` is different from the modified bid returned by a component auction: it represents a mechanical currency translation of the original buyer's bid, rather than the bid the component auction is making in a top-level auction (which could, perhaps, be reduced by the intermediate seller's fee or the like). It can also be specified in top-level auctions, unlike the modified bid.


#### 5.4 Losing Bidder Reporting

We also need to provide a mechanism for the _losing_ bidders in the auction to learn aggregate outcomes. Certainly they should be able to count the number of times they bid, and losing ads should also be able to learn (in aggregate) some seller-provided information about e.g. the auction clearing price. Likewise, a reporting mechanism should be available to buyers who attempted to bid with a creative that had not yet reached the k-anonymity threshold.

Expand Down
2 changes: 2 additions & 0 deletions FLEDGE_extended_PA_reporting.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,8 @@ Where `signalBucket` and `signalValue` is a dictionary which consists of:
* 6: indicates seller rejected bid because “Creative Filtered - Language Exclusions”
* 7: indicates seller rejected bid because “Creative Filtered - Category Exclusions”
* 8: indicates seller rejected bid because "Creative Filtered - Did Not Meet The K-anonymity Threshold"
* 9: indicates bid produced by `generateBid()` was rejected because it failed a currency check
* 10: indicates bid passed through or altered by `scoreAd()` was rejected because it failed a currency check
morlovich marked this conversation as resolved.
Show resolved Hide resolved
* Perhaps other values indicating:
* generateBid() hitting timeout
* The auction was aborted (i.e. calling endAdAuction())
Expand Down
3 changes: 3 additions & 0 deletions Proposed_First_FLEDGE_OT_Details.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,13 @@ As the FLEDGE explainer talks about, the FOT#1 will include event-level reportin
The FOT#1 will include event-level reporting for both winning and losing bids. Implementations of the `generateBid()` and `scoreAd()` worklets, provided by the buyers and sellers respectively in the auction, may call a `forDebuggingOnly.reportAdAuctionLoss()` API which takes a single string argument representing a URL. The text placeholders below will be replaced with the corresponding value from the auction when found in the reporting URL's query parameters (note that due to http://crbug.com/1338233, prior to Chrome version 107.0.5286.0, the replacements only took place in the path of the URL)

* “${winningBid}” - The value of the winning bid. In component auctions, this value comes from the component auction and not the top-level auction.
* “${winningBidCurrency}” - The currency `winningBid` is in. This is `'???'` if it's in bidder's original currency, or is a currency tag if it's in seller's currency.
JensenPaul marked this conversation as resolved.
Show resolved Hide resolved
* “${madeWinningBid}” - A boolean value representing whether the owner of this interest group made the winning bid, either via this interest group, or another interest group with the same owner. In component auctions, this value comes from the component auction and not the top-level auction.
* “${highestScoringOtherBid}” - The value of the bid that was scored as second highest by the seller’s scoreAd script. Note that this may not be the second highest bid value, since scores and bids may be independent. In component auctions, this value comes from the component auction and not the top-level auction.
* “${highestScoringOtherBidCurrency}” - The currency `highestScoringOtherBid` is in. This is `'???'` if it's in bidder's original currency, or is a currency tag if it's in seller's currency.
* “${madeHighestScoringOtherBid}” - A boolean value representing whether the owner of this interest group made the ${highestScoringOtherBid} bid, either via this interest group, or another interest group with the same owner. In component auctions, this value comes from the component auction and not the top-level auction.
* “${topLevelWinningBid}” - The value of the bid that won the top-level auction. This value is only reported in component auctions.
* “${topLevelWinningBidCurrency}” - The currency `topLevelWinningBid` is in. This is `'???'` if it's in whatever currency the component auction made the bid in, or is a currency tag if it's in top-level auction's seller currency.
* “${topLevelMadeWinningBid}” - A boolean value representing whether the owner of this interest group made the bid that won the top-level auction, either via this interest group, or another interest group with the same owner. This value is only reported in component auctions.

If the bid being generated or scored loses the auction, the URL will be fetched. These worklets may also call a `forDebuggingOnly.reportAdAuctionWin()` API which operates similarly to `forDebuggingOnly.reportAdAuctionLoss()` API but only fetches the URL after a winning bid or score.
Expand Down