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

Priority vector re-prioritization proposal #329

Merged
merged 28 commits into from
Nov 11, 2022
Merged
Changes from 8 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
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
76 changes: 68 additions & 8 deletions FLEDGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ We plan to hold regular meetings under the auspices of the WICG to go through th
- [3.2 On-Device Bidding](#32-on-device-bidding)
- [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 Prioritizing Interest Groups](#35-prioritizing-interest-groups)
MattMenke2 marked this conversation as resolved.
Show resolved Hide resolved
- [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)
Expand Down Expand Up @@ -88,6 +89,17 @@ const myGroup = {
'owner': 'https://www.example-dsp.com',
'name': 'womens-running-shoes',
'priority': 0.0,
'priorityVector': {
'signal1': 2,
'signal2': -3.5,
...
}
'prioritySignalsOverrides': {
'signal1': 4.5,
'signal2': 0,
...
}
`enableBiddingSignalsPrioritization` : [true | false],
MattMenke2 marked this conversation as resolved.
Show resolved Hide resolved
'biddingLogicUrl': ...,
'biddingWasmHelperUrl': ...,
'dailyUpdateUrl': ...,
Expand All @@ -114,11 +126,13 @@ The browser will remain in an interest group for only a limited amount of time.

The `priority` is used to select which interest groups participate in an auction when the number of interest groups are limited by the `perBuyerGroupLimits` attribute of the auction config. If not specified, a `priority` of `0.0` is assigned. There is no special meaning to these values. These values are only used to select interest groups to participate in an auction such that if there is an interest group participating in the auction with priority `x`, all interest groups with the same owner having a priority `y` where `y > x` should also participate (i.e. `generateBid` will be called). In the case where some but not all interest groups with equal priority can participate in an auction due to `perBuyerGroupLimits`, the participating interest groups will be uniformly randomly chosen from the set of interest groups with that priority.

`priorityVector`, `prioritySignalsOverrides`, and `enableBiddingSignalsPrioritization` are optional values used to dymnically calculate a priority used in place of `priority`. `priorityVector` and `prioritySignalsOverrides` are mappings of strings to Javscript numbers, while enableBiddingSignalsPrioritization is a bool that defaults to `false`. See [Prioritizing Interest Groups](#35-prioritizing-interest-groups) for a description of how these fields are used.
MattMenke2 marked this conversation as resolved.
Show resolved Hide resolved

The `userBiddingSignals` is for storage of additional metadata that the owner can use during on-device bidding, and the `trustedBiddingSignals` attributes provide another mechanism for making real-time data available for use at bidding time.

The `biddingWasmHelperUrl` field is optional, and lets the bidder provide computationally-expensive subroutines in WebAssembly, rather than JavaScript, to be driven from the JavaScript function provided by `biddingLogicUrl`. If provided, it must point to a WebAssembly binary, delivered with an `application/wasm` mimetype. The corresponding `WebAssembly.Module` will be made available by the browser to the `generateBid` function.

The `dailyUpdateUrl` provides a mechanism for the group's owner to periodically update the attributes of the interest group: any new values returned in this way overwrite the values previously stored (except that the `name` and `owner` cannot be changed). However, the browser will only allow daily updates when a sufficiently large number of people have the same `dailyUpdateUrl` , e.g. at least 100 browsers with the same update URL. This will not include any metadata, so data such as the interest group `name` should be included within the URL, so long as the URL exceeds the minimum count threshold. (Without this sort of limit, a single-person interest group could be used to observe that person's coarse-grained IP-Geo location over time.)
The `dailyUpdateUrl` provides a mechanism for the group's owner to periodically update the attributes of the interest group: any new values returned in this way overwrite the values previously stored (except that the `name` and `owner` cannot be changed, and `perBrowserSignalsOverrides` will be merged with the previous value, with `null` meaning a value should be removed from the interest group's old dictionary). However, the browser will only allow daily updates when a sufficiently large number of people have the same `dailyUpdateUrl` , e.g. at least 100 browsers with the same update URL. This will not include any metadata, so data such as the interest group `name` should be included within the URL, so long as the URL exceeds the minimum count threshold. (Without this sort of limit, a single-person interest group could be used to observe that person's coarse-grained IP-Geo location over time.)
MattMenke2 marked this conversation as resolved.
Show resolved Hide resolved

The `ads` list contains the various ads that the interest group might show. Each entry is an object that includes both a rendering URL and arbitrary metadata that can be used at bidding time.

Expand Down Expand Up @@ -180,9 +194,15 @@ const myAuctionConfig = {
'*': 150,
...},
'perBuyerGroupLimits': {'https://www.example-dsp.com': 2,
'https://www.another-buyer.com': 1000,
'*': 15,
...},
'https://www.another-buyer.com': 1000,
'*': 15,
...},
'perBuyerPrioritySignals': {'https://www.example-dsp.com': {'signal1': 2.5,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering, perhaps perBuyerPrioritySignals could be a field within perBuyerSignals['https://www.example-dsp.com']? That way, the protocol between the seller and the buyer wouldn't have to be updated to handle the priority signals. We'd also lose the natural support for the default (wildcard) priority signals (but currently, unless I'm missing something, I don't see a good use for them).

Copy link
Contributor Author

@MattMenke2 MattMenke2 Aug 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit concerned about overloading fields (field A is both data sent directly to buyer scripts, and data used to run these filters). Seems like there's a lot of room for unexpected behaviors there. If someone, for instance, is using a field we suddenly decide has another meaning, we'd be breaking consumers.

If we want to include with in perBuyerSignals, I'd be more comfortable structuring perBuyerSignals as:

{
  arbitraryJsonData: <...>
  prioritySignals: {...}
}

And dropping everything that's not in one of those two values, to minimize the chance of confusion. That would, of course, be a breaking change, but so would trying to extract priority signals from perBuyerSignals without the format change.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was some related discussion on this here:
#266 (comment)

The direction discussed was leaving perBuyerSignals alone, letting it contain arbitrary buyer json, but introducing a new perBuyerConfigurations field that would contain the various buyer-specific fields that FLEDGE needs to handle, e.g. prioritySignal, experimentGroupId, perBuyerGroupLimits, and potentially interestGroupBuyers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a very different proposal - at least I assume jonasz's suggestion was so that the signals would be passed to worklets, as opposed to be a suggestion on how to better organize fields.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, my read of

That way, the protocol between the seller and the buyer wouldn't have to be updated to handle the priority signals

was

"sellers can avoid redeploying code every time FLEDGE adds a new per-buyer field if the per-buyer fields are consolidated"

I don't see that a perBuyerConfigurations map clashes with making the signals available to worklets -- actually I'd think it desirable to make perBuyerConfigurations available to the worklet so that things like experimentGroupId and prioritySignals don't have to be redundantly passed through perBuyerSignals if they're needed by the worklet.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a very different proposal - at least I assume jonasz's suggestion was so that the signals would be passed to worklets, as opposed to be a suggestion on how to better organize fields.

My proposal was actually purely technical, as @jrmooring summarized.

I agree that if there are other use cases where the buyer needs to pass some configuration to the auction, something like perBuyerConfigurations would be nice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect we're going to switch to something along the lines of perBuyerConfigurations when we end the Fledge field trial and feel we can more safely break backwards compatibility. We could also switch to passing in the entire configuration to bidder worklets at the same time.

'signal2': 2.5,
...},
'https://www.another-buyer.com': {...},
'*': {...},
...},
'componentAuctions': [
{'seller': 'https://www.some-other-ssp.com',
'decisionLogicUrl': ...,
Expand All @@ -204,6 +224,8 @@ Optionally, `sellerTimeout` can be specified to restrict the runtime (in millise

Optionally, `perBuyerGroupLimits` can be specified to limit the number of of interest groups from a particular buyer that participate in the auction. A key of `'*'` in `perBuyerGroupLimits` is used to set a limit for unspecified buyers. For each buyer, interest groups will be selected to participate in the auction in order of decreasing `priority` (larger priorities are selected first) up to the specfied limit. The selection of interest groups occurs independently for each buyer, so the priorities do not need to be comparable between buyers and could have a buyer-specific meaning. The value of the limits provided should be able to be represented by a 16 bit unsigned integer.

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 [Prioritizing Interest Groups](#35-prioritizing-interest-groups) for more information.
MattMenke2 marked this conversation as resolved.
Show resolved Hide resolved

All fields that accept arbitrary metadata objects (`auctionSignals`, `sellerSignals`, and keys of `perBuyerSignals`) must be JSON-serializable.

A `Permissions-Policy` directive named "run-ad-auction" controls access to the `navigator.runAdAuction()` API.
Expand Down Expand Up @@ -302,23 +324,34 @@ Buyers have three basic jobs in the on-device ad auction:

Buyers may want to make on-device decisions that take into account real-time data (for example, the remaining budget of an ad campaign). This need can be met using the interest group's `trustedBiddingSignalsUrl` and `trustedBiddingSignalsKeys` fields. 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
https://www.kv-server.example/getvalues?hostname=publisher.com&keys=key1,key2&interestGroups=name1,name2
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This way of sending data loses the association between keys and Interest Group (IG) names. For example, we might have IG 1 with key 'key1' and IG2 with keys ['key2', 'key3'].

This may become awkward and limiting for usage on the trusted server in the future. For example, it may often be the case that computing the bidding signals corresponding to some key may overlap with computing the perInterestGroupData for the corresponding IG.

Can we have an API that preserves the relationship between keys and IG names? For example, we could require keys and to be in the same order as IG names, with keys from different IGs separated by semicolons instead of commas.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The does potentially make requests bigger, since we need to duplicate keys from multiple IGs. It would also require significant changes to the trusted server code. Are you thinking in terms of things that might be useful down the line, or that would be useful now, with the single perInterestGroupData field?

I'd hope that if something depends on key, it would be something that could be applied to all IGs with the same key, though that may be wishful thinking.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least with our usage, preserving the association means that we could make the request significantly smaller. If we cannot rely on the IG name->key association being available, the IG name potentially needs to be passed twice once as part of the key and once in the interestGroups field. There are ways one could imagine using the API where one would have many duplicate keys across IGs, but I am not sure if anyone uses the API in that way. (As far as I can tell those designs typically involve moving more computation onto the client, with corresponding latency and data integrity concerns.)

Another related issue, supposing we wish to filter out the IG with negative priority with this API, we would also prefer to return empty bidding signal responses for the corresponding key(s). This either involves looking up a key to IG mapping on the server, duplicating data in the key, or doing redundant computations on the trusted server.

Whether or not all of this will be possible likely depends on details of the trusted server model, but I think it is desirable to keep the options open by preserving the information.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least with our usage, preserving the association means that we could make the request significantly smaller. If we cannot rely on the IG name->key association being available, the IG name potentially needs to be passed twice once as part of the key and once in the interestGroups field. There are ways one could imagine using the API where one would have many duplicate keys across IGs, but I am not sure if anyone uses the API in that way. (As far as I can tell those designs typically involve moving more computation onto the client, with corresponding latency and data integrity concerns.)

Another related issue, supposing we wish to filter out the IG with negative priority with this API, we would also prefer to return empty bidding signal responses for the corresponding key(s). This either involves looking up a key to IG mapping on the server, duplicating data in the key, or doing redundant computations on the trusted server.

Whether or not all of this will be possible likely depends on details of the trusted server model, but I think it is desirable to keep the options open by preserving the information.

Seems like for your use case, it would make more sense to make unique keys for each IG, rather than shared keys between IGs. One of the reasons to use keys, instead of just IG name, is so that IGs can share data.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like for your use case, it would make more sense to make unique keys for each IG, rather than shared keys between IGs. One of the reasons to use keys, instead of just IG name, is so that IGs can share data.

Yes, indeed that is how we are using the API. Please see my original concern about losing the association:

This may become awkward and limiting for usage on the trusted server in the future. For example, it may often be the case that computing the bidding signals corresponding to some key may overlap with computing the perInterestGroupData for the corresponding IG.

If we lose the association then this effectively limits the future ability of the trusted bidding server to use the interestGroupNames in computing the key response, or sharing computation between the two different outputs.


The base URL `https://www.kv-server.example/getvalues` comes from the interest group's `trustedBiddingSignalsUrl`, the hostname of the top-level webpage where the ad will appear `publisher.com` is provided by the browser, and `keys` is a list of `trustedBiddingSignalsKeys` strings. The requests may be coalesced (for efficiency) across any number of interest groups that share a `trustedBiddingSignalsUrl` (which means they also share an owner).
The base URL `https://www.kv-server.example/getvalues` comes from the interest group's `trustedBiddingSignalsUrl`, the hostname of the top-level webpage where the ad will appear `publisher.com` is provided by the browser, `keys` is a list of `trustedBiddingSignalsKeys` strings, and interestGroupNames is a list of the names of interest groups data is being fetched for. The requests may be coalesced (for efficiency) across any number of interest groups that share a `trustedBiddingSignalsUrl` (which means they also share an owner).
MattMenke2 marked this conversation as resolved.
Show resolved Hide resolved

The response from the server should be a JSON object of the form:

```
{ 'keys': {
'key1': arbitrary_json,
'key2': arbitrary_json,
...}
...},
'perInterestGroupData': {
'name1': {
'priorityVector': {
'signal1': number,
'signal2': number,
...}
},
...
}
}
```

and the server must include the HTTP response header `X-fledge-bidding-signals-format-version: 2`. If the server does not include the header, the response will assumed to be an in older format, where the response is only the contents of the `keys` dictionary.

The value of each key that an interest group has in its `trustedBiddingSignalsKeys` list will be passed to the interest group's generateBid() function as the `trustedBiddingSignals` parameter. Values missing from the JSON object will be set to null. If the JSON download fails, or there are no `trustedBiddingSignalsKeys` or `trustedBiddingSignalsUrl` in the interest group, then the `trustedBiddingSignals` argument to generateBid() will be null.
The value of each key that an interest group has in its `trustedBiddingSignalsKeys` list will be passed from the `keys` dictionary to the interest group's generateBid() function as the `trustedBiddingSignals` parameter. Values missing from the JSON object will be set to null. If the JSON download fails, or there are no `trustedBiddingSignalsKeys` or `trustedBiddingSignalsUrl` in the interest group, then the `trustedBiddingSignals` argument to generateBid() will be null.

The `perInterestGroupData` dictionary contains optional data for interest groups whose names were included in the request URL. The `priorityVector` will be used as the priority for an interest group, if that interest group has `enableBiddingSignalsPrioritization` set to `true` in its definition. See [Prioritizing Interest Groups](#35-prioritizing-interest-groups) for more information.

Similarly, sellers may want to fetch information about a specific creative, e.g. the results of some out-of-band ad scanning system. This works in much the same way, with the base URL coming from the `trustedScoringSignalsUrl` property of the seller's auction configuration object. However, it has two sets of keys: "renderUrls=url1,url2,..." and "adComponentRenderUrls=url1,url2,..." for the main and adComponent renderUrls bids offered in the auction. It is up to the client how and whether to aggregate the fetches with the URLs of multiple bidders. The response to this request should be in the form:

Expand Down Expand Up @@ -376,6 +409,7 @@ The arguments to `generateBid()` are:


* interestGroup: The interest group object, as saved during `joinAdInterestGroup()` and perhaps updated via the `dailyUpdateUrl`.
* `priority` and `prioritySignalsOverrides` are not included. They can be modified by generatedBid() calls, so could theoretically be used to create a cross-site profile of a user accessible to generateBid() methods, otherwise.
MattMenke2 marked this conversation as resolved.
Show resolved Hide resolved
* auctionSignals: As provided by the seller in the call to `runAdAuction()`. This is the opportunity for the seller to provide information about the page context (ad size, publisher ID, etc), the type of auction (first-price vs second-price), and so on.
* perBuyerSignals: The value for _this specific buyer_ as taken from the auction config passed to `runAdAuction()`. This can include contextual signals about the page that come from the buyer's server, if the seller is an SSP which performs a real-time bidding call to buyer servers and pipes the response back, or if the publisher page contacts the buyer's server directly. If so, the buyer may wish to check a cryptographic signature of those signals inside `generateBid()` as protection against tampering.
* trustedBiddingSignals: An object whose keys are the `trustedBiddingSignalsKeys` for the interest group, and whose values are those returned in the `trustedBiddingSignals` request.
Expand All @@ -402,6 +436,8 @@ The output of `generateBid()` contains the following fields:
* 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.
* 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.

`generateBid()` has access to the setPrioritySignalsOverride(key, value) method. This adds an entry to the current interest group's prioritySignalsOverrides dictionary with the specified `key` and `value`, overwriting the previous value, if there was already an entry with `key`. If `value` is null, the entry with the specified key is deleted, if it exists.
MattMenke2 marked this conversation as resolved.
Show resolved Hide resolved


#### 3.3 Metadata with the Ad Bid

Expand All @@ -419,6 +455,30 @@ The [Product-level TURTLEDOVE](https://github.com/WICG/turtledove/blob/master/PR
The output of `generateBid()` can use the on-device ad composition flow through an optional adComponents field, listing additional URLs made available to the fenced frame the container URL is loaded in. The component URLs may be retrieved by calling `navigator.adAuctionComponents(numComponents)`, where numComponents is at most 20. To prevent bidder worklets from using this as a sidechannel to leak additional data to the fenced frame, exactly numComponents obfuscated URLs will be returned by this method, regardless of how many adComponent URLs were actually in the bid, even if the bid contained no adComponents, and the Interest Group itself had no adComponents either.


#### 3.5 Prioritizing Interest Groups

When an interest group has a non-empty `priorityVector`, its priority is dynically calculted before applying `perBuyerGroupLimits`. To do this, the sparse dot product of interest group's `priorityVector` is multiplied by a `prioritySignals` vector. The `prioritySignals` vector is the result of merging the following objects, which all have strings as keys and numbers as values, with entry in objects earlier in the list taking priority over entries later in the list:
MattMenke2 marked this conversation as resolved.
Show resolved Hide resolved

* The interest group's `prioritySignalsOverrides` field.
* A browser-generated `prioritySignals` object, defined below.
* The `auctionConfig`'s `perBuyerPrioritySignals` entry for the interest group owner.
* The `auctionConfig`'s `perBuyerPrioritySignals` "\*" entry.

Additionally, keys starting with "browserSignals." are reserved, and may only appear in `prioritySignalsOverrides` and the browser-generated `prioritySignals` object.

The browser-generated `prioritySignals` object contains the following values:
* `browserSignals.one`: This is always 1. It's useful for adding a constant to the dot product.
* `browserSignals.age`: How long ago the user was added to the interest group, in milliseconds. This is the most recent time the use was added to the injterest group, so re-joining an interest group resets the value. This value is always non-negative.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Age in msec seems like way more granularity than is warranted here.
  2. I think we might need a better way to handle age, actually. The use case we've heard about is owners who want their IG priority to drop off over time. The linear nature of a dot product means that if your priority on the second day is half of what it was on the first day, then your priority on day 3 is 0 and on day 4 is negative. Maybe it would be more useful for us to offer multiple capped values, like browserSignals.ageInHoursMax24 and browserSignals.ageInDaysMax30?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

browserSignals.ageinHoursMax24, ageInDaysMax30 sound very useful. If possible, I'd also add ageInMinutesMax60. Adding browserSignals.logAge, as proposed by Matt in #305 could also be useful.

Copy link
Contributor Author

@MattMenke2 MattMenke2 Aug 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree milliseconds is more granularity than people need, but I'm reluctant to declare only days are useful, or only hours are, or whatnot, though I think sub minute granulatity does seem very unlikely to ever be useful.

It wouldn't be hard to support [Log]AgeIn[Hours|Days|Minutes][Max#], though that might be making things too complicated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would also mean it's no longer a simple vector multiplication - we'd have to check for certain patterns, which would make things a bit more complicated on implementers, I suppose.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would also mean it's no longer a simple vector multiplication - we'd have to check for certain patterns (...)

Not sure if I got that right, could you explain what patterns do you have in mind?

// In my mind, it seemed it would be sufficient if there's a couple new age-related variables supplied by the browser in browserSignals.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[jonasz]: I was referring to my specific suggestion of adding more flexible options.

Wonder how useful the various resolutions are (minutes, hours, days), but I guess providing those three combined gets you a full clock, up to the expiration time.

So we're thinking: ageInMinutes, ageInMinutesMax60, ageInHoursMax24, ageInDaysMax30?

Sorry for the slow follow up. Been busy implementing the rest of this proposal, and only now getting back to figuring out what to do about age.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the PR to include the requested fields. Feedback welcome!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Experience from DSPs is that recency needs a lot more resolution than expected right after a signal has been given. For example of all users that add something to a shopping cart and click on an ad before completing the purchase, 80% of them will have done so within 3-4 days, and of those the majority within the first few hours and day.

So while milliseconds may seem too much, these pipelines are usually tuned to the second/minute.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@michaelkleber, @jonasz: Thoughts? Note that the values here are not really accessible by scripts or auctions . You could theoretically keep on modifying the filter and running auctions to try and get the time an IG was added, but there are easier and less finicky ways to probe IGs by using large numbers of auctions, as long as we expose whether any IG won the auction and if so, how long it took. We could just always provide second/minute resolution, if folks find it useful, and I don't think there would be a significant loss in privacy.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, there's no significant privacy implications here, it's just about providing values that are useful for the dot-product mechanism. If ageInSecondsMax600 or whatever is also useful, then sure go for it, I'd say.

MattMenke2 marked this conversation as resolved.
Show resolved Hide resolved
* `browserSignals.basePriority`: The priority field in the interest group, which may have been modified by a setPriority() call.
MattMenke2 marked this conversation as resolved.
Show resolved Hide resolved
* `browserSignals.firstDotProductPriority`: The priority from multiplying the interest group's `priorityVector` by `prioritySignals`. Only non-zero when using a `proirityVector` from a trusted bidding signals fetch, and the interest group also has a `prioritySignals` field. See below for more details.
MattMenke2 marked this conversation as resolved.
Show resolved Hide resolved

If the resulting dot-product is negative, the interest group is immediately removed from an auction (Note that if there's no `priorityVector`, interest groups with negative values currently are not filtered from auctions). After calculting new priorities, as needed, and filtering out interest groups with negative calculated priorities, the `perBuyerGroupLimits` value is applied to all interest groups of a given order, unless the interest group's `enableBiddingSignalsPrioritization` field is present and true.
MattMenke2 marked this conversation as resolved.
Show resolved Hide resolved

If `enableBiddingSignalsPrioritization` is `true`, then rather than applying `perBuyerGroupLimits` immediately after the the calculating the sparse dot product as desribed above (if `priorityVector` is non-null), then instead, group limit enforcement is delayed until after fetching the trusted bidding signals. In this case, if the trusted bidding signals specify a per-interest-group `priorityVector` for an interest group, the dot product of that `priorityVector` is a again taken with a `prioritySignals` vector. The `prioritySignals` vector is the same as in the first calculation, except that it may have a non-zero `browserSignals.firstDotProductPriority` value. If this dot product is negative, the interest group is removed from the auction. If there is no `priorityVector` for an interest group, the priority from earlier in the auction is used instead. Once all priorities have been calculated, then `perBuyerGroupLimits` is applied, and the auction continues as normal.

The advantage of having not using `enableBiddingSignalsPrioritization` is that interest groups can be filtered out before bidding signals are fetched, reducing network usage and server load. In auctions with large numbers of buyers auctions, some buyers may also be able to filter themselves out entirely, which could significantly improve performance.
MattMenke2 marked this conversation as resolved.
Show resolved Hide resolved


JensenPaul marked this conversation as resolved.
Show resolved Hide resolved
### 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