Frequency capping is an advertising practice that limits the number of ads from a given category that are shown to a user within a given time period. Frequency capping improves the end-user experience by keeping ad impressions fresh and interesting, and helps advertisers manage ad spend.
This proposal introduces how Protected Audience on Android can be used to implement frequency capping functionality in an accurate and privacy-preserving way.
Protected Audience implements frequency capping by combining two features: The on-device storage of counters for ad-specific events, and the ability to filter ads according to a predefined set of filter strategies. Frequency capping enables advertisers to indicate a counter threshold over a sum of histogram values for a given time period.
Counters are unique for each combination of device profile, ad tech, and counter key. Each ad should contain a set of counter keys to use in case a view or impression for the ad is registered. For each key, Protected Audience stores a set of counters, and each counter tallies all ad-specific events that occur within a specific time interval. On-device counters are incremented when an impression or view occurs, and counter data will be persisted on device. The exact persistence time will be defined later.
The ad filtering logic in Protected Audience's ad selection workflow has access to counters, remarketing ads, and contextual ads, giving Protected Audience frequency capping the ability to work with all such types of ad requests.
Note: Ad filtering is only available in the Privacy Sandbox on Android. Chrome's Protected Audience implementation does not currently implement a mechanism for filtering contextually-targeted non-Protected Audience ads. This proposal covers buy-side support only. If there is demand, we will add sell-side support at a later date.
Protected Audience frequency capping supports a broad range of requirements, including:
- Real-time filtering, with minimal server-side delay when on-device counters are updated.
- Flexible hierarchy of keys, including individual ads, campaigns, or any other grouping.
- Congruence with other frequency capping methods, without dependency on AdID.
- Works across apps on a given device user profile.
- Accurate and complete counters.
- Support for custom definitions of ad events, such as views or impressions.
- One function for both remarketing and contextual ads.
To set up frequency capping, follow these steps:
Step 1: Add frequency capping information to ads
Contextual and remarketing ads indicate relevant histogram counters to update in
case of a view or impression using the ad_counter_keys
field that
contains a list of arbitrary integer. The field is not included in the
metadata
field that is not parsed by Protected Audience.
The following example shows the data format for the adsData
field in
AdSelectionConfig
. For remarketing, the format of the list of ads for a given
custom audience is consistent with the content of the ads
field shown in the
following example:
'adsData': [
{
"buyer": "ads.example.com",
"ads": [
{
'render_url': 'exampleUrl',
'metadata': {...}, /* metadata are opaque to Protected Audience are
required to be in valid JSON format */
'ad_counter_keys': [1234, 5678]
}]
}]
}
Step 2: Register a view or impression
Ad techs can invoke the updateAdCounterHistogram
method to register
occurrences of events that are used for frequency capping. A method can be
invoked repeatedly on the same event for keys specified in the winning ad's
eventType
.
void updateAdCounterHistogram(@EventType eventType, long adSelectionId)
Inputs:
eventType
: Identifies whether an event is counted as a view, an impression, a click, or the win of the ad selection process.adSelectionId
: ID values in theAdSelectionOutcome
object that are returned byselectAds
calls.
The updateAdCounterHistogram
call updates the histogram for the set of keys
defined as part of either the remarketing ads fetched by a CustomAudience
or
the contextual ads included in the AdSelectionConfig
parameter for
selectAds
.
If you assume that the ad in Step 1 is the winner of an AdSelection
with an
id
value of 9999
, a call to
updateAdCounterHistogram(FrequencyCapFilters.AD_EVENT_TYPE_VIEW,
adSelectionId: 999)
increments the counters for the following three primary
keys:
{'ads.example.com', 1234, VIEW}
{'ads.example.com', 5678, VIEW}
The ad tech name is taken from the buyer field, either from contextual ads or from custom audiences, depending on where the winning ads come from.
Protected Audience for Android automatically increments all the counters
mentioned above for the event type FrequencyCapFilters.AD_EVENT_TYPE_WIN
for
ads returned by a selectAds
API call. This is functionally equivalent to the
addition of the prev_wins
argument to browser_signals
in generateBid
in
Chrome's Protected Audience implementation.
Step 3: Implement frequency cap filtering with filters
For optimal performance, the frequency cap filtering function is executed within
AdServices
. Protected Audience understands if a message has to be filtered by
reading the filters field in the AdsData
object. A list of filters is
specified in frequency_cap
. The values for key, event_type
and
interval_in_seconds
are used to retrieve a histogram of events that are used
for filtering and Protected Audience.
Filtering information can be specified for remarketing ads provided by a custom
audience and for contextual ads as part of the AdSelectionConfig
object.
For contextual ads with frequency cap filters, ads are passed in using the ads
field in the AdSelectionConfig
object. Ads are filtered, and the ad with the
highest bid is returned as the result of the selectAds
call.
For remarketing ads with frequency cap filters, ads are filtered before the
buyer-provided generateBid()
JavaScript function is invoked.
The following example shows a message with frequency cap filtering:
{
'render_url': 'url',
'metadata': {...}, /* metadata are opaque to Protected Audience and assumed
to be in valid JSON format */
'ad_counter_keys': [1234, 5678],
"filters": {
"frequency_cap": {
"view": [
{
"ad_counter_key": 1234
"max_count": 10,
"interval_in_seconds": 86400
},
{
"ad_counter_key": 5678
"max_count": 10,
"interval_in_seconds": 86400
},
],
"win": [
{
"ad_counter_key": 1234
"max_count": 5,
"interval_in_seconds": 604800
},
{
"ad_counter_key": 5678
"max_count": 5,
"interval_in_seconds": 345600
},
]
},
// This field is only required in contextual ads and is used in
// reportImpression calls to fetch the reportWin function.
'reportingJS': "https://ads.example.com?reportWin.js"
}
Step 4: Report on winning Ads
Once the ad selection process is complete, it returns an AdSelectionOutcome
object containing the renderUri
and adSelectionId
, a numeric identifier for
the selectAds
call. This ID can be used to invoke the reportImpression
API
that currently supports event-level reporting. In Beta 1, this method supports
reporting for remarketing ads, and will be extended to support reporting for
contextual ads in a later release. For contextual ads, the buyer is required to
indicate where the reportWin
function can be retrieved during a
reportImpression
call by using an extra field called reportingJS
in the ad
structure, as shown in the example above.
Best practices for selecting ad candidates
Protected Audience moves the enforcement of frequency capping from the server to the device. Although winning bids are reported with the Privacy Sandbox, developers won't know why an ad isn't shown. Ads might not be shown due to a lost bid, or due to frequency capping. With no full visibility into the reasons why certain ads don't win, bidding systems require additional work to ensure optimal ads are served. These best practices will help ensure optimal ad serving with Protected Audience.
Send enough remarketing ads
Remarketing ads cannot be optimized per user. If a user sees a significant
number of ads from a custom audience and the ad limits are low, all ads may be
filtered out. Remarketing ads are refreshed periodically, so enough ad inventory
should pass through frequency capping to ensure remarketing ads continue to be
served. This needs to be balanced with limitations on the size of the ads that
can be specified during the joinCustomAudience
call, and during the custom
audience daily update. Buyers must consider that there might be an increase in
latency during the bidding phase. To minimize the impact of these issues,
frequency cap filtering is performed before the call to generateBid
.
Keep contextual counters on the server
With server side estimation, a developer can have rough estimates for when frequency capping may be active. Those estimations can indicate that an ad has likely hit the frequency cap threshold, and should therefore be sent with more ad candidates or be eliminated completely.
Send multiple ad candidates on the contextual response
You should send multiple ad candidates with a contextual response before a Protected Audience auction. This ensures that if several ads are filtered out, other ads are still shown. Ad candidates can be prioritized so that some ads are provided as backup.
Since execution is time-bound, ad candidates should be chosen according to their likelihood to win an auction and to not be filtered out.
Limitations
The following are known limitations of Protected Audience frequency capping:
- Protected Audience frequency capping operates at the device user profile level, with no shared counters on other devices and other profiles. Any increments of ads shown from other devices need to be incorporated manually, if needed.
- Device counters are stored and accessed on the device. Server-side counters need to be managed separately.
- As frequency capping and related ad filtering is processed on a device, ad tech platforms don't have direct control over these operations. To bypass the device's frequency capping threshold, ad tech platforms can send multiple candidate ads with different filters.
- Bid adjustments based on recorded frequency are unsupported. The
generateBid
functions cannot view frequency counters.
Recommended for you
- Note: link text is displayed when JavaScript is off
- Protected Audience: integration guide
- Protected Audience API on Android developer guide
- Support custom audience targeting with the Protected Audience API