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

FLEDGE: currency of the bid #166

Closed
vincent-grosbois opened this issue Apr 12, 2021 · 58 comments
Closed

FLEDGE: currency of the bid #166

vincent-grosbois opened this issue Apr 12, 2021 · 58 comments

Comments

@vincent-grosbois
Copy link

Hello

after seeing issue #165 we wanted to ask questions regarding the currency we will bid with.

  1. Publisher will ask participants to bid in a given currency. How does FLEDGE implement this transfer of information, ie how will the bidding function know what kind of currency the publisher is expecting? It seems that there needs to be a way of "standardizing" this in the FLEDGE Api, as the bidding function can't know ahead of time the exact list of publishers it will be called on, and so it can't know the list of currencies each publisher will require
  2. If we assume that the publisher sends the info of the required currency to the bidding function, how is the bidding function supposed to handle this info? Suppose for instance that the bidding logic computes a bid in EUR and the publisher asks us a bidding value in USD. The bidding logic has to perform this EUR -> USD conversion. How in practice would it do it ? Storing fixed exchange rate in the bidding function is not really ideal as it will get stale. Another possibility we see is to store an up-to-date currency info in the key-value server, so that we will retrieve an up-to-date value during bidding. What's your take on this?

thanks!

@brodrigu
Copy link
Contributor

Adding the responsibility for accurate currency conversion rates to the browser might be tricky and having each buyer/IG ship its own currency conversion rates to the client would be inefficient.

I'd recommend that the buyer returns a currency along with the bid and that the publisher / SSP uses its own conversion rates to normalize in the scoring function. It's possible the publisher would need access to a conversion service, but its also possible that the scoring function could be shipped with good-enough conversion rates on a daily basis.

@michaelkleber
Copy link
Collaborator

Thanks for bringing this up on today's call, and pardon my ignorance as I try to fill out my understanding of the problem.

How do things work in RTB and in on-device header bidding today? In particular, does the auction specify the currency (or short list of currencies), and then each bidder has the obligation to submit in the currency permitted, perhaps looking up real-time conversion rates? Or do DSPs submit bids in many currencies, which are somehow normalized by the SSP?

Real-time data is available to the bidding and scoring functions, either through the config object passed into navigator.runAdAuction() (under the control of the seller) or through the real-time request to the trusted server (for both buyers and sellers). So there certainly are channels for making this sort of data available in the current design.

@vincent-grosbois
Copy link
Author

vincent-grosbois commented Apr 28, 2021

Thanks for the answer @brodrigu
I agree that the browser handling conversion rate is not really a good idea.

the scoring function could be shipped with good-enough conversion rates on a daily basis

Seems possible, but in that case the scoring function has to store all possible conversion rates for all possible publisher currencies. It seems it's contradictory with what you said in your first sentence where you said that having each buyer/IG ship its own conversion table is inefficient, as this solution would be exactly the same.

I'd recommend that the buyer returns a currency along with the bid and that the publisher / SSP uses its own conversion rates to normalize in the scoring function

That could work, but I'd be very very afraid that some publishers would simply not implement this and ignore this "currency name" value along with the bid, and then just compare bid values that would then be in different currencies (eg one bid in Euro, one bid in USD). Then there would be tons of silent conversion errors. This is why it would seem we need an "official" system so that the client can be sure that he returns a currency that the publisher expects

@vincent-grosbois
Copy link
Author

vincent-grosbois commented Apr 28, 2021

Hi @michaelkleber

How do things work in RTB and in on-device header bidding today? In particular, does the auction specify the currency (or short list of currencies), and then each bidder has the obligation to submit in the currency permitted, perhaps looking up real-time conversion rates? Or do DSPs submit bids in many currencies, which are somehow normalized by the SSP?

For the "vanilla RTB" case that I know of, we know in advance the publisher currency: either it's in the request and we use it, or most probably we have a database somewhere which maps a publisher id to the currency it requires; and our bidder just returns the value in the correct currency by converting it using (almost) real-time data. (to me the real-time aspect is really not important, I think any solution with conversion rates that were refreshed in a given day is fine)

So there certainly are channels for making this sort of data available in the current design.

Indeed. What I'm afraid of is that this just rely on the "convention" that publishers should communicate their currency of choice through a given keyword. Maybe this keyword should at least be standardized in the spec ?
Basically I'm looking for a way for this currency problem to be handled in a robust fashion. From experience I know that currency stuff will otherwise silently bug and then some party ends up unknowingly bidding 30x the intended amount :)

@brodrigu
Copy link
Contributor

. It seems it's contradictory with what you said in your first sentence where you said that having each buyer/IG ship its own conversion table is inefficient, as this solution would be exactly the same.

I assume here that the number of publishers/SSPs involved in a single Fledge auction would be small (probably 1) and the number of buyers would ideally be many. Hence a single conversion list handled by the publisher would be more efficient than a conversion list handled by N buyers.

It's a fair point that only a single SSP participating in a FLEDGE auction is sub-optimal and we may not want to align around that assumption.

@vincent-grosbois
Copy link
Author

Ah ok, sorry I misunderstood your message and mixed up bidding function and scoring function.
Indeed that's a possibility that each publisher handles internally its own currency conversion logic, and it would probably scale better than storing all conversion rates in either the bidding function or in the "trustes bidding signals" values.

Again, what i'm worried about with this solution is the fact that it requires publishers to change their logic and handle these conversions on their end (currently they don't do it). If a publisher decides to not care and assume all his bids are in Euro for instance, we will get super incoherent bids, and billing will be impacted too (imagine being billed mistakenly 100 Euros instead of 100 Korean Won, and the headache to sort this out...)

As a side note, I just had a look into the chromium fledge code and it seems that this comparaison of "who is the highest bidder" is not even done by the seller JS but directly by the browser

@vincent-grosbois
Copy link
Author

Hello @michaelkleber
do you have any update on this issue ? thanks

@MattMenke2
Copy link
Contributor

Publishers can already pass arbitrary data to scoreBid via the "ad" parameter of generateBid(). Could just require this be a currency indicator (could even ignore bid entirely and stuff the entire bid in there, if you really wanted, though bid would still have to be > 0), and then the seller signals (not currently implemented) would need to include conversion rates of all supported currencies.

Alternatively, the bidder could handle the conversions. Which, on one hand, means only the conversions needed for an auction would need to be downloaded from the bidders, but does place the onus on all bidders.

I'm not sure there's anything that can be reasonably done browser side to further facilitate this - could add a dedicated field for it as we think about other special use fields that might be handy, but I don't think that scales, and doesn't seem to be needed.

@vincent-grosbois
Copy link
Author

vincent-grosbois commented Jun 16, 2021

Alternatively, the bidder could handle the conversions. Which, on one hand, means only the conversions needed for an auction would need to be downloaded from the bidders, but does place the onus on all bidders.

If by bidder you mean not the browser itself but the buyer JS code, I don't see how it's possible technically to "only" download some currency rates based on publisher infos. The only communication channel with the outside is key/value server and you can't choose at bidding time which key to specifically query. It's however possible to download a json containing all conversion rates from the key/value server and applying the correct one based on what the publisher is asking.

Indeed from a purely technical standpoint, this currency issue can already be solved in 2 ways as we described above:

  • option 1 : get currency info from publisher, bidder has to deal with it and return a bid in given currency
  • option 2 : bidder bids in own currency and announces the currency, publisher deals with it and does the conversion

I'm not sure there's anything that can be reasonably done browser side to further facilitate this - could add a dedicated field for it as we think about other special use fields that might be handy, but I don't think that scales, and doesn't seem to be needed.

I don't think that anything needs to be done specifically in the browser code to handle this indeed, like having the browser itself download conversion rates and convert bids etc.
However, to me the way currency should be managed should be a part of the Fledge spec doc. As Fledge is describing a general-purpose system for adtech that is "decentralized" and that inherently does an auction between parties that don't know each other, currency should probably be a first-class "concept" included in the spec, and not an after-thought that is bolted on later on, where all the world's publisher and advertisers have now to agree on what convention they will use to transmit currency.

As I mentioned above, relying on each publisher and advertiser having their conventions on how to handle currency conversion is in itself the thing that doesn't scale, even more since bidding in incorrect currency going to produce silently invalid bids. Keep in mind that with Fledge you can easily have an APAC publisher loading interest group from a EU user, etc

@vincent-grosbois
Copy link
Author

Note that this is also causing trouble for the reporting, because the "cost" that is being sent in different reporting is currency-less, so it's impossible to actually know what to bill etc

@MattMenke2
Copy link
Contributor

I assume the seller script that's sending these reports would have to figure out the currency issue itself, so could decide what currency to use.

Note that the bidders and sellers in the FLEDGE spec are expected to know each other, and have agreements on, e.g., how to transfer money between each other. That's one of the reason the auction config lists IG owners that are allowed to participate in an auction.

@MattMenke2
Copy link
Contributor

(Note that wildcard owners are allowed in the FLEDGE spec, but that is currently disabled in Chrome, and likely will be removed)

@vincent-grosbois
Copy link
Author

vincent-grosbois commented Jun 19, 2021

Indeed it might be possible that for reporting to have the currency handled outside of Fledge, ie by knowing which publisher is billing in which currency etc.
But regarding the bidding itself, the currency has to be sorted out at this point also, otherwise the publisher will receive bids in different currencies and can't score them properly.
I understand that this could also be handled by convention outside of Fledge ("publisher 1 wants us to bid in USD", "publisher 2 allows us to bid in any currency but we have to send as metadata the currency of the bid", "publisher 3 wants us to use the currency sent in some seller signal"), but to me this seems to create massive complications for everybody and won't scale really well, over having a clear standard way to handle this defined in the spec. (having a convention in the spec wouldn't still prevent bidders from bidding in incorrect currency still, but that's another topic)

We should not forget that there is no real point in debating over ML models for bidding etc, as long as we can easily have a bid accidentally being 10x higher due to invalid currency.

@lbdvt
Copy link
Contributor

lbdvt commented Apr 12, 2022

In the light of the Origin Trial starting soon, I’d like to re-activate this issue:

Context

  • In most geos, marketers set campaign budgets in local currency and are getting billed by their DSP in local currency.
  • In most geos, publishers sell their ad inventory in local currency and bill their SSP in local currency.
  • In most geos, billing in the country’s currency is a legal requirement.
  • It’s in the very nature of the web to enable people access to a variety of websites in and outside their own geo. For example, a significant part of traffic for a well-known US blog site may come from outside of the US. So it’s very common for a marketing campaign from one geo to make displays on a publisher’s site of different geo. This is both beneficial for the marketer, reaching its audience on the sites they browse, and publishers, monetizing their inventory. So mismatches between the campaign’s and seller’s currencies, and currency conversions, do occur.

As of today, bidding currencies of an ad auction can be, for instance:

Needs

So FLEDGE must provide the following features:

  1. A way for the seller to agree in advance with or communicate to participating buyers the bidding currency or currencies.
  2. A way for buyers to bid in an accepted currency. Note that any currency conversion must be based on recent conversion rates, as sharp intra-day exchange rates variations do occur.
  3. And/Or a way for the seller to convert bids sent by the participating buyers.
  4. A way for a buyer to know, with low latency, winning bids amounts and currency per campaign and seller.
  5. A way for the seller to know, with low latency, winning bids amounts and currency per buyer.

In both reporting cases, amounts must be in the buyer bid currency, that is not modified by a seller-side conversion if any.

Proposal

In case of conversion done by the buyer (2.), this could be done by:

a. The seller adding the auction bid currency in auctionSignals.
b. The call to the buyer Trusted Server including the bid currency, something of the form
https://www.kv-server.example/getvalues?hostname=publisher.com&currency=EUR&keys=key1,key2
where the currency value is coded using the 3 letter ISO code for currencies.
c. The buyer Trusted Server returning in one of the keys the necessary relevant data so that generateBid() can take into account the bid currency through trustedBiddingSignalsKeys.
d. Adding a currency field in browserSignals alongside the bid value.
e. Passing bid value and bid currency to reportResult() and reportWin() .

a. b. d. would require a modification in FLEDGE, while c. and e. can be managed through the existing specifications.

Caveat

That solution does not support seller-side currency conversions.

What are your thoughts on this?

@MattMenke2
Copy link
Contributor

a. I don't believe this requires a modification in FLEDGE? auctionSignals is free form JSON, so buyers and sellers can agree to include currency as a dictionary entry in this field or somesuch.

d. Also doesn't seem to require changes. auctionSignals is passed to generateBid() and reportWin() explicitly. It's also available in the auctionConfig field of scoreAd() and ReportResult().

b. Would require changes. The current design deliberately minimizes bits of entropy provided by the page running the auction to the network requests related to the interest group. The privacy model involved in these requests isn't really my area, so I'll let others provide their thoughts there.

@lbdvt
Copy link
Contributor

lbdvt commented Apr 12, 2022

Thanks for the quick reply.

a. I don't believe this requires a modification in FLEDGE? auctionSignals is free form JSON, so buyers and sellers can agree to include currency as a dictionary entry in this field or somesuch.

If the currency is to be picked up from auctionSignals to be included in the call to the Trusted Server (as described in b), it would require standardization in FLEGE.

d. Also doesn't seem to require changes. auctionSignals is passed to generateBid() and reportWin() explicitly. It's also available in the auctionConfig field of scoreAd() and ReportResult().

That's true, even if I tend to think that having an explicit currency field next to the bid field in browserSignals would be a good property, that could also be leveraged in the case of seller-side currency conversion.

Looking forward for further discussions on b.

@sbelov
Copy link

sbelov commented Apr 13, 2022

How many bidding currencies would a typical buyer need to support in practice? Is that a fairly limited set?

Have you considered how the existing FLEDGE mechanisms can be used to communicate currency information, such as the conversion rate table for all potential auction currencies, in close to real-time? For example:

  • A buyer could populate conversion rates and, with the help of a seller, make those available to the in-browser auction via perBuyerSignals.

  • Alternatively, a buyer could reserve a single trusted bidding signal key to represent a currency table across all their interest groups. A browser would include that key in the request to the trusted server, e.g.:
    https://www.kv-server.example/getvalues?hostname=publisher.com&keys=currency_table,other_key,… … and a buyer would be able to return the currency table as an object value corresponding to that key.

Communicating rates for multiple currencies can incur network overhead (how many are we talking about?); perhaps, on-device caching – e.g. caching information for the same trusted bidding signals key – could be employed to reduce these costs

@lbdvt
Copy link
Contributor

lbdvt commented Apr 14, 2022

How many bidding currencies would a typical buyer need to support in practice? Is that a fairly limited set?

When considering buyer-side conversions, the question is "as an advertiser how likely is it for my audience to go on publisher sites from other geos?".

So for example, "as a runningshoes-shop.example, targeting an audience of people living and buying in Europe and having a marketing budget in EUR, how is it likely for my audience to read sites outside of Europe (and that these sites are running auctions in their local currency)?".
There are a lot of people in Europe who are likely to browse sites outside of Europe, like well-known US sites for instance, or because sites linked to their own cultural background, or for any other reason - the web knows no border :) .

As of today, as a "guestimate", a dozen to twenty currencies should cover most cases. But I don't think that should be a limitation that can be built upon: FLEDGE should not assume that a buyer audience will be limited to twenty geos / sellers' currencies.

A buyer could populate conversion rates and, with the help of a seller, make those available to the in-browser auction via perBuyerSignals.

That would add latency, as the seller would have to retrieve the buyers' conversion table in a server to server call first (assuming the buyer wants to control that table).

Alternatively, a buyer could reserve a single trusted bidding signal key to represent a currency table across all their interest groups.

Yes, that is doable, but that would add some network overhead for each FLEDGE ad auction. Caching client-side can reduce the load, but it will be limited by campaigns budget management needs.

Is adding the bid currency to the buyer Trusted Server call a significant privacy risk?

@jeffkaufman
Copy link
Contributor

jeffkaufman commented Apr 14, 2022

That would add latency, as the seller would have to retrieve the buyers' conversion table in a server to server call first

Isn't that call, to populate perBuyerSignals, already part of how people generally expect to use FLEDGE?

@lbdvt
Copy link
Contributor

lbdvt commented Apr 15, 2022

Isn't that call, to populate perBuyerSignals, already part of how people generally expect to use FLEDGE?

I think buyers will want to avoid doing this, because of extra latency (one extra network call), and scalability.

Regarding scalability

As of today, buyers (DSP) can ask sellers (SSP) to send only bid opportunities that they are likely to bid on. In particular, DSP and SSP can engage in cookie matching, which provides SSP the ability to select and send only (or at least in priority) bid opportunities for users "known" to the DSP.

The purpose of FLEDGE is also for buyers to be able to bid on opportunities for which they have some prior knowledge of the user (stored as Interest Group).

But with FLEDGE the SPP does not know which Interest Groups and IG buyers are stored in the browser for a given ad opportunity. So it has no way to know when to call a specific DSP for fetching perBuyerSignals data. In order for the DSP to get a maximum of Interest Group bid opportunities, the SSP would have to call the DSP for every ad opportunity, and the DSP would have to respond to these calls.

While various technics may diminish the load (client-side caching mainly?), responding to these calls is likely to incur significant costs for the DSP. These costs would be fixed, and proportionally more important for small or new actors (who would need servers to handle all these requests just for running their first campaign).

For the DSP, having to answer FLEDGE calls only for opportunities where at least one of its Interest Groups is present (which is the case with the Trusted Server) is, similar to what exists today, much more cost-effective, and does not create barriers to entry.

While buyers could include in the response of the Trusted Server a currency conversion table, adding the currency to the call to the Trusted Server seems a less network intensive and more straightforward way of addressing demand-side currency conversions:
https://www.kv-server.example/getvalues?hostname=publisher.com&currency=EUR&keys=key1,key2

Would that be possible?

@MattMenke2
Copy link
Contributor

There's already a proposal to add 16-bit of data to those requests available in the scope of the page for experiments. If there are, say, 128 different currencies, that's 7 more bits of info available to the requests, which gets us to 23 total bits of entropy, if both are in use.

I think this entirely depends on how concerned we are about more bits of entropy being available to both the site and the trusted buyer servers.

@appascoe
Copy link
Collaborator

Also, only calling out to DSPs that have interest groups in the browser could be another tracking vector as well. Since the SSP is responsible for fanning out the contextual request(s), they'd be able to do this.

Similarly, and more nefariously, a DSP could "fake" being multiple DSPs, and then perform timing attacks on calls to their servers, and deanonymize users that way.

@MattMenke2
Copy link
Contributor

Note that something is a tracking vector only if that information shares information from two different first party contexts and can provide it in a network request. DSP network requests only have context from the page on which the DSP was learned, except for the publisher, timing information, and the (putative) 16-bit experiment ID.

@appascoe
Copy link
Collaborator

Are you suggesting that what I proposed is not a tracking vector?

For example: The user goes to an advertiser page. The DSP generates a 64-bit ID for the user. Not only do they use this for the identifier in the first-party cookie, but they drop interest groups with different owners, dsp-0, dsp-1, ..., dsp-63 corresponding the bits of the identifier.

Later, the SSP, as in the suggestion, only receives the subset of "DSPs" that have interest groups in the browser. So they get a callout from the publisher page that includes { dsp-1, dsp-17, dsp-29 }. Not only can the SSP use this information, but each one of those fans out to the "DSPs," but these are all controlled by the malicious DSP. Now the DSP has learned that the user was on the advertiser page and on this publisher page. They record this and store it on their servers. Repeat, and now you've built a profile of the user's general web browsing habits.

@lbdvt
Copy link
Contributor

lbdvt commented Apr 15, 2022

Also, only calling out to DSPs that have interest groups in the browser could be another tracking vector as well. Since the SSP is responsible for fanning out the contextual request(s), they'd be able to do this.

@appascoe, the proposal is not for the SSP to call for perBuyerSignals only DSP that have interest groups in the browser.

The proposal is:

  • For SSP not to call any DSP for populating perBuyerSignals
  • For DSP to respond to the call to the Trusted Server, which call is already triggered only for DSP that have interest groups in the browser, but which does not require the SSP knowing which DSP have IG in the browser

@appascoe
Copy link
Collaborator

Sorry if I'm misunderstanding. How is this proposal immune to the tracking attack I outlined? If the malicious DSP has dsp-trusted-server-0, dsp-trusted-server-1, ..., dsp-trusted-server-63, (each associated with the different interest groups and owners) it still allows the DSP to track the user across sites because the callout to the trusted servers includes the publisher in the request.

@lbdvt
Copy link
Contributor

lbdvt commented Apr 15, 2022

If the malicious DSP has dsp-trusted-server-0, dsp-trusted-server-1, ..., dsp-trusted-server-63, (each associated with the different interest groups and owners) it still allows the DSP to track the user across sites because the callout to the trusted servers includes the publisher in the request.

Yes, it seems like a valid attack vector. But the currency management proposal does not add any new call to the DSP, and only relies on the one DSP call that already exists within the current FLEDGE specification :

Once a seller initiates an on-device auction on a publisher page, the browser checks each participating interest group for these fields, and makes an uncredentialed (cookieless) HTTP fetch to a URL of the form: https://www.kv-server.example/getvalues?hostname=publisher.com&keys=key1,key2

I guess that FLEDGE assumes the Trusted Sever to be ... trusted, and not to be used for such a timing attack, and that "trust guarantees" will be required in a future FLEDGE version.

The currency management proposal only proposes to add a currency field in that call:
https://www.kv-server.example/getvalues?hostname=publisher.com&currency=EUR&keys=key1,key2
and therefore does not improve or reduce the attack vector you describe.

@appascoe
Copy link
Collaborator

I don't have much of an opinion on the currency management proposal, just responding to the suggestion/request in your specific comment #166 (comment) , which I believe is unworkable from a privacy perspective.

@lbdvt
Copy link
Contributor

lbdvt commented Apr 19, 2022

Going back to the proposal of adding the auction currency, passed by the SSP, in the call to the Trusted Server, in a form such as https://www.kv-server.example/getvalues?hostname=publisher.com&currency=EUR&keys=key1,key2;

@MattMenke2

Note that something is a tracking vector only if that information shares information from two different first party contexts and can provide it in a network request.

Agreed.

DSP network requests only have context from the page on which the DSP was learned, except for the publisher, timing information, and the (putative) 16-bit experiment ID.

(I guess you meant "the page on which the DSP Interest Group was learned"?).

This is actually a lot, since that network request joins the publisher domain with an arbitrary number of bits from the DSP (the list of keys that has been set when the IG was learned). It's entirely doable for a DSP to use that list of keys to build a user id, which will then be joined with the successive publisher domains the user visits, through calls to the Trusted Server.

My understanding is that this is only possible because the server answering the call is a Trusted Server. If it is, sending the bid currency to that server should not be an issue.

@JensenPaul
Copy link
Collaborator

Most of 2/15/2023's WICG FLEDGE call was devoted to discussions on this issue's topic.

I believe @timphsieh's Options 1& 2 above have potential privacy impacts as more information flows into reporting. I wanted to call out two other options that I don't believe have privacy impacts:

Option 3: seller provides currency conversion table; all bids in same currency

This works as follows:

  1. Seller provides currency conversion table and indicates desired currency of bids to buyers via auctionSignals.
  2. Buyers calculate their bids in their preferred currency, then convert using conversion table to the desired currency.
  3. Buyer's reportWin function converts their bid value back to their desired currency for reporting.

This option facilitates buyers bidding and reporting in their desired currency, and highestScoringOtherBid's currency not being dependent on the winning buyer. Buyers can apply currency conversions on highestScoringOtherBid using the scale multiplier if reporting in aggregate, or by multiplying in reportWin.

Option 4: bids in different currencies; scoreAd converts to one currency

This works as follows:

  1. Buyers bid in their preferred currency and indicate the currency to the seller via the ad metadata field returned from generateBid.
  2. Seller converts each bid to one currency and their scoreAd function returns this converted bid to the browser. The browser passes the converted winning bid and highestScoringOtherBid to reportWin and reportResult.
  3. Buyers can convert the converted bid and highestScoringOtherBid values to their preferred currency if they chose perhaps using a currency conversion table provided by the seller in auctionSignals.

@MattMenke2
Copy link
Contributor

One potential issue here is fluxuations in exchange rates - if the exchange rate changes between when the auction runs, and when the aggregated report is received, the bidder may be charged more or less than they bid, when converted back to the currency they bid in. I guess if exchange rates are received by the publisher page, and sent along to reportWin() as well, the exchange rate could be taken into account in the aggregated report, though the more that's included in those, the less precise the data you can get out of them, I believe.

@appascoe
Copy link
Collaborator

I'd like to document what I said on the call and hopefully clarify why I think it's important.

The proposal is that seller's declare the currency that they want to be paid in in the auctionConfig. Buyers, in the interest group, can pack in a list of currencies and what the buyer believes is a fair exchange rate, and then use these to bid in the seller's desired currency. The interest group update mechanism can be used by buyers to update their exchange rates.

I said that this is an appropriate mechanism because it operates on two principles:

  1. Sellers are the ones who "own" their inventory. It is their right to determine how they are compensated for displaying an ad in that inventory.
  2. Buyers need to control their own exchange rates so they know exactly what they are offering to show an ad. Critically, buyers may actually differ in what they think a fair exchange rate is.

Why are these principles important? It's literally how all global financial markets work. Indeed, a large reason that exchange rates even exist is because sellers reserve the right to determine how they are compensated. The more sellers that desire to be compensated in a given currency, the value of that currency rises against other currencies. The opposite is also true.

Buyers also have an effect on currency markets. If they perform their own currency conversion, and the rate is lower than a seller thinks is fair, that will suppress their bids in the seller's currency. If enough buyers do this, what the seller can gain from the transaction is lower, which creates less economic value as measured in the given currency, lowering its value.

There is no such thing as a universal, agreed-upon exchange rate for converting between currencies. It's always a perception of value between sellers and buyers. This perception of value is mediated by the seller saying what they want and the buyer offering what they think is an appropriate quantity of those units. This is not new; these are fundamental global economic principles.

There was an objection on the call that there are certain regulations that entities must be billed and provide compensation in particular currencies, but we ran out of time. My proposal does not preclude this. A seller can sum up their auction payments, grouped by currency, and apply conversion rates for the bill to send to the buyer. This allows the buyer to clearly see, in bulk, what the average exchange rate is, and potential even bargain with the seller for a better rate post facto. But there's no reason to do this on every individual auction. Moreover, buyers have a capability to do "currency hedging:" if they are concerned that rates will fluctuate so dramatically before they get their bill, they can perform a currency exchange at a desired rate in the present and hold it to be used in the payment at a later date. Beyond hedging, a buyer, if they think the seller's currency is in rapid flux relative to their own, the buyer can bake this uncertainty into their own exchange rate, and simply bid less (or more!) than they otherwise would if they can control their own rate.

@sbelov
Copy link

sbelov commented Feb 19, 2023

@JensenPaul for clarity, in option 4, were you contemplating an extension to FLEDGE API that allows the seller's scoreAd() function to compute some form of an adjusted bid to be available to both reportResult() and, perhaps, reportWin(), instead of the original bid value computed by generateBid()? If so, does it mean that some information from derived from the generateBid()-returned ad metadata object might be made available to the event-level reporting time?

@lbdvt
Copy link
Contributor

lbdvt commented Feb 20, 2023

I agree with the two principles laid out by @appascoe :

Sellers are the ones who "own" their inventory. It is their right to determine how they are compensated for displaying an ad in that inventory.
Buyers need to control their own exchange rates so they know exactly what they are offering to show an ad. Critically, buyers may actually differ in what they think a fair exchange rate is.

So any conversion table must be owned by the DSP, which does not seem to be the case in options 3 and 4.

The interest group update mechanism can be used by buyers to update their exchange rates.

Exchange rates can have large intra-day variations, and although this is exceptional, this must be taken into account. Interest group update mechanism would not cover this.

@MarcoLugo
Copy link

From @timphsieh's message:

Buyers may need to receive invoices from sellers in local currencies in different geographical regions.

Why would this be the case? If I buy something in the US from Canada, I can expect the price to be in USD. Now, some sellers do offer to bill in CAD at an exchange rate I have no say in and I'd be free to take it or to find my own and pay in USD but most don't and that's their prerogative as by law they must accept USD. Obviously, in the case of adtech, volume may create other arrangements but as Michael said during last call, this is an issue for the industry to solve. In my opinion, this is not merely a API issue for Chrome/FLEDGE.

Per last meeting's minutes, Fabian H. mentioned that his understanding is that it is a financial requirement to invoice in Euro if the market is in Euro. I have not had the chance to follow up with Fabian on the meaning of market is in Euro but if I understand it correctly this position is not necessarily contradictory with my own above. Customarily, a seller must accept the currency of where it is legally based, this is similar to the concept of legal tender in most cases. So if I open up a shop in Canada and I have a customer from the European Union I will be selling in CAD and it would be up to the buyer to arrange payment. If one day my shop grew and I decided to open a location in Paris and a buyer came into the shop in Paris then yes, I would be legally required to take EUR as payment. In other words, it's the legal location of the seller that determines the currency that must be accepted, not that of the buyer. That being said, nothing precludes the seller from accepting other currencies and it may even be a competitive advantage or an arrangement done for big/loyal customers.

Buyers may want to place in-browser bids in the same currency as the billing currency to avoid the currency conversion risk.

This comment supposes that the seller does bill in other currencies and the goal here is to avoid currency conversion risk.

I would argue that the means to achieve the goal are not effective. Unless the transaction itself is in real-time, there will always be currency conversion risk. The only question is who will bear this risk, the seller or the buyer? There may be many thousands or even millions of transactions with minimal amounts of money so it makes sense to do something like bill once per month. Let's see two options:

  • The US seller accepts EUR payments: say a bill of $1M EUR accrued over the month, then at the end of the month the seller will take $1M EUR from the buyer and then they will have to convert it back to USD. The seller will convert the money into USD and either gain or lose due to currency fluctuation.
  • The EU buyer pays in USD: say a bill of $1M USD accrued over the month, then at the end of the month the buyer will take whatever amount of EUR makes $1M USD to pay and thus either lose or gain due to currency fluctuation.

I mention one month but as Lionel points out above, large intra-day swings can also be important and this can happen several times a month, usually during economic announcements (interest rate decisions by central banks and unemployment announcements come to mind but there are also geopolitical shocks and other market movers, particularly when liquidity is low).

There are proper ways of managing and mitigating currency conversion risk. The simplest of them all would be if you anticipate to need $1M of a foreign currency a month from now, you buy some of it or all of it up front to lock in the exchange rate and then incur in some interest rate risk which presumably would be much lower given it's only a month. There are more sophisticated methods (see currency hedging in general) but I don't think putting a field for the currency in the API would be a solution. It would just transfer the risk to another party.

As Andrew pointed out, there is no single exchange rate. You can call five financial institutions simultaneously and you may get five different quotes for EUR/USD. These quotes can also depend on how much money you are exchanging and other factors.

I favour the option where the seller determines the currency(ies) they sell in while complying with all applicable regulations. Perhaps some sellers will only accept their own currency, others would accept a subset of major currencies plus their own, others could accept certain currencies if the guaranteed volume from the buyer is above a certain threshold, etc. but that's not up to us, what matters is that we do not preclude these arrangements from happening but that we enable them.

As a side note, if we somehow ended up having a price and currency per bid, I am no accountant but I can only begin to imagine the headache for everyone that a financial/accounting audit would impose and all the logging requirements that may be required as well.

@timphsieh-google
Copy link

Why would this be the case? If I buy something in the US from Canada, I can expect the price to be in USD....

The context of this requirement is that the seller may have traffic from multiple regions. However, the buyer might locate in and interested in traffic from only one of the regions. The buyer would need to let the seller know which region the buyer is in.

@JensenPaul to make Option 4 work, will we need to make the following changes to the FLEDGE API:

  • Seller’s scoreAd()’s return value will include a new bidInSellerCurrency.
  • The browser will populate browserSignals.highestScoringOtherBid using bidInSellerCurrency. Both the seller and the buyer will know that highestScoringOtherBid is in the seller’s currency.
  • The browser could add a new field browserSignals.bidInSellerCurrency to reportWin() and reportResult(). Alternatively, the browser could replace the current browserSignals.bid with browserSignals.bidInSellerCurrency.

@appascoe
Copy link
Collaborator

The context of this requirement is that the seller may have traffic from multiple regions. However, the buyer might locate in and interested in traffic from only one of the regions. The buyer would need to let the seller know which region the buyer is in.

The buyer declaring a region seems orthogonal to me from dealing with currency and fluctuating exchange rates. As noted above, buyers are not in a position to demand a seller take a particular currency, even if that's the buyer's local currency.

I'm also confused by this notion of a seller having traffic from multiple regions. The FLEDGE bidding mechanism starts with the browser being added to an interest group on an advertiser's page. Nominally, wouldn't it be on the advertiser to pack in geolocation information into this interest group while the user is on the advertiser's site? If the user is outside of the buyer's desired region of operation, they could simply not add the user to an interest group. Could you please clarify what you mean here?

(Note: On the contextual request side of FLEDGE, this operates very similarly to the current market today; I don't see any particular reason to alter the way this works, where the seller declares the currency. Moreover, as discussed in last week's meeting, it's a separate discussion on whether contextual bids should be part of the scoreAd() function through the interest group mechanism.)

@piwanczak
Copy link

From our perspective option 4 mentioned by @JensenPaul seems plausible - also due to it's similarity to how nowadays RTB works

@timphsieh-google
Copy link

timphsieh-google commented Mar 4, 2023

I'm also confused by this notion of a seller having traffic from multiple regions.

As an example, a seller may have a presence in both the US and Europe. The seller may work with 2 buyers. One of the buyers is located in the US and only interested in users from the US. On the other hand, the other buyer is located in Europe and only interested in users from Europe. To make billing more convenient and satisfy the local regulations, the seller could bill the buyers in their local regions.

I believe that the current FLEDGE API already allows the buyer to indicate a preferred in-browser currency during the contextual request (See “Without changing FLEDGE API: Choose currency during contextual response” in the comment). My understanding is that the feature gap is that highestScoringOtherBid will have ambiguous currency when the seller supports multiple currencies. To clarify the proposal from my last comment:

  • In seller’s scoreAd(), the seller converts the buyer’s bid into a seller-defined currency and returns it in a new value as bidInSellerCurrency.
  • In seller’s reportResult() and buyer’s reportWin(),
    • browsersignals.bid will be populated using generateBid()’s returned bid. In other words, browsersignals.bid will be in buyer-preferred currency.
    • browserSignals.highestScoringOtherBid will be populated using scoreAd()’s returned bidInSellerCurrency. In other words, browserSignals.highestScoringOtherBid will be in seller-defined currency.
  • In reportLoss(), both the winning bid and the highestScoringOtherBid can be in seller-defined currency.

@JensenPaul
Copy link
Collaborator

All the discussion on this issue and in the WICG FLEDGE call have taught me a lot about the different ways multiple currencies can be handled. I think the browser’s job is to support the different ways while protecting the user’s privacy. At the end of the day, FLEDGE auctions must compare the bids to decide the winning bid, so we need ways to communicate the currencies of bids when they’re placed and when they’re reported. I see two distinct ways to chose and convey the currencies, and two ways the FLEDGE API can support them:

When sellers chose currencies of bids: In this case I believe my “Option 3” above addresses the need. auctionSignals or some other part of the auction configuration can convey the currency to bidders and sellers when bids are placed and when reports are sent.

When buyers chose currencies of bids: In this case I believe my “Option 4” above addresses the need. Buyers can convey the currency of their bids via contextual communication before the FLEDGE auction (e.g. a buyer telling a seller that all their bids in geo X will be in currency Y) or in the ad metadata field during the FLEDGE auction. scoreAd converts the bid price to a single currency so that post-auction signals like

are all in a known currency that doesn’t depend on auction specific information like who the winning bidder is. @timphsieh, I think your formalization of my “Option 4” is roughly accurate.

@michaelkleber
Copy link
Collaborator

Thanks everyone — I'm happy that we seem to have nearly agreed on a plan in which everyone knows what currency every value is in, without any new channel for leakage of private information.

The only bit I think needs modification is the part where @JensenPaul wrote that buyers had the option to "convey the currency of their bids[...] in the ad metadata field during the FLEDGE auction". We can't let that propagate from generateBid() to reportWin(), as discussed above. Instead I think we should just require that the buyer and seller agree on the bid currency based on purely contextual data — that is, that all the currencies could be specified in the auction config, and are known independent of what IGs happen to bid. As Paul said, currencies are chosen "via contextual communication before the FLEDGE auction", if they vary at all.

As @vincent-grosbois and @lbdvt have both pointed out, though, this system still has the risk of people accidentally interpreting a price as being in a different currency than was intended. As the Criteo folks expressed it recently, we should try to make this a "type-safe system".

@timphsieh already suggested the natural answer in Option 1 above: Including the currency alongside the bid value, every time a monetary value is passed around. We weren't able to accept this suggestion while the bid currency was a dynamic choice, because that was a privacy leakage. But in the modified Option 4 world, the choice of currency is always known ahead of time. That means there is no information leakage in passing currencies around. And to ensure that that's the case, we should (i) have the expected currencies defined in the auction config in a way that the browser understands, and (ii) make the browser check to be sure that each declared currency really is what the auction config said it should be.

To make this work, we would need something like the following:

  • In the auction config, we have a list of currencies: 'sellerCurrency':'eur' and 'perBuyerCurrencies': {'https://www.example-dsp.com': 'jpy', 'https://www.another-buyer.com': 'usd', '*': 'eur'}

  • Each representation of money has both a value and a currency: Instead of generateBid return value including 'bid': 3.14, it should include 'bid': {'value': 3.14, 'currency':'jpy'}. Or we could keep 'bid': 3.14 and add 'bidCurrency': 'jpy' as Tim did, but tying them tightly together seems more in line with the rest of the safety goals here.

  • The browser makes sure that every time a function emits a monetary value, its currency is what the auction config said it would be. If generateBid tries to bid in the wrong currency, it's an error, and the IG does not participate in the auction. (We'll need to add a new currency mismatch error to the enum of reasons a group didn't win.)

There is a little sticking point of how to migrate — making the new currency field required is not backwards compatible. But if we all like the destination, I'm sure we can figure out how to get there.

@dmdabbs
Copy link
Contributor

dmdabbs commented Mar 18, 2023

Destination sounds good. Will it also make change?

@morlovich
Copy link
Collaborator

A few additional thoughts:

  1. For migration, if something doesn't specify a currency, default to '???'. An unspecified value for perBuyerCurrencies gets interpreted as {'*': '???'}; with the idea of removing the default value eventually (which may be its own pain...). Same about sellerCurrency.
  2. Do we need to support promises for perBuyerCurrencies?

@michaelkleber
Copy link
Collaborator

@dmdabbs I contend there are better choices, especially if we want a theme song.

@morlovich Agreed that the way to migrate is to allow currency-or-'???' as an intermediary step (leaking one additional bit of information temporarily). Note that we ought to be sure we can handle buyers and sellers switching over in either order.

I suspect that we should support promises, since there may be server-side business logic (at contextual-request time) in deciding which currency some buyer wants to bid with in this auction.

@dmdabbs
Copy link
Contributor

dmdabbs commented Mar 20, 2023

Theme song and Eric Idle & Python for the win, @michaelkleber!

@lbdvt
Copy link
Contributor

lbdvt commented Mar 22, 2023

Thanks, @michaelkleber for the proposal in FLEDGE: currency of the bid · Issue #166 · WICG/turtledove , it looks good.

Could you please clarify the use of sellerCurrency?

Also, as mentioned by @timphsieh in a earlier comment FLEDGE: currency of the bid · Issue #166 · WICG/turtledove , during the seller’s reportResult() and buyer’s reportWin(), browserSignals should include currency for both bid and highestScoringOtherBid.
It should, I think, be the winning buyer currency for both, which is the agreed-upon currency between the buyer and seller, defined in perBuyerCurrencies.

@morlovich
Copy link
Collaborator

So I interpreted (and implemented) sellerCurrency as restricting what scoreAd in a component auction returns when it's producing a modified bid (bidInSellerCurrency will do that too, once I get back to that). It does get a little awkward since the top-level auction also has perBuyerCurrencies, so there are actually 2 checks happening.

aarongable pushed a commit to chromium/chromium that referenced this issue Apr 3, 2023
This let auction configuration state which currencies they expect each buyer to use, and buyers to state which ones they are using, so if they disagree on what currencies they use they get an error rather than a financial disagreement.

For transition reasons, the checking only happens if both specify currencies.

This CL does not cover the reporting phase, which will be in follow up CL, along with requested features involving how seller currency conversion interacts with reporting, due to size.

Context for this work is WICG/turtledove#166

Change-Id: I366f9021598bc2dd35b21abec809464c115f257d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4354633
Reviewed-by: Daniel Cheng <[email protected]>
Commit-Queue: Maks Orlovich <[email protected]>
Reviewed-by: Russ Hamilton <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1125366}
@morlovich
Copy link
Collaborator

So basic currency checking is in as of canary 114.0.5694.0.

The rules I am thinking of for bidInSellerCurrency are:

  1. If auctionConfig.sellerCurrency is not set, then everything is in bidder currency. highestScoringOtherBidCurrency is always '???'
  2. If auctionConfig.sellerCurrency is set:
    1. If madeHighestScoringOtherBid is true, it gets highestScoringOtherBid in its original, currency annotation is '???'
    2. IfmadeHighestScoringOtherBid is false, and highestScoringOtherBid is either missing/0 or in seller currency; with the value provided by bidder if its bid was in the seller currency in the first place, or seller if it wasn't. Currency annotation is auctionConfig.sellerCurrency

aarongable pushed a commit to chromium/chromium that referenced this issue Apr 24, 2023
For component auctions, each component + its buyers use the component's sellerCurrency, while the top-level sellerCurrency is used by it alone.

This also fixes a few cases where we incorrectly provided highestScoringOtherBid for a top-level seller with component sellers.

Context for this work is WICG/turtledove#166


Change-Id: I45347eeadeb44300f68879f536bcb06439067797
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4450587
Code-Coverage: Findit <[email protected]>
Commit-Queue: Maks Orlovich <[email protected]>
Reviewed-by: Russ Hamilton <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1134798}
aarongable pushed a commit to chromium/chromium that referenced this issue Apr 25, 2023
When a component auction has seller currency restricted we were checking bids it modified against the requirement, but not those it just passed through to top-level auction.
(Credit to Russ for spotting this bug).

Context for this work is WICG/turtledove#166


Change-Id: I663b9f0e22ac2c5252d922fc6f7faf4c405d183c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4468969
Code-Coverage: Findit <[email protected]>
Reviewed-by: Caleb Raitto <[email protected]>
Commit-Queue: Maks Orlovich <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1135501}
@morlovich
Copy link
Collaborator

Pull request for explainer:
#571
(Everything here should be in M114, except the reject-reason which is in code review, and targetted for M115)

aarongable pushed a commit to chromium/chromium that referenced this issue May 11, 2023
This required making it possible for the bidder worklet to specify the reject reason, not just the seller worklet, since it's what checks the generateBid currency.

See WICG/turtledove#166

(This also does it for scoreAd in component auctions)

Change-Id: Id521e62fbd96819b559b4871d6544a20e2a71e71
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4492732
Reviewed-by: Qingxin Wu <[email protected]>
Commit-Queue: Maks Orlovich <[email protected]>
Reviewed-by: Daniel Cheng <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1142879}
aarongable pushed a commit to chromium/chromium that referenced this issue May 31, 2023
We got feedback that it would be preferred, and none of the reason for things to be in seller currency apply (and the bidder can do conversion if it wants to).

The accompanied tag is again based on config, for similar redaction reasons, like in reportWin.

(This is tracked in WICG/turtledove#166)

Change-Id: I733cdcd0ec47dd7166f08ea82e43d8aea2025da2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4573913
Reviewed-by: Russ Hamilton <[email protected]>
Commit-Queue: Maks Orlovich <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1151414}
@morlovich
Copy link
Collaborator

Note that the last change is change in behavior of reportResult arguments when sellerCurrency is on, so you may want to be extra-careful around that.

@JensenPaul
Copy link
Collaborator

I'm closing this issue as currency support is added to the explainer in #571 and to the spec in #594. Feel free to reopen or file another issue if additional concerns exist.

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