Guide de démarrage rapide pour l'implémentation du stockage partagé et de l'agrégation privée

Ce document est un guide de démarrage rapide pour utiliser Shared Storage et Private Aggregation. Vous devez connaître les deux API, car Shared Storage stocke les valeurs et Private Aggregation crée les rapports agrégables.

Cible:technologies publicitaires et fournisseurs de solutions de mesure.

API Shared Storage

Pour empêcher le suivi intersites, les navigateurs ont commencé à partitionner toutes les formes de stockage, y compris le stockage local, les cookies, etc. Toutefois, il existe des cas d'utilisation où un stockage non partitionné est nécessaire. L'API Shared Storage fournit un accès en écriture illimité sur différents sites de premier niveau avec un accès en lecture protégeant la confidentialité.

Le stockage partagé est limité à l'origine du contexte (l'appelant de sharedStorage).

Le stockage partagé est limité en termes de capacité par origine, et chaque entrée est limitée à un nombre maximal de caractères. Si la limite est atteinte, aucune autre entrée n'est stockée. Les limites de stockage des données sont décrites dans la présentation de Shared Storage.

Appeler le stockage partagé

Les technologies publicitaires peuvent écrire dans Shared Storage à l'aide de JavaScript ou d'en-têtes de réponse. La lecture à partir du stockage partagé ne se produit que dans un environnement JavaScript isolé appelé "worklet".

  • À l'aide de JavaScript Les technologies publicitaires peuvent effectuer des fonctions de stockage partagé spécifiques, telles que le paramétrage, l'ajout et la suppression de valeurs en dehors d'un worklet JavaScript. Toutefois, les fonctions telles que la lecture de Shared Storage et l'exécution d'une agrégation privée doivent être effectuées via un worklet JavaScript. Vous trouverez les méthodes pouvant être utilisées en dehors d'un worklet JavaScript dans la section Proposed API Surface - Outside the worklet (Proposed API Surface - Outside the worklet).

    Les méthodes utilisées dans le worklet lors d'une opération se trouvent dans la section Proposed API Surface - In the worklet (Surface de l'API proposée : dans le worklet).

  • Utiliser des en-têtes de réponse

    Comme en JavaScript, seules des fonctions spécifiques telles que la définition, l'ajout et la suppression de valeurs dans Shared Storage peuvent être effectuées à l'aide d'en-têtes de réponse. Pour utiliser Shared Storage dans un en-tête de réponse, Shared-Storage-Writable: ?1 doit être inclus dans l'en-tête de la requête.

    Pour lancer une requête à partir du client, exécutez le code suivant, en fonction de la méthode choisie:

    • Utiliser fetch()

      fetch("https://a.example/path/for/updates", {sharedStorageWritable: true});
      
    • Utiliser une balise iframe ou img

      <iframe src="https://a.example/path/for/updates" sharedstoragewritable></iframe>
      
    • Utiliser un attribut IDL avec une balise iframe ou img

      let iframe = document.getElementById("my-iframe");
      iframe.sharedStorageWritable = true;
      iframe.src = "https://a.example/path/for/updates";
      

Pour en savoir plus, consultez Shared Storage: Response Headers (Stockage partagé : en-têtes de réponse).

Écrire dans Shared Storage

Pour écrire dans Shared Storage, appelez sharedStorage.set() à l'intérieur ou à l'extérieur d'un worklet JavaScript. Si appelé en dehors du worklet, les données sont écrites à l'origine du contexte de navigation à partir duquel l'appel a été effectué. Si elle est appelée depuis le worklet, les données sont écrites à l'origine du contexte de navigation qui a chargé le worklet. Les clés définies ont une date d'expiration de 30 jours à compter de la dernière mise à jour.

Le champ ignoreIfPresent est facultatif. Si elle est présente et définie sur true, la clé n'est pas mise à jour si elle existe déjà. L'expiration de la clé est renouvelée pour 30 jours à compter de l'appel set(), même si la clé n'est pas mise à jour.

Si le stockage partagé est consulté plusieurs fois lors du chargement d'une même page avec la même clé, la valeur de la clé est écrasée. Il est conseillé d'utiliser sharedStorage.append() si la clé doit conserver la valeur précédente.

  • À l'aide de JavaScript

    En dehors du widget de travail:

    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'}
    

    De même, dans le worklet:

    sharedStorage.set('myKey', 'myValue1', { ignoreIfPresent: true });
    
  • Utiliser des en-têtes de réponse

    Vous pouvez également écrire dans Shared Storage à l'aide d'en-têtes de réponse. Pour ce faire, utilisez Shared-Storage-Write dans l'en-tête de réponse avec les commandes suivantes:

    Shared-Storage-Write : set;key="myKey";value="myValue";ignore_if_present
    
    Shared-Storage-Write : set;key="myKey";value="myValue";ignore_if_present=?0
    

    Vous pouvez séparer plusieurs éléments par une virgule et combiner set, append, delete et clear.

    Shared-Storage-Write :
    set;key="hello";value="world";ignore_if_present, set;key="good";value="bye"
    

Ajouter une valeur

Vous pouvez ajouter une valeur à une clé existante à l'aide de la méthode d'ajout. Si la clé n'existe pas, l'appel de append() crée la clé et définit la valeur. Pour ce faire, vous pouvez utiliser JavaScript ou des en-têtes de réponse.

  • À l'aide de JavaScript

    Pour mettre à jour les valeurs des clés existantes, utilisez sharedStorage.append() à l'intérieur ou à l'extérieur du worklet.

    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'}
    

    Pour ajouter des données dans le worklet:

    sharedStorage.append('myKey', 'myValue1');
    
  • Utiliser des en-têtes de réponse

    Comme pour définir une valeur dans Shared Storage, vous pouvez utiliser Shared-Storage-Write dans l'en-tête de réponse pour transmettre la paire clé-valeur.

    Shared-Storage-Write : append;key="myKey";value="myValue2"
    

Mise à jour groupée des valeurs

Vous pouvez appeler sharedStorage.batchUpdate() à partir ou en dehors d'un worklet JavaScript et transmettre un tableau ordonné de méthodes qui spécifient les opérations choisies. Chaque constructeur de méthode accepte les mêmes paramètres que la méthode individuelle correspondante pour les opérations de définition, d'ajout, de suppression et d'effacement.

Vous pouvez définir le verrouillage à l'aide de JavaScript ou de l'en-tête de réponse:

  • À l'aide de JavaScript

    Les méthodes JavaScript disponibles avec batchUpdate() sont les suivantes:

    • SharedStorageSetMethod(): écrit une paire clé-valeur dans Shared Storage.
    • SharedStorageAppendMethod(): ajoute une valeur à une clé existante dans Shared Storage.
    • SharedStorageDeleteMethod(): supprime une paire clé-valeur du stockage partagé.
    • SharedStorageClearMethod(): efface toutes les clés du stockage partagé.
    sharedStorage.batchUpdate([
    new SharedStorageSetMethod('keyOne', 'valueOne'),
    new SharedStorageAppendMethod('keyTwo', 'valueTwo'),
    new SharedStorageDeleteMethod('keyThree'),
    new SharedStorageClearMethod()
    ]);
    
  • Utiliser des en-têtes de réponse

    Shared-Storage-Write : batchUpdate;methods="set;key=keyOne;value=valueOne, append;key=keyTwo;value=valueTwo,delete;key=keyThree,clear"
    

Lire à partir du stockage partagé

Vous ne pouvez lire les données du stockage partagé qu'à partir d'un worklet.

await sharedStorage.get('mykey');

L'origine du contexte de navigation à partir duquel le module de worklet a été chargé détermine le stockage partagé qui est lu.

Supprimer de l'espace de stockage partagé

Vous pouvez effectuer des suppressions à partir de Shared Storage à l'aide de JavaScript, que ce soit à l'intérieur ou à l'extérieur du worklet, ou en utilisant des en-têtes de réponse avec delete(). Pour supprimer toutes les clés en même temps, utilisez clear() dans l'un ou l'autre.

  • À l'aide de JavaScript

    Pour supprimer des éléments du stockage partagé en dehors du worklet:

    window.sharedStorage.delete('myKey');
    

    Pour supprimer des éléments du stockage partagé depuis le worklet:

    sharedStorage.delete('myKey');
    

    Pour supprimer toutes les clés en même temps en dehors du worklet:

    window.sharedStorage.clear();
    

    Pour supprimer toutes les clés en une seule fois depuis le worklet:

    sharedStorage.clear();
    
  • Utiliser des en-têtes de réponse

    Pour supprimer des valeurs à l'aide d'en-têtes de réponse, vous pouvez également utiliser Shared-Storage-Write dans l'en-tête de réponse pour transmettre la clé à supprimer.

    delete;key="myKey"
    

    Pour supprimer toutes les clés à l'aide d'en-têtes de réponse:

    clear;
    

Lire les groupes d'intérêt Protected Audience à partir de Shared Storage

Vous pouvez lire les groupes de centres d'intérêt de Protected Audience à partir d'un worklet Shared Storage. La méthode interestGroups() renvoie un tableau d'objets StorageInterestGroup, y compris les attributs AuctionInterestGroup et GenerateBidInterestGroup.

L'exemple suivant montre comment lire les groupes d'intérêts du contexte de navigation et certaines opérations pouvant être effectuées sur les groupes d'intérêts récupérés. Deux opérations sont possibles : trouver le nombre de groupes de centres d'intérêt et trouver le groupe de centres d'intérêt ayant le plus grand nombre d'enchères.

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);
}

L'origine du contexte de navigation à partir duquel le module de travaillet a été chargé détermine l'origine des groupes d'intérêt lus par défaut. Pour en savoir plus sur l'origine par défaut du worklet et comment la modifier, consultez la section Exécuter Shared Storage et Private Aggregation dans le tutoriel de l'API Shared Storage.

Options

Toutes les méthodes de modificateur de stockage partagé acceptent un objet d'options facultatif comme dernier argument.

withLock

L'option withLock est facultative. Si elle est spécifiée, cette option indique à la méthode d'acquérir un verrouillage pour la ressource définie à l'aide de l'API Web Locks avant de continuer. Un nom de serrure est transmis lors de la demande de verrouillage. Le nom représente une ressource dont l'utilisation est coordonnée entre plusieurs onglets,nœuds de calcul ou code au sein de l'origine.

L'option withLock peut être utilisée avec les méthodes de modificateur de stockage partagé suivantes:

  • set
  • append
  • supprimer
  • effacer
  • mise à jour groupée

Vous pouvez définir le verrouillage à l'aide de JavaScript ou de l'en-tête de réponse:

  • À l'aide de JavaScript

    sharedStorage.set('myKey', 'myValue', { withLock: 'myResource' });
    
  • Utiliser des en-têtes de réponse

    Shared-Storage-Write : set;key="myKey";value="myValue";with_lock="myResource"
    

Les verrous Shared Storage sont partitionnés en fonction de l'origine des données. Les verrous sont indépendants de tous les verrous obtenus à l'aide de la méthode request() de LockManager, que ce soit dans un contexte window ou worker. Toutefois, ils partagent la même portée que les verrous obtenus à l'aide de request() dans le contexte SharedStorageWorklet.

Bien que la méthode request() offre différentes options de configuration, les verrous acquis dans Shared Storage respectent toujours les paramètres par défaut suivants:

  • mode: "exclusive": aucun autre verrou portant le même nom ne peut être détenu simultanément.
  • steal: false: les verrous existants portant le même nom ne sont pas libérés pour répondre à d'autres requêtes.
  • ifAvailable: false: les requêtes attendent indéfiniment jusqu'à ce que le verrouillage soit disponible.
Dans quel contexte utiliser withLock ?

Les verrous sont utiles dans les scénarios où plusieurs worklets peuvent s'exécuter simultanément (par exemple, plusieurs worklets sur une page ou dans différents onglets), chacun d'eux examinant les mêmes données. Dans ce scénario, il est judicieux d'encapsuler le code de travaillet approprié avec un verrouillage pour s'assurer qu'un seul travaillet traite les rapports à la fois.

Les serrures sont également utiles si plusieurs clés doivent être lues ensemble dans un worklet et que leur état doit être synchronisé. Dans ce cas, vous devez encapsuler les appels get avec un verrou et vous assurer d'acquérir le même verrou lorsque vous écrivez sur ces clés.

Ordre des serrures

En raison de la nature des verrous Web, les méthodes de modification peuvent ne pas s'exécuter dans l'ordre que vous avez défini. Si la première opération nécessite un verrouillage et qu'elle est retardée, la deuxième opération peut commencer avant la fin de la première.

Par exemple :

// 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');
Exemple de modification de plusieurs clés

Cet exemple utilise un verrou pour s'assurer que les opérations de lecture et de suppression dans le worklet se produisent ensemble, ce qui empêche toute interférence extérieure au worklet.

L'exemple modify-multiple-keys.js suivant définit de nouvelles valeurs pour keyOne et keyTwo avec modify-lock, puis exécute l'opération modify-multiple-keys à partir du worklet:

// 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');

Ensuite, dans modify-multiple-keys-worklet.js, vous pouvez demander le verrouillage à l'aide de navigator.locks.request() pour lire et modifier les clés si nécessaire.

// 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);

Changement de contexte

Les données de stockage partagé sont écrites dans l'origine (par exemple, https://example.adtech.com) du contexte de navigation à partir duquel l'appel a été effectué.

Lorsque vous chargez le code tiers à l'aide d'une balise <script>, le code est exécuté dans le contexte de navigation de l'intégrateur. Par conséquent, lorsque le code tiers appelle sharedStorage.set(), les données sont écrites dans l'espace de stockage partagé de l'intégrateur. Lorsque vous chargez le code tiers dans un élément iFrame, le code reçoit un nouveau contexte de navigation et son origine est celle de l'élément iFrame. Par conséquent, l'appel sharedStorage.set() effectué à partir de l'iFrame stocke les données dans le stockage partagé de l'origine de l'iFrame.

Contexte first party

Si une page propriétaire intègre du code JavaScript tiers qui appelle sharedStorage.set() ou sharedStorage.delete(), la paire clé-valeur est stockée dans le contexte propriétaire.

Données stockées sur une page first party avec du code JavaScript tiers intégré.

Contexte tiers

La paire clé-valeur peut être stockée dans le contexte de la technologie publicitaire ou tiers en créant une iFrame et en appelant set() ou delete() dans le code JavaScript à partir de l'iFrame.

Données stockées dans le contexte de la technologie publicitaire ou tiers.

API Private Aggregation

Pour mesurer les données agrégables stockées dans Shared Storage, vous pouvez utiliser l'API Private Aggregation.

Pour créer un rapport, appelez contributeToHistogram() dans un worklet avec un bucket et une valeur. Le bucket est représenté par un entier non signé de 128 bits qui doit être transmis à la fonction en tant que BigInt. La valeur est un entier positif.

Pour protéger la confidentialité, la charge utile du rapport, qui contient le bucket et la valeur, est chiffrée en transit et ne peut être déchiffrée et agrégée qu'à l'aide du service d'agrégation.

Le navigateur limite également les contributions qu'un site peut apporter à une requête de sortie. Plus précisément, le budget de contribution limite le total de tous les rapports d'un même site pour un navigateur donné au cours d'une période donnée pour tous les buckets. Si le budget actuel est dépassé, aucun rapport ne sera généré.

privateAggregation.contributeToHistogram({
  bucket: BigInt(myBucket),
  value: parseInt(myBucketValue)
});

Exécuter Shared Storage et Private Aggregation

Vous devez créer un worklet pour accéder aux données du stockage partagé. Pour ce faire, appelez createWorklet() avec l'URL du worklet. Par défaut, lorsque vous utilisez un stockage partagé avec createWorklet(), l'origine de la partition de données correspond à l'origine du contexte de navigation appelé, et non à l'origine du script de worklet lui-même.

Pour modifier le comportement par défaut, définissez la propriété dataOrigin lorsque vous appelez createWorklet.

  • dataOrigin: "context-origin": (par défaut) les données sont stockées dans l'espace de stockage partagé de l'origine du contexte de navigation appelé.
  • dataOrigin: "script-origin": les données sont stockées dans l'espace de stockage partagé de l'origine du script de travail. Notez que vous devez activer ce mode pour pouvoir l'utiliser.
sharedStorage.createWorklet(scriptUrl, {dataOrigin: "script-origin"});

Pour activer cette fonctionnalité, lorsque vous utilisez "script-origin", le point de terminaison du script doit répondre avec l'en-tête Shared-Storage-Cross-Origin-Worklet-Allowed. Notez que CORS doit être activé pour les requêtes multi-origines.

Shared-Storage-Cross-Origin-Worklet-Allowed : ?1

Utiliser un iFrame inter-origines

Un iframe est nécessaire pour appeler le worklet de stockage partagé.

Dans l'iframe de l'annonce, chargez le module de travaillet en appelant addModule(). Pour exécuter la méthode enregistrée dans le fichier de worklet sharedStorageWorklet.js, dans le même code JavaScript de l'iFrame d'annonce, appelez sharedStorage.run().

const sharedStorageWorklet = await window.sharedStorage.createWorklet(
  'https://any-origin.example/modules/sharedStorageWorklet.js'
);
await sharedStorageWorklet.run('shared-storage-report', {
  data: { campaignId: '1234' },
});

Dans le script du worklet, vous devez créer une classe avec une méthode run asynchrone et register pour l'exécuter dans l'iframe de l'annonce. Dans sharedStorageWorklet.js:

class SharedStorageReportOperation {
  async run(data) {
    // Other code goes here.
    bucket = getBucket(...);
    value = getValue(...);
    privateAggregation.contributeToHistogram({
      bucket,
      value
    });
  }
}
register('shared-storage-report', SharedStorageReportOperation);

Utiliser une requête multi-origines

Shared Storage et Private Aggregation permettent de créer des worklets multi-origines sans avoir besoin d'iFrames multi-origines.

La page propriétaire peut également appeler un appel createWorklet() au point de terminaison JavaScript inter-origine. Vous devez définir l'origine de la partition de données du worklet sur celle de l'origine du script lorsque vous créez le worklet.

async function crossOriginCall() {
  const privateAggregationWorklet = await sharedStorage.createWorklet(
    'https://cross-origin.example/js/worklet.js',
    { dataOrigin: 'script-origin' }
  );
  await privateAggregationWorklet.run('pa-worklet');
}
crossOriginCall();

Le point de terminaison JavaScript inter-origines doit répondre avec les en-têtes Shared-Storage-Cross-Origin-Worklet-Allowed et noter que le CORS est activé pour la requête.

Shared-Storage-Cross-Origin-Worklet-Allowed : ?1

Les worklets créés à l'aide de createWorklet() auront selectURL et run(). addModule() n'est pas disponible pour cela.

class CrossOriginWorklet {
  async run(data){
    // Other code goes here.
    bucket = getBucket(...);
    value = getValue(...);
    privateAggregation.contributeToHistogram({
      bucket,
      value
    });
  }
}

Étapes suivantes

Les pages suivantes expliquent les aspects importants des API Shared Storage et Private Aggregation.

Une fois que vous avez pris connaissance des API, vous pouvez commencer à collecter les rapports, qui sont envoyés sous forme de requête POST aux points de terminaison suivants au format JSON dans le corps de la requête.

  • Rapports de débogage - context-origin/.well-known/private-aggregation/debug/report-shared-storage
  • Rapports - context-origin/.well-known/private-aggregation/report-shared-storage

Une fois les rapports collectés, vous pouvez effectuer des tests à l'aide de l'outil de test local ou configurer l'environnement d'exécution sécurisé pour le service d'agrégation afin d'obtenir les rapports agrégés.

Envoyer des commentaires

Vous pouvez partager vos commentaires sur les API et la documentation sur GitHub.