Learn how to define an audience by creating an interest group using the Protected Audience API. Read the developer guide for the full lifecycle of the Protected Audience API, and refer to the Protected Audience API explainer for an in-depth proposal of how browsers record interest groups.
Not a developer? Refer to the Protected Audience API overview.
Protected Audience API interest groups
A Protected Audience API interest group represents a group of people with a common interest, corresponding to a remarketing list. Every Protected Audience API interest group has an owner.
Interest group owners act as the buyer in the Protected Audience API ad auction. Interest group membership is stored by the browser, on the user's device, and is not shared with the browser vendor or anyone else.
API functions
joinAdInterestGroup()
The advertiser's demand-side platform (DSP) or the advertiser itself calls navigator.joinAdInterestGroup()
to ask the browser to add an interest group to the browser's membership list.
The origin of the calling context for joinAdInterestGroup()
must match the interest group owner's origin, so joinAdInterestGroup()
will need to be called from an iframe (for example, from a DSP) unless the origin of the interest group owner matches the origin of the current document (for example, a website with its own interest groups).
joinAdInterestGroup()
requires permission from:
- The site being visited
- The interest group owner
This means it's not possible for malicious.example
to call joinAdInterestGroup()
for an interest group owned by dsp.example.com
, without dsp.example.com
granting permission.
Permission from the visited site
Permission can be granted from the same origin or cross-origin. By default, permission is granted for joinAdInterestGroup()
calls from the same origin as the site visited, (in other words, from the same origin as the top-level frame of the current page).
Example usage
Here's an example of how one might define an interest group and ask the browser to join the group.
const interestGroup = {
owner: 'https://dsp.example',
name: 'custom-bikes',
biddingLogicUrl: ...,
biddingWasmHelperUrl: ...,
updateUrl: ...,
trustedBiddingSignalsUrl: ...,
trustedBiddingSignalsKeys: ['key1', 'key2'],
userBiddingSignals: {...},
ads: [bikeAd1, bikeAd2, bikeAd3],
adComponents: [customBike1, customBike2, bikePedal, bikeFrame1, bikeFrame2],
};
navigator.joinAdInterestGroup(interestGroup, 7 * kSecsPerDay);
The interestGroup
object passed to the function must be no more than 50 kiB in size, otherwise the call will fail. The second parameter specifies the duration of the interest group, capped at 30 days. Successive calls overwrite previously stored values.
Required properties
The only required properties for interest groups are owner
and name
:
Property | Example | Role |
---|---|---|
owner |
https://dsp.example |
Origin of the interest group owner. |
name |
custom-bikes |
Name of the interest group. |
Optional properties
The remaining properties are optional:
biddingLogicUrl
1, 2- Example:
https://dsp.example/bid/custom-bikes/bid.js
- Role: URL for bidding JavaScript run in worklet.
biddingWasmHelperUrl
1, 2- Example:
https://dsp.example/bid/custom-bikes/bid.wasm
- Role: URL for WebAssembly code driven from
biddingLogicUrl
. updateUrl
2- Example:
https://dsp.example/bid/custom-bikes/update
- Role: URL that returns JSON to update interest group attributes. (See Update audience data and refresh ads.)
trustedBiddingSignalsUrl
2- Example:
https://dsp.example/trusted/bidding-signals
- Role: Base URL for key-value requests to bidder's trusted Key/Value service.
trustedBiddingSignalsKeys
- Example:
['key1', 'key2' ...]
- Role: Keys for requests to key-value trusted Key/Value service.
userBiddingSignals
- Example:
{...}
- Role: Additional metadata the owner can use during bidding.
ads
1- Example:
[bikeAd1, bikeAd2, bikeAd3]
- Role: Ads that might be rendered for this interest group.
adComponents
- Example:
[customBike1, customBike2, bikePedal, bikeFrame1, bikeFrame2]
- Role: Components for ads composed of multiple pieces.
1 The biddingLogicUrl
and ads
properties are optional, but required to participate in an auction. There may be use cases for creating an interest group without these properties: for example, an interest group owner might want to add a browser to an interest group for a campaign that isn't running yet, or for some other future use, or they may temporarily have run out of advertising budget.
2 In the current implementation of the Protected Audience API, biddingLogicUrl
, biddingWasmHelperUrl
, updateUrl
, and trustedBiddingSignalsUrl
must have the same origin as owner. That may not be a long-term constraint, and the ads
and adComponents
URLs have no such constraint.
Specify ads for an interest group
ads
and adComponents
objects include a URL for an ad creative and, optionally, arbitrary metadata that can be used at bidding time.
For example:
{
renderUrl: 'https://cdn.example/.../bikeAd1.html',
metadata: bikeAd1metadata // optional
}
leaveAdInterestGroup()
The interest group owner can request to a browser be removed from an interest group. The browser removes the interest group from its membership list.
navigator.leaveAdInterestGroup({
owner: 'https://dsp.example',
name: 'custom-bikes'
});
If a user returns to the site which asked the browser to add an interest group, the interest group owner can call the navigator.leaveAdInterestGroup()
function to request the browser remove the interest group.
Code for an ad can also call this function for its interest group.
Frequently asked questions
What's the maximum number of interest groups per group owner for a single user?
Chrome allows up to 1000 interest groups per owner, and up to 1000 interest group owners. These limits are meant as guard rails, not to be hit in regular operation.
How can I maximize interest group ads that meet 𝑘-anon thresholds?
As the public explainer notes, since a single interest group can carry multiple possible ads that it might show, the group will have an opportunity to re-bid another one of its ads to act as a "fallback ad" any time its most-preferred choice is below threshold. This means that a small, specialized ad that is still below the 𝑘-anonymity threshold could still choose to participate in auctions, and its interest group has a way to fall back to a more generic ad until the more specialized one has a large enough audience.
From a tactical perspective, you may consider the following:
- To get a new ad to start showing, just start bidding with it in cases where you want it to show. There is nothing additional that you need to do.
- You can have a fallback ad that you use when new ads are not 𝑘-anon. There is some risk of your fallback ad itself not being 𝑘-anon, so you could consider sometimes just bidding with the fallback ad in the first place. Perhaps do this 1% of the time, for example, if that is a good level to ensure that you expect the fallback to stay over threshold.
There has been some recent discussion of other ways things could work, so if you have some use case for which this mechanism would pose a problem, continue engaging in the public conversation about ways in which the API could improve.
All Protected Audience API references
API reference guides are available:
- Developer guide for the Protected Audience API.
- Ad buyer guide to Protected Audience interest groups and bid generation.
- Ad seller guide to Protected Audience ad auctions.
- Guide to reporting auction results
- Best practices for Protected Audience ad auction latency
- Troubleshoot Protected Audience
The Protected Audience API explainer also provides detail about feature support and constraints.