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 dictionary {
AuctionAd required USVString ;
renderUrl any ; };
metadata dictionary {
AuctionAdInterestGroup required USVString ;
owner required USVString ;
name double = 0.0;
priority boolean =
enableBiddingSignalsPrioritization false ;record <DOMString ,double >;
priorityVector record <DOMString ,double >;
prioritySignalsOverrides DOMString = "compatibility";
executionMode 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:
-
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
. -
Let interestGroup be a new interest group.
-
Validate the given group and set interestGroup’s fields accordingly.
-
Set interestGroup’s expiry to now plus durationSeconds.
-
Let ownerUrl be the result of running the URL parser on group["
owner
"]. -
Set interestGroup’s enable bidding signals prioritization to group["
enableBiddingSignalsPrioritization
"]. -
If group["
priorityVector
"] exists, then set interestGroup’s priority vector to group["priorityVector
"]. -
If group["
prioritySignalsOverrides
"] exists, then set interestGroup’s priority signals overrides to group["prioritySignalsOverrides
"]. -
Set interestGroup’s execution mode to group["
executionMode
"]. -
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 -
If group contains groupMember:
-
Let parsedUrl be the result of running the URL parser on group[groupMember].
-
-
parsedUrl is an error.
-
parsedUrl is not same origin with interestGroup’s owner.
-
parsedUrl includes credentials.
-
parsedUrl fragment is not null.
-
-
Set interestGroup’s interestGroupField to parsedUrl.
-
-
-
If interestGroup’s trusted bidding signals url's query is not null, then throw a
TypeError
. -
If group["
trustedBiddingSignalsKeys
"] exists, then set interestGroup’s trusted bidding signals keys to group["trustedBiddingSignalsKeys
"]. -
If group["
userBiddingSignals
"] exists:-
Let interestGroup’s user bidding signals be the result of serializing a JavaScript value to a JSON string, given group["
userBiddingSignals
"]. This can throw aTypeError
.
-
-
For each groupMember and interestGroupField in the following table
Group member Interest group field " ads
"ads " adComponents
"ad components -
For each ad of group[groupMember]:
-
Let igAd be a new interest group ad.
-
Let renderUrl be the result of running the URL parser on ad["
renderUrl
"]. -
-
renderUrl is an error.
-
renderUrl scheme is not "
https
". -
renderUrl includes credentials.
-
-
Set igAd’s render url to renderUrl.
-
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 aTypeError
. -
Append igAd to interestGroup’s interestGroupField.
-
-
-
-
If interestGroup’s estimated size is greater than 50 KB, then throw a
TypeError
. -
Let p be a new promise.
-
Return p and run the following steps in parallel: (TODO: Enqueue the steps to a parallel queue instead.)
-
TODO: document .well-known fetches for cross-origin joins.
-
If the browser is currently storing an interest group with
owner
andname
that matches interestGroup, then remove the currently stored one. -
TODO: Set interestGroup’s joining origin to top level page origin from where the interest group was joined.
-
Store interestGroup in the browser’s interest group set.
-
Queue a task to resolve p with
undefined
.
-
The estimated size of an interest group ig is the sum of:
-
The length of the serialization of ig’s owner.
-
8 bytes, which is the size of ig’s priority.
-
The length of ig’s execution mode.
-
2 bytes, which is the size of ig’s enable bidding signals prioritization.
-
If ig’s priority vector is not null, for each key → value of priority vector:
-
The length of key.
-
8 bytes, which is the size of value.
-
-
If ig’s priority signals overrides is not null, for each key → value of priority signals overrides:
-
The length of key.
-
8 bytes, which is the size of value.
-
-
The size of execution mode.
-
The length of the serialization of ig’s bidding url, if the field is not null.
-
The length of the serialization of ig’s bidding wasm helper url, if the field is not null.
-
The length of the serialization of ig’s daily update url, if the field is not null.
-
The length of the serialization of ig’s trusted bidding signals url, if the field is not null.
-
For each key of ig’s trusted bidding signals keys:
-
The length of key.
-
-
The length of ig’s user bidding signals.
-
If ig’s ads is not null, for each ad of it:
-
The length of the serialization of ad’s render url.
-
-
If ig’s ad components is not null, for each ad of it:
-
The length of the serialization of ad’s render url.
-
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
The runAdAuction(config)
method steps are:
-
If this's relevant global object's associated Document is not allowed to use the "run-ad-auction" policy-controlled feature, then throw a "
NotAllowedError
"DOMException
. -
Let auctionConfig be the result of running validate and convert auction ad config with config and isTopLevel set to true.
-
-
If config["
signal
"] is aborted, then return a promise rejected with config["signal
"]'s abort reason.
-
-
Let p be a new promise.
-
Return p, and run the remaining steps in parallel.
-
Run start bidding and scoring with auctionConfig.
-
TODO: add missing steps.
To validate and convert auction ad config given an AuctionAdConfig
config and a boolean isTopLevel:
-
Let auctionConfig be a new auction config.
-
Let seller be the result of running the URL parser on config["
seller
"]. -
Let decisionLogicUrl be the result of running the URL parser on config["
decisionLogicUrl
"].-
Throw a
TypeError
if decisionLogicUrl is an error, or it is not same origin with auctionConfig’s seller. -
Assert: decisionLogicUrl’s scheme is "
https
". -
Set auctionConfig’s decision logic url to decisionLogicUrl.
-
-
If config["
trustedScoringSignalsUrl
"] exists:-
Let trustedScoringSignalsUrl be the result of running the URL parser on config["
trustedScoringSignalsUrl
"]. -
Throw a
TypeError
if trustedScoringSignalsUrl is an error, or it is not same origin with auctionConfig’s seller. -
Assert: trustedScoringSignalsUrl’s scheme is "
https
". -
Set auctionConfig’s trusted scoring signals url to trustedScoringSignalsUrl.
-
-
If config["
interestGroupBuyers
"] exists, let buyers be a new empty list.-
For each buyerString in config["
interestGroupBuyers
"]:-
Let buyer be the result of parsing an origin with buyerString. If buyer is an error, or buyer’s scheme is not "
https
", then throw aTypeError
. Otherwise, append buyer to buyers.
-
-
Set auctionConfig’s interest group buyers to buyers.
-
-
If config["
auctionSignals
"] exists, let auctionConfig’s auction signals be the result of serializing a JavaScript value to a JSON string, given config["auctionSignals
"]. -
If config["
sellerSignals
"] exists, let auctionConfig’s seller signals of be the result of serializing a JavaScript value to a JSON string, given config["sellerSignals
"]. -
If config["
directFromSellerSignals
"] exists, let directFromSellerSignalsPrefix be the result of running the URL parser on config["directFromSellerSignals
"].-
-
directFromSellerSignalsPrefix is an error.
-
directFromSellerSignalsPrefix is not same origin with auctionConfig’s seller.
-
directFromSellerSignalsPrefix’s query is not null.
-
-
Assert: directFromSellerSignalsPrefix’s scheme is "
https
". -
TODO: Figure out how to deal with DirectFromSellerSignals.
-
-
If config["
sellerTimeout
"] exists, set auctionConfig’s seller timeout to min(config["sellerTimeout
"], 500) milliseconds. -
If config["
sellerExperimentGroupId
"] exists:-
Set auctionConfig’s seller experiment group id to config["
sellerExperimentGroupId
"].
-
-
If config["
perBuyerSignals
"] exists, for each key → value of config["perBuyerSignals
"]:-
Let buyer be the result of parsing an origin with key. If buyer is an error, throw a
TypeError
. -
Let signalsString be the result of serializing a JavaScript value to a JSON string, given value.
-
Set auctionConfig’s per buyer signals[buyer] to signalsString.
-
-
If config["
perBuyerTimeouts
"] exists, for each key → value of config["perBuyerTimeouts
"]:-
If key equals to "*", then set auctionConfig’s all buyers timeout to min(value, 500) milliseconds, and continue.
-
Let buyer the result of parsing an origin with key. If buyer is an error, throw a
TypeError
. -
Set auctionConfig’s per buyer timeouts[buyer] to min(value, 500) milliseconds.
-
-
If config["
perBuyerGroupLimits
"] exists, for each key → value of config["perBuyerGroupLimits
"]:-
If key equals to "*", then set auctionConfig’s all buyers group limit to value, and continue.
-
Let buyer be the result of parsing an origin with key. If buyer is an error, throw a
TypeError
. -
Set auctionConfig’s per buyer group limits[buyer] to value.
-
If config["
perBuyerExperimentGroupIds
"] exists, for each key → value of config["perBuyerExperimentGroupIds
"]:-
If key equals to "*", then set auctionConfig’s all buyer experiment group id to value, and continue.
-
Let buyer the result of parsing an origin with key. If buyer is an error, throw a
TypeError
. -
Set auctionConfig’s per buyer experiment group ids[buyer] to value.
-
-
If config["
perBuyerPrioritySignals
"] exists, for each key → value of config["perBuyerPrioritySignals
"]:-
Let signals be an ordered map whose keys are strings and whose values are
double
. -
for each k → v of value:
-
If k starts with "browserSignals.", throw a
TypeError
. -
Set signals[k] to v.
-
-
If key equals to "*", then set auctionConfig’s all buyers priority signals to value, and continue.
-
Let buyer be the result of parsing an origin with key. If it fails, throw a
TypeError
. -
Set auctionConfig’s per buyer priority signals[buyer] to signals.
-
-
For each component in config["
componentAuctions
"]:-
Let componentAuction be the result of running validate and convert auction ad config with component and isTopLevel set to false.
-
Append componentAuction to auctionConfig’s component auctions.
-
Return auctionConfig.
To parse an origin given a string input:
-
Let url be the result of running the URL parser on input.
-
If url is an error, then return failure.
-
Return url’s origin.
To start bidding and scoring given an auction config auctionConfig:
-
If auctionConfig’s component auctions are empty:
-
TODO: Create a seller worklet.
-
-
Otherwise:
-
For each component in auctionConfig’s component auctions:
-
Start bidding and scoring with component.
-
-
TODO: If the last component’s seller worklet is received, create a seller worklet.
-
-
Let bidGenerators be a new ordered map whose keys are origins and whose values are per buyer bid generators.
-
For each buyer in interest group buyers:
-
For each ig of the user agent’s interest group set whose owner is buyer:
-
Let signalsUrl be ig’s trusted bidding signals url.
-
Let joiningOrigin be ig’s joining origin.
-
If bidGenerators does not contain buyer:
-
Let perBuyerGenerator be a new per buyer bid generator.
-
Let perSignalsUrlGenerator be a new per signals url bid generator.
-
Set perSignalsUrlGenerator[joiningOrigin] to « ig ».
-
Set perBuyerGenerator[signalsUrl] to perSignalsUrlGenerator.
-
Set bidGenerators[buyer] to perBuyerGenerator.
-
TODO: add a perBiddingScriptUrlGenerator layer that replaces the list of IGs with a map from biddingScriptUrl to a list of IGs.
-
-
Otherwise:
-
Let perBuyerGenerator be bidGenerators[buyer].
-
If perBuyerGenerator does not contain signalsUrl:
-
Let perSignalsUrlGenerator be a new per signals url bid generator.
-
Set perSignalsUrlGenerator[joiningOrigin] to « ig ».
-
Set perBuyerGenerator[signalsUrl] to perSignalsUrlGenerator.
-
-
Otherwise:
-
-
-
-
For each buyer → perBuyerGenerator of bidGenerators:
-
For each signalsUrl -> perSignalsUrlGenerator of perBuyerGenerator:
-
TODO: Fetch signalsUrl synchronously.
-
For each joiningOrigin -> groups of perSignalsUrlGenerator:
-
For each ig of groups:
-
Let biddingScript be the result of fetch bidding or scoring javascript with ig’s bidding url.
-
If biddingScript is an error, continue.
-
TODO: Evaluate script with script set to biddingScript, functionName set to "generateBid", and arguments set to generateBid’s arguemnts.
-
-
-
-
To create a request given a URL url, and a string accept:
-
Let request be a new request with the following properties:
- URL
-
url
- header list
-
A new header list containing a header named "
Accept
" whose value is accept - client
-
null
- window
-
"
no-window
" TODO: verify - service-workers mode
-
"
none
" - origin
- referrer
-
"
no-referrer
" - credentials mode
-
"
omit
" - cache mode
-
"
no-store
" - redirect mode
-
"
error
"
-
Return request.
To fetch bidding or scoring javascript with given URL url:
-
Let request be the result of creating a request with url, and accept set to "
application/javascript
". -
Fetch request.
-
Wait for the processResponseConsumeBody algorithm to finish. TODO: use processResponseConsumeBody as argument to fetch.
-
Let response be the result of fetch when it asynchronously completes.
-
Let body be response’s body.
-
If body is null, return failure.
-
Let headers be response’s header list.
-
If getting a structured field value "X-Allow-FLEDGE" from headers does not return true, return failure.
-
Let mimeType be the result of extracting a MIME type from headers.
-
If mimeType is failure or not a JavaScript MIME type, return failure.
-
If mimeType’s parameters["
charset
"] exists, and is not "utf-8" or "us-ascii", return failure. -
Return body.
To evaluate script with given string script, string functionName, and a list arguments:
-
TODO: Return an object or null, which is the result of evaluating script’s functionName with arguments.
4. Permissions Policy integration
This specification defines two policy-controlled features identified by the string
"join-ad-interest-group
", and
"run-ad-auction
". Their default allowlists are self
.
Note: In the Chromium implementation the default allowlists for both
features are 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 byperBuyerGroupLimits
. - 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
double
. Its dot product with theperBuyerPrioritySignals
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
double
. Overrides theAuctionAdConfig
's corresponding priority signals. - execution mode
-
A string, 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
- 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".
- joining origin
-
An origin.The top level page origin from where the interest group was joined.
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:
5.3. Auction config
An auction config is a struct with the following items:
- seller
-
An origin.
- decision logic url
-
A URL.
- trusted scoring signals url
-
Null or a URL.
- interest group buyers
- auction signals
-
Null or a string.
- seller signals
-
Null or a string.
- seller timeout
-
A duration. Defaulting to 50.
- per buyer signals
-
Null or an ordered map whose keys are origins and whose values are strings.
- per buyer timeouts
-
Null or an ordered map whose keys are origins and whose values are durations.
- all buyers timeout
-
A duration. Defaulting to 50.
- per buyer group limits
-
Null or an ordered map whose keys are origins and whose values are non-negative 16-bit integers.
- per buyer priority signals
-
Null or an ordered map whose keys are origins and whose values are ordered maps, whose keys are strings and whose values are
double
. - all buyers priority signals
-
Null or an ordered map whose keys are strings and whose values are
double
. - all buyers group limit
-
A non-negative 16-bit integer.
- component auctions
-
A list of auction configs.
- seller experiment group id
-
A non-negative 16-bit integer.
- all buyer experiment group id
-
A non-negative 16-bit integer.
- per buyer experiment group ids
-
An ordered map whose keys are origins and whose values are non-negative 16-bit integers.
5.4. Per buyer bid generator
A per buyer bid generator is an ordered map whose keys are URLs representing trusted bidding signals urls, and whose values are per signals url bid generators.
5.5. Per signals url bid generator
A per signals url bid generator is an ordered map whose keys are origins representing joining origins, and whose values are lists of interest groups.
TODO: Add short descriptions for fields of each structure above.