FLEDGE

Draft Community Group Report,

This version:
https://wicg.github.io/fledge/
Editor:
(Google)
Participate:
GitHub WICG/turtledove (new issue, open issues)
Commits:
GitHub spec.bs commits

Abstract

Provides a privacy advancing API to facilitate interest group based advertising.

Status of this document

This specification was published by the Web Platform Incubator Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.

1. Introduction

This section is non-normative

The FLEDGE API facilitates selecting an advertisement to display to a user based on a previous interaction with the advertiser or advertising network.

When a user’s interactions with an advertiser indicate an interest in something, the advertiser can ask the browser to record this interest on-device by calling navigator.joinAdInterestGroup(). Later, when a website wants to select an advertisement to show to the user, the website can call navigator.runAdAuction() to ask the browser to conduct an auction where each of these on-device recorded interests are given the chance to calculate a bid to display their advertisement.

2. Joining Interest Groups

When a user’s interactions with a website indicate that the user may have a particular interest, an advertiser or someone working on behalf of the advertiser (e.g. a demand side platform, DSP) can ask the user’s browser to record this interest on-device by calling navigator.joinAdInterestGroup(). This indicates an intent to display an advertisement relevant to this interest to this user in the future. The user agent has an interest group set, a list of interest groups in which owner / name pairs are unique.

[SecureContext]
partial interface Navigator {
  Promise<undefined> joinAdInterestGroup(AuctionAdInterestGroup group, double durationSeconds);
};

enum WorkletExecutionMode {
  "compatibility",
  "groupByOrigin",
};

dictionary AuctionAd {
  required USVString renderUrl;
  any metadata;
};

dictionary AuctionAdInterestGroup {
  required USVString owner;
  required USVString name;

  double priority = 0.0;
  boolean enableBiddingSignalsPrioritization = false;
  record<USVString, double> priorityVector;
  record<USVString, double> prioritySignalsOverrides;

  WorkletExecutionMode executionMode = "compatibility";
  USVString biddingLogicUrl;
  USVString biddingWasmHelperUrl;
  USVString dailyUpdateUrl;
  USVString trustedBiddingSignalsUrl;
  sequence<USVString> trustedBiddingSignalsKeys;
  any userBiddingSignals;
  sequence<AuctionAd> ads;
  sequence<AuctionAd> adComponents;
};

The joinAdInterestGroup(group, durationSeconds) method steps are:

  1. If this's relevant global object's associated Document is not allowed to use the "join-ad-interest-group" policy-controlled feature, then throw a "NotAllowedError" DOMException.

  2. Let interestGroup be a new interest group.

  3. Validate the given group and set interestGroup’s fields accordingly.

    1. Set interestGroup’s expiry to now plus durationSeconds.

    2. Let ownerUrl be the result of running the URL parser on group["owner"].

      1. If ownerUrl is an error, or its scheme is not "https", throw a TypeError.

      2. Set interestGroup’s owner to ownerUrl’s origin.

    3. Set interestGroup’s name to group["name"].

    4. Set interestGroup’s priority to group["priority"].

    5. Set interestGroup’s enable bidding signals prioritization to group["enableBiddingSignalsPrioritization"].

    6. If group["priorityVector"] exists, then set interestGroup’s priority vector to group["priorityVector"].

    7. If group["prioritySignalsOverrides"] exists, then set interestGroup’s priority signals overrides to group["prioritySignalsOverrides"].

    8. Set interestGroup’s execution mode to group["executionMode"].

    9. For each groupMember and interestGroupField in the following table

      Group member Interest group field
      "biddingLogicUrl" bidding url
      "biddingWasmHelperUrl" bidding wasm helper url
      "dailyUpdateUrl" daily update url
      "trustedBiddingSignalsUrl" trusted bidding signals url
      1. If group contains groupMember:

        1. Let parsedUrl be the result of running the URL parser on group[groupMember].

        2. Throw a TypeError if any of:

        3. Set interestGroup’s interestGroupField to parsedUrl.

    10. If interestGroup’s trusted bidding signals url's query is not null, then throw a TypeError.

    11. If group["trustedBiddingSignalsKeys"] exists, then set interestGroup’s trusted bidding signals keys to group["trustedBiddingSignalsKeys"].

    12. If group["userBiddingSignals"] exists:

      1. Let interestGroup’s user bidding signals be the result of serializing a JavaScript value to a JSON string, given group["userBiddingSignals"]. This can throw a TypeError.

    13. For each groupMember and interestGroupField in the following table

      Group member Interest group field
      "ads" ads
      "adComponents" ad components
      1. For each ad of group[groupMember]:

        1. Let igAd be a new interest group ad.

        2. Let renderUrl be the result of running the URL parser on ad["renderUrl"].

        3. Throw a TypeError if any of:

        4. Set igAd’s render url to renderUrl.

        5. If ad["metadata"] exists, then let igAd’s metadata be the result of serializing a JavaScript value to a JSON string, given ad["metadata"]. This can throw a TypeError.

        6. Append igAd to interestGroup’s interestGroupField.

  4. If interestGroup’s estimated size is greater than 50 KB, then throw a TypeError.

  5. Let p be a new promise.

  6. Return p and run the following steps in parallel: (TODO: Enqueue the steps to a parallel queue instead.)

    1. TODO: document .well-known fetches for cross-origin joins.

    2. If the browser is currently storing an interest group with owner and name that matches interestGroup, then remove the currently stored one.

    3. Store interestGroup in the browser’s interest group set.

    4. Queue a task to resolve p with undefined.

The estimated size of an interest group ig is the sum of:

  1. The length of the serialization of ig’s owner.

  2. The length of ig’s name.

  3. 8 bytes, which is the size of ig’s priority.

  4. The length of ig’s execution mode.

  5. 2 bytes, which is the size of ig’s enable bidding signals prioritization.

  6. If ig’s priority vector is not null, for each keyvalue of priority vector:

    1. The length of key.

    2. 8 bytes, which is the size of value.

  7. If ig’s priority signals overrides is not null, for each keyvalue of priority signals overrides:

    1. The length of key.

    2. 8 bytes, which is the size of value.

  8. The size of execution mode.

  9. The length of the serialization of ig’s bidding url, if the field is not null.

  10. The length of the serialization of ig’s bidding wasm helper url, if the field is not null.

  11. The length of the serialization of ig’s daily update url, if the field is not null.

  12. The length of the serialization of ig’s trusted bidding signals url, if the field is not null.

  13. For each key of ig’s trusted bidding signals keys:

    1. The length of key.

  14. The length of ig’s user bidding signals.

  15. If ig’s ads is not null, for each ad of it:

    1. The length of the serialization of ad’s render url.

    2. The length of ad’s metadata if the field is not null..

  16. If ig’s ad components is not null, for each ad of it:

    1. The length of the serialization of ad’s render url.

    2. The length of ad’s metadata if the field is not null.

3. Running Ad Auctions

When a website or someone working on behalf of the website (e.g. a supply side platform, SSP) wants to conduct an auction to select an advertisement to display to the user, they can call the navigator.runAdAuction() function, providing an auction configuration that tells the browser how to conduct the auction and which on-device recorded interests are allowed to bid in the auction for the chance to display their advertisement.

[SecureContext]
partial interface Navigator {
  Promise<USVString?> runAdAuction(AuctionAdConfig config);
};

dictionary AuctionAdConfig {
  required USVString seller;
  required USVString decisionLogicUrl;
  USVString trustedScoringSignalsUrl;
  sequence<USVString> interestGroupBuyers;
  any auctionSignals;
  any sellerSignals;
  USVString directFromSellerSignals;
  unsigned long long sellerTimeout;
  unsigned short sellerExperimentGroupId;
  record<USVString, any> perBuyerSignals;
  record<USVString, unsigned long long> perBuyerTimeouts;
  record<USVString, unsigned short> perBuyerGroupLimits;
  record<USVString, unsigned short> perBuyerExperimentGroupIds;
  record<USVString, record<USVString, double>> perBuyerPrioritySignals;
  sequence<AuctionAdConfig> componentAuctions;
  AbortSignal? signal;
};

4. Permissions Policy integration

This specification defines a policy-controlled feature identified by the string "join-ad-interest-group". Its default allowlist is 'self'.

Note: In the Chromium implementation the default allowlist is temporarily set to * to ease testing.

5. Structures

5.1. Interest group

An interest group is a struct with the following items:

expiry

A point in time at which the browser will forget about this interest group.

owner

An origin.

name

A string.

priority

A double. Defaulting to 0.0. Used to select which interest groups participate in an auction when the number of interest groups are limited by perBuyerGroupLimits.

enable bidding signals prioritization

A boolean. Defaulting to false. Being true if the interest group’s priority should be calculated using vectors from bidding signals fetch.

priority vector

Null or an ordered map whose keys are strings and whose values are doubles. Its dot product with the perBuyerPrioritySignals will be used in place of priority, if set.

priority signals overrides

Null or an ordered map whose keys are strings and whose values are doubles. Overrides the AuctionAdConfig's corresponding priority signals.

execution mode

An WorkletExecutionMode, defaulting to "compatibility".

bidding url

Null or a URL. The URL to fetch the buyer’s Javascript from.

bidding wasm helper url

Null or a URL. Lets the bidder provide computationally-expensive subroutines in WebAssembly, rather than JavaScript, to be driven from the JavaScript function provided by bidding url.

daily update url

Null or a URL. Provides a mechanism for the group’s owner to periodically update the attributes of the interest group.

trusted bidding signals url

Null or a URL. Provide a mechanism for making real-time data available for use at bidding time.

trusted bidding signals keys

Null or a list of string.

user bidding signals

Null or a string. Additional metadata that the owner can use during on-device bidding.

ads

Null or a list of interest group ad. Contains various ads that the interest group might show.

ad components

Null or a list of interest group ad. Contains various ad components (or "products") that can be used to construct ads composed of multiple pieces — a top-level ad template "container" which includes some slots that can be filled in with specific "products".

TODO: Update the short descriptions of some fields above, and add links when runAdAuction() section is ready.

5.2. Interest group ad

An interest group ad is a struct with the following items:

render url

A URL.

metadata

Null or a string.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[PERMISSIONS-POLICY-1]
Ian Clelland. Permissions Policy. URL: https://w3c.github.io/webappsec-permissions-policy/
[URL]
Anne van Kesteren. URL Standard. Living Standard. URL: https://url.spec.whatwg.org/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

IDL Index

[SecureContext]
partial interface Navigator {
  Promise<undefined> joinAdInterestGroup(AuctionAdInterestGroup group, double durationSeconds);
};

enum WorkletExecutionMode {
  "compatibility",
  "groupByOrigin",
};

dictionary AuctionAd {
  required USVString renderUrl;
  any metadata;
};

dictionary AuctionAdInterestGroup {
  required USVString owner;
  required USVString name;

  double priority = 0.0;
  boolean enableBiddingSignalsPrioritization = false;
  record<USVString, double> priorityVector;
  record<USVString, double> prioritySignalsOverrides;

  WorkletExecutionMode executionMode = "compatibility";
  USVString biddingLogicUrl;
  USVString biddingWasmHelperUrl;
  USVString dailyUpdateUrl;
  USVString trustedBiddingSignalsUrl;
  sequence<USVString> trustedBiddingSignalsKeys;
  any userBiddingSignals;
  sequence<AuctionAd> ads;
  sequence<AuctionAd> adComponents;
};

[SecureContext]
partial interface Navigator {
  Promise<USVString?> runAdAuction(AuctionAdConfig config);
};

dictionary AuctionAdConfig {
  required USVString seller;
  required USVString decisionLogicUrl;
  USVString trustedScoringSignalsUrl;
  sequence<USVString> interestGroupBuyers;
  any auctionSignals;
  any sellerSignals;
  USVString directFromSellerSignals;
  unsigned long long sellerTimeout;
  unsigned short sellerExperimentGroupId;
  record<USVString, any> perBuyerSignals;
  record<USVString, unsigned long long> perBuyerTimeouts;
  record<USVString, unsigned short> perBuyerGroupLimits;
  record<USVString, unsigned short> perBuyerExperimentGroupIds;
  record<USVString, record<USVString, double>> perBuyerPrioritySignals;
  sequence<AuctionAdConfig> componentAuctions;
  AbortSignal? signal;
};