Private Aggregation API overview

Generate aggregate data reports using data from Protected Audience and cross-site data from Shared Storage.

To provide critical features that the web relies on, the Private Aggregation API has been built for aggregating and reporting on cross-site data in a privacy-preserving manner.

Implementation status

Proposal Status
Prevent invalid Private Aggregation API reports with report verification for Shared Storage
Available in Chrome
Private Aggregation debug mode availability dependent on 3PC eligibility
GitHub issue
Available in Chrome M119
Reducing report delay
Available in Chrome M119
Support for Private Aggregation API and Aggregation Service for Google Cloud
Available in Chrome M121
Padding for aggregatable report payloads
Available in Chrome M119
Private Aggregation debug mode available for auctionReportBuyers reporting
Expected in Chrome M123
Filtering ID support
Expected in Chrome M128

What is the Private Aggregation API

The Private Aggregation API allows developers to generate aggregate data reports with data from the Protected Audience API and cross-site data from Shared Storage.

This API currently provides one operation, contributeToHistogram(), but more may be supported in the future. The histogram operation allows you to aggregate data across users in each bucket (known in the API as an aggregation key) you define. Your histogram call accumulates values and returns a noised aggregated result in the form of a summary report. For instance, the report might show the number of sites each user has seen your content on, or come across a bug in your third-party script. This operation is performed within another API's worklet.

For example, if you have previously recorded demographic and geographic data in Shared Storage, you can use the Private Aggregation API to construct a histogram that tells you approximately how many users in New York City have seen your content cross-site. To aggregate for this measurement, you can encode the geography dimension into the aggregation key and count the users in the aggregatable value.

Key concepts

When you call the Private Aggregation API with an aggregation key and an aggregatable value, the browser generates an aggregatable report.

Aggregatable reports are sent to your server for collection and batching. The batched reports are processed later by the Aggregation Service, and a summary report is generated.

See the Private Aggregation API fundamentals document to learn more about the key concepts involved with the Private Aggregation API.

Differences from Attribution Reporting

The Private Aggregation API shares many similarities with the Attribution Reporting API. Attribution Reporting is a standalone API designed to measure conversions, whereas Private Aggregation is built for cross-site measurements in conjunction with APIs such as the Protected Audience API and Shared Storage. Both APIs produce aggregatable reports that are consumed by the Aggregation Service back-end to generate summary reports.

Attribution Reporting associates data gathered from an impression event and a conversion event, which happen at different times. Private Aggregation measures a single, cross-site event.

Test this API

To test the Private Aggregation API locally, enable all the Ad privacy APIs under chrome://settings/adPrivacy.

Read more about testing in experiment and participate.

Use the demo

The demo of Private Aggregation API for Shared Storage can be accessed at, and the code is available on GitHub. The demo implements the client-side operations and produces an aggregatable report that is sent to your server.

A demo of Private Aggregation API for the Protected Audience API will be published in the future.

Use cases

Private Aggregation is a general-purpose API for cross-site measurement, and it's available to be used in Shared Storage and Protected Audience API worklets. The first step is to decide specifically what information you want to collect. Those data points are the basis of your aggregation keys.

With Shared storage

Shared Storage lets you to read and write cross-site data in a secure environment to prevent leakage, and the Private Aggregation API allows you to measure cross-site data stored in Shared Storage.

Unique reach measurement

You may want to measure how many unique users have seen their content. Private Aggregation API can provide an answer such as "Approximately 317 unique users have seen the Content ID 861."

You can set a flag in Shared Storage to signify whether the user has already seen the content or not. On the first visit where the flag does not exist, a call to Private Aggregation is made and then the flag is set. On subsequent visits by the user, including cross-site visits, you can check Shared Storage and skip submitting a report to Private Aggregation if the flag is set. To learn more about methods to implement these measurements, check out our reach whitepaper.

Demographics measurement

You may want to measure the demographics of the users who have seen your content across different sites.

Private Aggregation can provide an answer, such as "Approximately 317 unique users are from the age of 18-45 and are from Germany." Use Shared Storage to access demographics data from a third-party context. At a later point in time, you can generate a report with Private Aggregation by encoding the age group and country dimensions in the aggregation key.

K+ frequency measurement

You may want to measure the number of users who have seen a piece of content or an ad at least K times on a given browser, for a pre-chosen value of K.

Private Aggregation can provide an answer such as "Approximately 89 users have seen the Content ID 581 at least 3 times." A counter can be incremented in Shared Storage from different sites and can be read within a worklet. When the count has reached K, a report can be submitted via Private Aggregation.

With the Protected Audience API

The Protected Audience API enables retargeting and custom audience use cases, and Private Aggregation allows you to report events from buyer and seller worklets. The API can be used for tasks such as measuring the distribution of auction bids.

From a Protected Audience API worklet, you can aggregate your data directly using contributeToHistogram() and report your data based on a trigger using contributeToHistogramOnEvent(), which is a special extension for the Protected Audience API.

Available functions

The following functions are available in the privateAggregation object available in Shared Storage and Protected Audience API worklets.


You can call privateAggregation.contributeToHistogram({ bucket: <bucket>, value: <value> }), where the aggregation key is bucket and the aggregatable value as value. For the bucket parameter, a BigInt is required. For the value parameter, an integer Number is required.

Here is an example of how it may be called in Shared Storage for reach measurement:


// Cross-site iframe code

async function measureReach() {
 // Register worklet
 await window.sharedStorage.worklet.addModule('worklet.js');

 // Run reach measurement operation
 await'reach-measurement', { 
  data: { contentId: '1234' } 



// Shared storage worklet code

function convertContentIdToBucket(campaignId){ 
  // Generate aggregation key

// The scale factor is multiplied by the aggregatable value to
// maximize the signal-to-noise ratio. See "Noise and scaling" 
// section in the Aggregation Fundamentals document to learn more.
const SCALE_FACTOR = 65536;

class ReachMeasurementOperation {
  async run(data) {
    const key = 'has-reported-content';
    // Read the flag from Shared Storage
    const hasReportedContent = await this.sharedStorage.get(key) === 'true';

    // Do not send report if the flag is set
    if (hasReportedContent) {

    // Send histogram report
    // Set the aggregation key in `bucket`
    // Bucket examples: 54153254n or BigInt(54153254)
    // Set the scaled aggregatable value in `value`
      bucket: convertContentIdToBucket(data.contentId), 
      value: 1 * SCALE_FACTOR 

    // Set the flag in Shared Storage
    await this.sharedStorage.set(key, true);

register('reach-measurement', ReachMeasurementOperation);

The above code example will call Private Aggregation whenever the cross-site iframe content is loaded. The iframe code loads the worklet, and the worklet calls the Private Aggregation API with the content ID converted to an aggregation key (bucket).


Within Protected Audience API worklets only, we provide a trigger-based mechanism for sending a report only if a certain event occurs. This function also allows for the bucket and value to depend on signals that are not yet available at that point in the auction.

The privateAggregation.contributeToHistogramOnEvent(eventType, contribution) method takes an eventType that specifies the triggering event, and the contribution to be submitted when the event is triggered. The triggering event can come from the auction itself after the auction ends, such as an auction win or loss event, or it can come from a fenced frame that rendered the ad. To send a report for auction events, you can use two reserved keywords,, reserved.loss, and reserved.always. To submit a report triggered by an event from a fenced frame, define a custom event type. To trigger the event from a fenced frame, use the fence.reportEvent() method available from the Fenced Frames Ads Reporting API.

The following example sends an impression report when the auction win event is triggered, and sends a click report if a click event is triggered from the fenced frame that rendered the ad. These two values can be used to calculate the clickthrough rate.

function generateBid(interestGroup, auctionSignals, perBuyerSignals, trustedBiddingSignals, browserSignals) {
  // …
  privateAggregation.contributeToHistogramOnEvent("", {
      bucket: getImpressionReportBucket(),
      value: 1
  privateAggregation.contributeToHistogramOnEvent("click", {
      bucket: getClickReportBuckets(), // 128-bit integer as BigInt
      value: 1

See the Extended Private Aggregation Reporting explainer to learn more.


While third-party cookies are still available, we'll provide a temporary mechanism that allows easier debugging and testing by enabling the debug mode. A debug report is useful in comparing your cookie-based measurements with your Private Aggregation measurements, and also allows you to quickly validate your API integration.

Calling privateAggregation.enableDebugMode() in the worklet enables the debug mode which causes aggregatable reports to include the unencrypted (cleartext) payload. You can then process these payloads with the Aggregation Service local testing tool.

The debug mode is only available to callers that are allowed to access third-party cookies. If the caller does not have access to third-party cookies, enableDebugMode() will silently fail. This means that when third party cookies are deprecated the debug mode will no longer be available.

You can also set the debug key by calling privateAggregation.enableDebugMode({ <debugKey: debugKey> }) where a BigInt can be used as a debug key. The debug key can be used to associate data from a cookie-based measurement and data from Private Aggregation measurement.

These can be called only once per context. Any subsequent calls will throw an exception.

// Enables debug mode

// Enables debug mode and sets a debug key
privateAggregation.enableDebugMode({ debugKey: BigInt(1234) });

Report verification

For Shared Storage, you can verify the aggregatable reports you received are legitimate by adding a context ID to the shared storage operation call. The ID will be attached to the sent report, and at a later time, you can use that ID to verify that the report was sent from your shared storage operation.

The feature is available for testing in Chrome M114+. Report verification for the Protected Audience API is not yet available for testing.

To learn more, see the report verification explainer.

Engage and share feedback

The Private Aggregation API is under active discussion and subject to change in the future. If you try this API and have feedback, we'd love to hear it.