Warning: This feature is currently opposed by two browser vendors. See the Standards positions section below for details of opposition.
Note: An Enrollment process is required to use the Topics API in your applications. See the Enrollment section for details of what sub-features are gated by enrollment.
This page explains how the Topics API works and how it can be used to create an interest-based advertising (IBA) solution.
High-level overviewLet's say we've got an ad tech platform, ad-tech1.example
, which is embedding ads via <iframe>
s into the following publisher sites:
yoga.example
knitting.example
football.example
If the <iframe>
content from ad-tech1.example
implements a feature that enables the Topics API, when each of the sites is loaded the browser will:
Note: Different browser implementations may select topics in different ways. The below text is based on how Chrome currently selects topics, for demonstration purposes.
On an ongoing basis, the browser will:
Keep track of how often the user observes each topic during each new epoch. An epoch is a week by default, but the length can be altered for testing purposes (see Testing hints).
Chrome places each of the 22 root topics (those without an ancestor) from the taxonomy into one of two buckets indicating higher or standard utility for the overall ad tech ecosystem. All descendants of the root topics inherit the same bucket assignment from their parent. The assignment of root topics to buckets is based on input about utility Google received from companies across the ecosystem.
Select top topics for each user, at the end of each epoch:
The top topics are returned to ad-tech1.example
, only if ad-tech1.example
appears in the list of caller domains for each topic, as stored in the topic's history entry.
Note: Initially, no topics are returned, so the <iframe>
will likely display a default non-targeted ad. However, once the end of the first epoch is reached, the API will start to return topics and ad-tech1.example
can start to show more relevant ads based on the observed topics for the current user.
ad-tech1.example
then selects a relevant ad to serve to the user, based on the returned topics.
The following features all serve a dual purpose â they return the user's top topics to the caller and they trigger the browser to record the current page visit as observed by the caller, so the page's hostname can later be used in topics calculation. To do so, they need to be included in a calling ad tech's <iframe>
; the <iframe>
then has to be embedded on the pages where you want topics observed.
You can specify a browsingTopics: true
option in the options object of a fetch()
call to the ad tech platform.
You could also pass browsingTopics: true
into the options object of a Request()
constructor call, and pass the resulting Request
object into the fetch()
call.
You can set a browsingtopics
attribute on the <iframe>
, at the same time or before setting the src
attribute to load the source. This could be done:
<iframe browsingtopics src="ad-tech1.example"> ... </iframe>
HTMLIFrameElement.browsingTopics
property to true
:const iframeElem = document.querySelector("iframe");
iframeElem.browsingTopics = true;
When the request associated with one of the above features is sent:
A Sec-Browsing-Topics
header is sent along with the request, which contains the top topic(s) for the current user.
The ad tech server selects a relevant ad to display in the <iframe>
, based on these topics, and sends the required data to display it in the response.
An Observe-Browsing-Topics
header should be set on the response to the request â this has the effect of causing the browser to record the current page visit as observed by the calling ad tech provider, so the associated topic(s) will be recorded in a topics history entry, and subsequently be used in topic selection.
Note: It is important to clarify that this doesn't record the top topics sent in the Sec-Browsing-Topics
header as observed. It records the topics inferred from the calling site's URL (i.e., the site where the ad tech <iframe>
is embedded) as observed.
browsingTopics()
method
Alternatively, the embedded <iframe>
can call Document.browsingTopics()
to return a user's current top topic(s), which can then be returned to the ad tech platform in a subsequent fetch request. This does not rely on the HTTP headers, but is somewhat less performant. You are advised to use one of the HTTP header methods listed above, falling back to browsingTopics()
only in situations where the headers cannot be modified.
Note: Because the browsingTopics()
method does not rely on the HTTP headers, the Observe-Browsing-Topics
header is not used for setting the topics as observed and recording/updating topics history entries; the browser does this automatically when the method is called.
A caller can only access topics that they themselves have observed for a user â and not topics observed by other callers. For example:
ad-tech1.example
platform has an <iframe>
embedded on tennis.example
that includes a Topics API feature, they would observe topics like "Sports" and "Tennis" for a user who visits that site.ad-tech2.example
, has a Topics API <iframe>
embedded on "gardening.example", they would observe the topic "Gardening".These ad tech platforms will only get topics for a user that they have observed. In this example, ad-tech1.example
won't get "Gardening" and ad-tech2.example
won't get "Tennis".
In other words, callers such as ad tech platforms only get topics for pages where they have a presence. More importantly, the recorded topics of interest are the only information that can be accessed via this API â unlike with tracking cookies, no other information can be leaked.
Examples UsingDocument.browsingTopics()
// Get an array of topics for this user
const topics = await document.browsingTopics();
// Request an ad creative
const response = await fetch("https://ads.example/get-creative", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(topics),
});
// Get the JSON from the response
const creative = await response.json();
// Display ad
Passing the browsingTopics
option into fetch()
// Request an ad creative
const response = await fetch("https://ads.example/get-creative", {
browsingTopics: true,
});
// Get the JSON from the response
const creative = await response.json();
// Display ad
Including the browsingtopics
attribute in an <iframe>
<iframe browsingtopics src="ad-tech1.example"> ... </iframe>
Complete examples
document.browsingTopics()
calls can be used to observe and then access topics (see source code).fetch()
request with a Sec-Browsing-Topics
header can be used to observe and then access topics (see source code).The default epoch length for observing topics is one week, which is way too long to test code that uses the Topics API. To shorten this for test purposes, in Chrome you can open the browser with a feature flag along the following lines:
BrowsingTopicsParameters:time_period_per_epoch/15s/max_epoch_introduction_delay/3s
See Run Chromium with command-line switches for more information on how to do this.
You can also test your Topics API code locally without enrollment by enabling the following Chrome developer flag:
chrome://flags/#privacy-sandbox-enrollment-overrides
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4