このドキュメントは、Shared Storage と Private Aggregation の使用に関するクイックスタート ガイドです。Shared Storage は値を保存し、Private Aggregation は集計可能なレポートを作成するため、両方の API を理解する必要があります。
対象ユーザー: 広告テクノロジーおよび測定プロバイダ。
Shared Storage API
クロスサイト トラッキングを防止するため、ブラウザはローカル ストレージや Cookie など、あらゆる形式のストレージをパーティショニングするようになりました。ただし、パーティション化されていないストレージが必要なユースケースもあります。Shared Storage API は、プライバシー保護の読み取りアクセス権を持つ、さまざまなトップレベル サイトにわたる無制限の書き込みアクセス権を提供します。
共有ストレージは、コンテキストのオリジン(sharedStorage
の呼び出し元)に制限されます。
共有ストレージにはオリジンごとに容量の上限があり、各エントリには最大文字数が制限されています。上限に達すると、それ以上の入力は保存されません。データ ストレージの上限については、共有ストレージの説明をご覧ください。
共有ストレージの呼び出し
広告テクノロジーは、JavaScript またはレスポンス ヘッダーを使用して共有ストレージに書き込むことができます。共有ストレージからの読み取りは、ワークレットと呼ばれる分離された JavaScript 環境内でのみ行われます。
JavaScript を使用: 広告テクノロジーは、JavaScript ワークレットの外部で値の設定、追加、削除など、特定の共有ストレージ機能を実行できます。ただし、共有ストレージの読み取りや非公開集計の実行などの関数は、JavaScript ワークレットで完了する必要があります。JavaScript ワークレットの外部で使用できるメソッドについては、提案されている API サーフェス - ワークレットの外部をご覧ください。
オペレーション中にワークレットで使用されるメソッドについては、提案されている API サーフェス - ワークレット内をご覧ください。
レスポンス ヘッダーの使用
JavaScript と同様に、レスポンス ヘッダーを使用して実行できる機能は、共有ストレージの値の設定、追加、削除などの特定の関数に限られます。レスポンス ヘッダーで共有ストレージを操作するには、リクエスト ヘッダーに
Shared-Storage-Writable: ?1
を含める必要があります。クライアントからリクエストを開始するには、選択した方法に応じて次のコードを実行します。
fetch()
の使用fetch("https://a.example/path/for/updates", {sharedStorageWritable: true});
iframe
タグまたはimg
タグの使用<iframe src="https://a.example/path/for/updates" sharedstoragewritable></iframe>
iframe
タグまたはimg
タグで IDL 属性を使用するlet iframe = document.getElementById("my-iframe"); iframe.sharedStorageWritable = true; iframe.src = "https://a.example/path/for/updates";
詳細については、共有ストレージ: レスポンス ヘッダーをご覧ください。
共有ストレージへの書き込み
共有ストレージに書き込むには、JavaScript ワークレットの内外から sharedStorage.set()
を呼び出します。ワークレットの外部から呼び出された場合は、呼び出し元のブラウジング コンテキストのオリジンにデータが書き込まれます。ワークレット内から呼び出された場合は、ワークレットを読み込んだブラウジング コンテキストのオリジンにデータが書き込まれます。設定された鍵の有効期限は、最後の更新から 30 日です。
ignoreIfPresent
フィールドは省略可能です。存在し、true
に設定されている場合、キーがすでに存在する場合は更新されません。キーが更新されていない場合でも、キーの有効期限は set()
呼び出しから 30 日間更新されます。
同じページの読み込みで同じキーを使用して Shared Storage に複数回アクセスすると、キーの値が上書きされます。キーで以前の値を保持する必要がある場合は、sharedStorage.append()
を使用することをおすすめします。
JavaScript を使用している場合
ワークレットの外部:
window.sharedStorage.set('myKey', 'myValue1', { ignoreIfPresent: true }); // Shared Storage: {'myKey': 'myValue1'} window.sharedStorage.set('myKey', 'myValue2', { ignoreIfPresent: true }); // Shared Storage: {'myKey': 'myValue1'} window.sharedStorage.set('myKey', 'myValue2', { ignoreIfPresent: false }); // Shared Storage: {'myKey': 'myValue2'}
同様に、ワークレット内では次のようになります。
sharedStorage.set('myKey', 'myValue1', { ignoreIfPresent: true });
レスポンス ヘッダーの使用
レスポンス ヘッダーを使用して共有ストレージに書き込むこともできます。これを行うには、レスポンス ヘッダーで
Shared-Storage-Write
と次のコマンドを使用します。Shared-Storage-Write : set;key="myKey";value="myValue";ignore_if_present
Shared-Storage-Write : set;key="myKey";value="myValue";ignore_if_present=?0
複数のアイテムをカンマ区切りで指定できます。また、
set
、append
、delete
、clear
を組み合わせることもできます。Shared-Storage-Write : set;key="hello";value="world";ignore_if_present, set;key="good";value="bye"
値を追加する
既存のキーに値を追加するには、append メソッドを使用します。キーが存在しない場合、append()
を呼び出すとキーが作成され、値が設定されます。これは、JavaScript またはレスポンス ヘッダーを使用して実現できます。
JavaScript を使用している場合
既存のキーの値を更新するには、ワークレットの内外で
sharedStorage.append()
を使用します。window.sharedStorage.append('myKey', 'myValue1'); // Shared Storage: {'myKey': 'myValue1'} window.sharedStorage.append('myKey', 'myValue2'); // Shared Storage: {'myKey': 'myValue1myValue2'} window.sharedStorage.append('anotherKey', 'hello'); // Shared Storage: {'myKey': 'myValue1myValue2', 'anotherKey': 'hello'}
ワークレット内に追加するには:
sharedStorage.append('myKey', 'myValue1');
レスポンス ヘッダーの使用
共有ストレージで値を設定する方法と同様に、レスポンス ヘッダーの
Shared-Storage-Write
を使用して Key-Value ペアを渡すことができます。Shared-Storage-Write : append;key="myKey";value="myValue2"
値の一括更新
sharedStorage.batchUpdate()
は、JavaScript ワークレット内または外部から呼び出し、選択したオペレーションを指定するメソッドの順序付き配列を渡すことができます。各メソッドのコンストラクタは、set、append、delete、clear の対応する個々のメソッドと同じパラメータを受け取ります。
ロックは、JavaScript またはレスポンス ヘッダーを使用して設定できます。
JavaScript を使用している場合
batchUpdate()
で使用できる JavaScript メソッドは次のとおりです。SharedStorageSetMethod()
: Key-Value ペアを共有ストレージに書き込みます。SharedStorageAppendMethod()
: 共有ストレージ内の既存のキーに値を追加します。SharedStorageDeleteMethod()
: 共有ストレージから Key-Value ペアを削除します。SharedStorageClearMethod()
: 共有ストレージ内のすべてのキーを消去します。
sharedStorage.batchUpdate([ new SharedStorageSetMethod('keyOne', 'valueOne'), new SharedStorageAppendMethod('keyTwo', 'valueTwo'), new SharedStorageDeleteMethod('keyThree'), new SharedStorageClearMethod() ]);
レスポンス ヘッダーの使用
Shared-Storage-Write : batchUpdate;methods="set;key=keyOne;value=valueOne, append;key=keyTwo;value=valueTwo,delete;key=keyThree,clear"
共有ストレージからの読み取り
共有ストレージから読み取ることができるのは、ワークレット内からのみです。
await sharedStorage.get('mykey');
ワークレット モジュールが読み込まれたブラウジング コンテキストのオリジンによって、どの共有ストレージが読み取られるかが決まります。
共有ストレージからの削除
共有ストレージからの削除は、ワークレットの内外から JavaScript を使用して、または delete()
でレスポンス ヘッダーを使用して実行できます。すべてのキーを一度に削除するには、どちらかの clear()
を使用します。
JavaScript を使用している場合
ワークレットの外部から共有ストレージから削除するには:
window.sharedStorage.delete('myKey');
ワークレット内から共有ストレージから削除するには:
sharedStorage.delete('myKey');
ワークレットの外部からすべてのキーを一度に削除するには:
window.sharedStorage.clear();
ワークレット内からすべてのキーを一度に削除するには:
sharedStorage.clear();
レスポンス ヘッダーの使用
レスポンス ヘッダーを使用して値を削除するには、レスポンス ヘッダーで
Shared-Storage-Write
を使用して、削除するキーを渡すこともできます。delete;key="myKey"
レスポンス ヘッダーを使用してすべてのキーを削除するには:
clear;
共有ストレージから Protected Audience インタレスト グループを読み取る
Protected Audience のインタレスト グループは、共有ストレージ ワークレットから読み取ることができます。interestGroups()
メソッドは、AuctionInterestGroup 属性と GenerateBidInterestGroup 属性を含む StorageInterestGroup オブジェクトの配列を返します。
次の例は、ブラウジング コンテキストのインタレスト グループを読み取る方法と、取得したインタレスト グループに対して実行できるオペレーションを示しています。使用できるオペレーションは、インタレスト グループの数の検索と、入札数が一番多いインタレスト グループの検索の 2 つです。
async function analyzeInterestGroups() {
const interestGroups = await interestGroups();
numIGs = interestGroups.length;
maxBidCountIG = interestGroups.reduce((max, cur) => { return cur.bidCount > max.bidCount ? cur : max; }, interestGroups[0]);
console.log("The IG that bid the most has name " + maxBidCountIG.name);
}
デフォルトで読み取られるインタレスト グループのオリジンは、ワークレット モジュールが読み込まれたブラウジング コンテキストのオリジンによって決まります。デフォルトのワークレット オリジンとその変更方法について詳しくは、Shared Storage API のチュートリアルの「Shared Storage と Private Aggregation の実行」セクションをご覧ください。
オプション
すべての共有ストレージ修飾子メソッドは、最後の引数としてオプションのオプション オブジェクトをサポートしています。
withLock
withLock
オプションは省略可能です。このオプションを指定すると、このオプションは、続行する前に Web Locks API を使用して定義済みリソースのロックを確保するようにメソッドに指示します。ロックをリクエストするときにロック名が渡されます。この名前は、オリジン内の複数のタブ、ワーカー、コード間で使用が調整されるリソースを表します。
withLock
オプションは、次の共有ストレージ修飾子メソッドで使用できます。
- set
- append
- delete
- クリア
- バッチ アップデート
ロックは、JavaScript またはレスポンス ヘッダーを使用して設定できます。
JavaScript を使用している場合
sharedStorage.set('myKey', 'myValue', { withLock: 'myResource' });
レスポンス ヘッダーの使用
Shared-Storage-Write : set;key="myKey";value="myValue";with_lock="myResource"
Shared Storage ロックは、データの送信元によってパーティショニングされます。ロックは、window
コンテキストか worker
コンテキストかにかかわらず、LockManager の request() メソッドを使用して取得されたロックとは独立しています。ただし、SharedStorageWorklet コンテキスト内で request()
を使用して取得されたロックと同じスコープを共有します。
request()
メソッドではさまざまな構成オプションを使用できますが、共有ストレージ内で取得されたロックは常に次のデフォルト設定に従います。
mode: "exclusive"
: 同じ名前の他のロックを同時に保持することはできません。steal: false
: 他のリクエストに対応するために、同じ名前の既存のロックは解放されません。ifAvailable: false
: ロックが使用可能になるまでリクエストは無期限に待機します。
withLock
を使用するタイミング
ロックは、複数のワークレットが同時に実行され、それぞれが同じデータを参照している場合(ページ上の複数のワークレット、または異なるタブの複数のワークレットなど)に便利です。このようなシナリオでは、関連するワークレット コードをロックでラップして、一度に 1 つのワークレットのみがレポートを処理するようにすることをおすすめします。
ロックが便利なもう 1 つの状況は、ワークレットで一緒に読み取る必要がある複数のキーがあり、その状態を同期する必要がある場合です。その場合は、get
呼び出しをロックでラップし、これらのキーへの書き込み時に同じロックを取得する必要があります。
ロックの順序
ウェブルックの性質上、修飾子メソッドが定義した順序で実行されないことがあります。最初のオペレーションでロックが必要になり、ロックが遅延すると、最初のオペレーションが完了する前に 2 つ目のオペレーションが開始される可能性があります。
次に例を示します。
// This line might pause until the lock is available.
sharedStorage.set('keyOne', 'valueOne', { withLock: 'resource-lock' });
// This line will run right away, even if the first one is still waiting.
sharedStorage.set('keyOne', 'valueTwo');
複数のキーを変更する例
この例では、ロックを使用して、ワークレット内の読み取りオペレーションと削除オペレーションが同時に実行され、ワークレット外からの干渉を防ぎます。
次の modify-multiple-keys.js
の例では、modify-lock
を使用して keyOne
と keyTwo
の新しい値を設定し、ワークレットから modify-multiple-keys
オペレーションを実行します。
// modify-multiple-keys.js
sharedStorage.batchUpdate([
new SharedStorageSetMethod('keyOne', calculateValueFor('keyOne')),
new SharedStorageSetMethod('keyTwo', calculateValueFor('keyTwo'))
], { withLock: 'modify-lock' });
const modifyWorklet = await sharedStorage.createWorklet('modify-multiple-keys-worklet.js');
await modifyWorklet.run('modify-multiple-keys');
次に、modify-multiple-keys-worklet.js
内で navigator.locks.request()
を使用してロックをリクエストし、必要に応じてキーを読み取り、変更できます。
// modify-multiple-keys-worklet.js
class ModifyMultipleKeysOperation {
async run(data) {
await navigator.locks.request('modify-lock', async (lock) => {
const value1 = await sharedStorage.get('keyOne');
const value2 = await sharedStorage.get('keyTwo');
// Do something with `value1` and `value2` here.
await sharedStorage.delete('keyOne');
await sharedStorage.delete('keyTwo');
});
}
}
register('modify-multiple-keys', ModifyMultipleKeysOperation);
コンテキストの切り替え
共有ストレージ データは、呼び出しが発生したブラウジング コンテキストのオリジン(https://example.adtech.com など)に書き込まれます。
<script>
タグを使用してサードパーティ コードを読み込むと、コードは埋め込み元のブラウジング コンテキストで実行されます。したがって、サードパーティ コードが sharedStorage.set()
を呼び出すと、データは埋め込み元の共有ストレージに書き込まれます。iframe 内にサードパーティ コードを読み込むと、コードは新しいブラウジング コンテキストを受け取ります。そのオリジンは iframe のオリジンです。したがって、iframe から行われた sharedStorage.set()
呼び出しは、iframe オリジンの共有ストレージにデータを保存します。
ファーストパーティ コンテキスト
ファーストパーティ ページに sharedStorage.set()
または sharedStorage.delete()
を呼び出すサードパーティの JavaScript コードが埋め込まれている場合、Key-Value ペアはファーストパーティ コンテキストに保存されます。

サードパーティのコンテキスト
Key-Value ペアを広告テクノロジーまたはサードパーティのコンテキストに保存するには、iframe を作成し、iframe 内から JavaScript コードで set()
または delete()
を呼び出します。

Private Aggregation API
Shared Storage に保存されている集計可能なデータを測定するには、Private Aggregation API を使用します。
レポートを作成するには、バケットと値を指定してワークレット内で contributeToHistogram()
を呼び出します。バケットは符号なし 128 ビット整数で表され、BigInt
として関数に渡す必要があります。値は正の整数です。
プライバシーを保護するため、バケットと値を含むレポートのペイロードは転送中に暗号化されます。このペイロードを復号して集計できるのは、集計サービスを使用する場合のみです。
また、ブラウザは、サイトが出力クエリに提供できる貢献度も制限します。具体的には、貢献度予算により、特定のブラウザの特定の期間における、すべてのバケットにわたる単一サイトからのすべてのレポートの合計が制限されます。現在の予算を超えている場合、レポートは生成されません。
privateAggregation.contributeToHistogram({
bucket: BigInt(myBucket),
value: parseInt(myBucketValue)
});
共有ストレージと非公開集計の実行
共有ストレージからデータにアクセスするには、ワークレットを作成する必要があります。これを行うには、ワークレットの URL を指定して createWorklet()
を呼び出します。デフォルトでは、createWorklet()
で共有ストレージを使用する場合、データ パーティションのオリジンは、ワークレット スクリプト自体のオリジンではなく、呼び出し元のブラウジング コンテキストのオリジンになります。
デフォルトの動作を変更するには、createWorklet
を呼び出すときに dataOrigin
プロパティを設定します。
dataOrigin: "context-origin"
: (デフォルト)データは、呼び出し元のブラウジング コンテキストのオリジンの共有ストレージに保存されます。dataOrigin: "script-origin"
: データは、ワークレット スクリプトのオリジンの共有ストレージに保存されます。このモードを有効にするには、オプトインする必要があります。
sharedStorage.createWorklet(scriptUrl, {dataOrigin: "script-origin"});
オプトインするには、"script-origin"
を使用するときに、スクリプト エンドポイントがヘッダー Shared-Storage-Cross-Origin-Worklet-Allowed
で応答する必要があります。クロスオリジン リクエストでは CORS を有効にする必要があります。
Shared-Storage-Cross-Origin-Worklet-Allowed : ?1
クロスオリジン iframe の使用
共有ストレージ ワークレットを呼び出すには iframe が必要です。
広告の iframe で、addModule()
を呼び出してワークレット モジュールを読み込みます。sharedStorageWorklet.js
ワークレット ファイルに登録されているメソッドを実行するには、同じ広告 iframe JavaScript で sharedStorage.run()
を呼び出します。
const sharedStorageWorklet = await window.sharedStorage.createWorklet(
'https://any-origin.example/modules/sharedStorageWorklet.js'
);
await sharedStorageWorklet.run('shared-storage-report', {
data: { campaignId: '1234' },
});
ワークレット スクリプトでは、非同期の run
メソッドを持つクラスを作成し、register
して広告の iframe で実行する必要があります。sharedStorageWorklet.js
内:
class SharedStorageReportOperation {
async run(data) {
// Other code goes here.
bucket = getBucket(...);
value = getValue(...);
privateAggregation.contributeToHistogram({
bucket,
value
});
}
}
register('shared-storage-report', SharedStorageReportOperation);
クロスオリジン リクエストの使用
Shared Storage と Private Aggregation を使用すると、クロスオリジン iframe を使用せずにクロスオリジン ワークレットを作成できます。
ファーストパーティ ページは、クロスオリジン JavaScript エンドポイントへの createWorklet()
呼び出しを呼び出すこともできます。ワークレットを作成するときに、ワークレットのデータ パーティションのオリジンをスクリプト オリジンに設定する必要があります。
async function crossOriginCall() {
const privateAggregationWorklet = await sharedStorage.createWorklet(
'https://cross-origin.example/js/worklet.js',
{ dataOrigin: 'script-origin' }
);
await privateAggregationWorklet.run('pa-worklet');
}
crossOriginCall();
クロスオリジンの JavaScript エンドポイントは、Shared-Storage-Cross-Origin-Worklet-Allowed
ヘッダーで応答し、リクエストで CORS が有効になっていることを示す必要があります。
Shared-Storage-Cross-Origin-Worklet-Allowed : ?1
createWorklet()
を使用して作成されたワークレットには、selectURL
と run()
があります。addModule()
は使用できません。
class CrossOriginWorklet {
async run(data){
// Other code goes here.
bucket = getBucket(...);
value = getValue(...);
privateAggregation.contributeToHistogram({
bucket,
value
});
}
}
次のステップ
以降のページでは、Shared Storage API と Private Aggregation API の重要な点について説明します。
- 共有ストレージの概要(デベロッパー向け Chrome)
- 共有ストレージのユースケース(デベロッパー向け Chrome)
- 限定公開集計の概要(デベロッパー向け Chrome)
- 共有ストレージの説明(GitHub)
- 非公開集計の説明(GitHub)
- Shared Storage と Private Aggregation のデモ
API に慣れたら、レポートの収集を開始できます。レポートは、リクエスト本文の JSON として次のエンドポイントに POST リクエストとして送信されます。
- デバッグ レポート -
context-origin/.well-known/private-aggregation/debug/report-shared-storage
- レポート -
context-origin/.well-known/private-aggregation/report-shared-storage
レポートが収集されたら、ローカルテストツールを使用してテストするか、集計サービス用の高信頼実行環境を設定して集計レポートを取得できます。
フィードバックをお寄せください
API とドキュメントに関するフィードバックは GitHub で共有できます。