Este documento es una guía de inicio rápido para usar Shared Storage y Private Aggregation. Deberás comprender ambas APIs, ya que Shared Storage almacena los valores y Private Aggregation crea los informes agregables.
Público objetivo: Proveedores de tecnología publicitaria y medición.
API de Shared Storage
Para evitar el seguimiento entre sitios, los navegadores comenzaron a particionar todas las formas de almacenamiento, incluido el almacenamiento local, las cookies, etcétera. Sin embargo, hay casos de uso en los que se requiere almacenamiento no particionado. La API de Shared Storage proporciona acceso de escritura ilimitado en diferentes sitios de nivel superior con acceso de lectura que preserva la privacidad.
El almacenamiento compartido se restringe al origen del contexto (el llamador de sharedStorage
).
El almacenamiento compartido tiene un límite de capacidad por origen, y cada entrada está limitada a una cantidad máxima de caracteres. Si se alcanza el límite, no se almacenarán más entradas. Los límites de almacenamiento de datos se describen en la explicación del almacenamiento compartido.
Cómo invocar el almacenamiento compartido
Las tecnologías publicitarias pueden escribir en el almacenamiento compartido con JavaScript o encabezados de respuesta. La lectura del almacenamiento compartido solo se produce dentro de un entorno aislado de JavaScript llamado worklet.
Con JavaScript, las tecnologías publicitarias pueden realizar funciones específicas de almacenamiento compartido, como establecer, agregar y borrar valores fuera de un worklet de JavaScript. Sin embargo, las funciones como leer el almacenamiento compartido y realizar la agregación privada se deben completar a través de una worklet de JavaScript. Los métodos que se pueden usar fuera de una worklet de JavaScript se encuentran en Proposed API Surface - Outside the worklet.
Los métodos que se usan en la worklet durante una operación se pueden encontrar en Proposed API Surface - In the worklet.
Cómo usar encabezados de respuesta
Al igual que en JavaScript, solo se pueden realizar funciones específicas, como establecer, agregar y borrar valores en el almacenamiento compartido, con los encabezados de respuesta. Para trabajar con el almacenamiento compartido en un encabezado de respuesta, se debe incluir
Shared-Storage-Writable: ?1
en el encabezado de la solicitud.Para iniciar una solicitud desde el cliente, ejecuta el siguiente código, según el método que hayas elegido:
Usa
fetch()
fetch("https://a.example/path/for/updates", {sharedStorageWritable: true});
Usa una etiqueta
iframe
oimg
<iframe src="https://a.example/path/for/updates" sharedstoragewritable></iframe>
Usa un atributo IDL con una etiqueta
iframe
oimg
let iframe = document.getElementById("my-iframe"); iframe.sharedStorageWritable = true; iframe.src = "https://a.example/path/for/updates";
Puedes encontrar más información en Almacenamiento compartido: encabezados de respuesta.
Cómo escribir en el almacenamiento compartido
Para escribir en Shared Storage, llama a sharedStorage.set()
desde dentro o fuera de una worklet de JavaScript. Si se realiza una llamada desde fuera de la worklet, los datos se escriben en el origen del contexto de navegación desde el que se realizó la llamada. Si se llama desde dentro de la worklet, los datos se escriben en el origen del contexto de navegación que cargó la worklet. Las claves establecidas tienen una fecha de vencimiento de 30 días a partir de la última actualización.
El campo ignoreIfPresent
es opcional. Si está presente y se establece en true
, la clave no se actualiza si ya existe. El vencimiento de la clave se renueva a 30 días a partir de la llamada a set()
, incluso si la clave no se actualiza.
Si se accede al almacenamiento compartido varias veces en la misma carga de página con la misma clave, se reemplaza el valor de la clave. Es conveniente usar sharedStorage.append()
si la clave debe mantener el valor anterior.
Cómo usar JavaScript
Fuera de la worklet:
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'}
Del mismo modo, dentro de la worklet:
sharedStorage.set('myKey', 'myValue1', { ignoreIfPresent: true });
Cómo usar encabezados de respuesta
También puedes escribir en el almacenamiento compartido con encabezados de respuesta. Para ello, usa
Shared-Storage-Write
en el encabezado de respuesta junto con los siguientes comandos:Shared-Storage-Write : set;key="myKey";value="myValue";ignore_if_present
Shared-Storage-Write : set;key="myKey";value="myValue";ignore_if_present=?0
Se pueden separar varios elementos con comas y combinar
set
,append
,delete
yclear
.Shared-Storage-Write : set;key="hello";value="world";ignore_if_present, set;key="good";value="bye"
Cómo agregar un valor
Puedes adjuntar un valor a una clave existente con el método de adición. Si la clave
no existe, llamar a append()
crea la clave y establece el valor. Esto se puede lograr con JavaScript o encabezados de respuesta.
Cómo usar JavaScript
Para actualizar los valores de las claves existentes, usa
sharedStorage.append()
dentro o fuera de la 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'}
Para agregarlo dentro de la worklet, haz lo siguiente:
sharedStorage.append('myKey', 'myValue1');
Cómo usar encabezados de respuesta
Al igual que cuando estableces un valor en el almacenamiento compartido, puedes usar
Shared-Storage-Write
en el encabezado de respuesta para pasar el par clave-valor.Shared-Storage-Write : append;key="myKey";value="myValue2"
Actualización por lotes de valores
Puedes llamar a sharedStorage.batchUpdate()
desde dentro o fuera de una worklet de JavaScript y pasar un array ordenado de métodos que especifiquen las operaciones elegidas. Cada constructor de métodos acepta los mismos parámetros que su método individual correspondiente para establecer, agregar, borrar y borrar.
Puedes configurar el bloqueo con JavaScript o el encabezado de respuesta:
Cómo usar JavaScript
Entre los métodos de JavaScript disponibles que se pueden usar con
batchUpdate()
, se incluyen los siguientes:SharedStorageSetMethod()
: Escribe un par clave-valor en el almacenamiento compartido.SharedStorageAppendMethod()
: Agrega un valor a una clave existente en el almacenamiento compartido.SharedStorageDeleteMethod()
: Borra un par clave-valor del almacenamiento compartido.SharedStorageClearMethod()
: Borra todas las claves del almacenamiento compartido.
sharedStorage.batchUpdate([ new SharedStorageSetMethod('keyOne', 'valueOne'), new SharedStorageAppendMethod('keyTwo', 'valueTwo'), new SharedStorageDeleteMethod('keyThree'), new SharedStorageClearMethod() ]);
Cómo usar encabezados de respuesta
Shared-Storage-Write : batchUpdate;methods="set;key=keyOne;value=valueOne, append;key=keyTwo;value=valueTwo,delete;key=keyThree,clear"
Cómo leer desde el almacenamiento compartido
Solo puedes leer desde el almacenamiento compartido desde una worklet.
await sharedStorage.get('mykey');
El origen del contexto de navegación desde el que se cargó el módulo de la worklet determina cuyo almacenamiento compartido se lee.
Cómo borrar contenido del almacenamiento compartido
Puedes realizar eliminaciones desde el almacenamiento compartido con JavaScript desde dentro o fuera de la worklet, o bien con encabezados de respuesta con delete()
. Para borrar todas las claves a la vez, usa clear()
desde cualquiera de ellas.
Cómo usar JavaScript
Para borrar elementos del almacenamiento compartido desde fuera de la worklet, haz lo siguiente:
window.sharedStorage.delete('myKey');
Para borrar elementos del almacenamiento compartido desde la worklet, haz lo siguiente:
sharedStorage.delete('myKey');
Para borrar todas las claves de una sola vez desde fuera de la worklet, haz lo siguiente:
window.sharedStorage.clear();
Para borrar todas las claves a la vez desde dentro de la worklet, haz lo siguiente:
sharedStorage.clear();
Cómo usar encabezados de respuesta
Para borrar valores con encabezados de respuesta, también puedes usar
Shared-Storage-Write
en el encabezado de respuesta para pasar la clave que se borrará.delete;key="myKey"
Para borrar todas las claves con encabezados de respuesta, haz lo siguiente:
clear;
Cómo leer grupos de interés de Protected Audience desde el almacenamiento compartido
Puedes leer los grupos de interés de Protected Audience desde una tarea de Shared Storage. El método interestGroups()
muestra un array de objetos StorageInterestGroup, incluidos los atributos AuctionInterestGroup y GenerateBidInterestGroup.
En el siguiente ejemplo, se muestra cómo leer los grupos de intereses del contexto de navegación y algunas operaciones posibles que se podrían realizar en los grupos de intereses recuperados. Dos operaciones posibles que se utilizan son encontrar la cantidad de grupos de intereses y encontrar el grupo de intereses con el recuento de ofertas más alto.
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);
}
El origen del contexto de navegación desde el que se cargó el módulo de worklet determina el origen de los grupos de intereses que se leen de forma predeterminada. Para obtener más información sobre el origen predeterminado de la worklet y cómo cambiarlo, consulta la sección Ejecución de Shared Storage y Private Aggregation en la explicación de la API de Shared Storage.
Opciones
Todos los métodos de modificador de almacenamiento compartido admiten un objeto de opciones opcional como último argumento.
withLock
La opción withLock
es opcional. Si se especifica, esta opción le indica al método que adquiera un bloqueo para el recurso definido con la API de Web Locks antes de continuar. Se pasa un nombre de bloqueo cuando se solicita el bloqueo. El nombre representa un recurso cuyo uso se coordina en varias pestañas,trabajadores o códigos dentro del origen.
La opción withLock
se puede usar con los siguientes métodos de modificador de almacenamiento compartido:
- set
- append
- delete
- borrar
- actualización por lotes
Puedes configurar el bloqueo con JavaScript o el encabezado de respuesta:
Cómo usar JavaScript
sharedStorage.set('myKey', 'myValue', { withLock: 'myResource' });
Cómo usar encabezados de respuesta
Shared-Storage-Write : set;key="myKey";value="myValue";with_lock="myResource"
Los bloqueos de almacenamiento compartido se particionan según el origen de los datos. Los bloqueos son independientes de los bloqueos obtenidos con el método request() de LockManager, independientemente de si se encuentran en un contexto window
o worker
. Sin embargo, comparten el mismo alcance que los bloqueos obtenidos con request()
dentro del contexto de SharedStorageWorklet.
Si bien el método request()
permite varias opciones de configuración, los bloqueos adquiridos en el almacenamiento compartido siempre se adhieren a la siguiente configuración predeterminada:
mode: "exclusive"
: No se pueden mantener otros bloqueos con el mismo nombre de forma simultánea.steal: false
: Los bloqueos existentes con el mismo nombre no se liberan para adaptarse a otras solicitudes.ifAvailable: false
: Las solicitudes esperan de forma indefinida hasta que el bloqueo esté disponible.
Cuándo usar withLock
Los bloqueos son útiles en situaciones en las que puede haber varios worklets ejecutándose de forma simultánea (p.ej., varios worklets en una página o en diferentes pestañas) que analizan los mismos datos. En ese caso, es recomendable unir el código de la tarea relevante con un bloqueo para garantizar que solo una tarea procese informes a la vez.
Otra situación en la que las cerraduras son útiles es si hay varias claves que se deben leer juntas en una worklet y su estado debe sincronizarse. En ese caso, se deben unir las llamadas a get
con un bloqueo y asegurarse de adquirir el mismo bloqueo cuando se escriba en esas claves.
Orden de los bloqueos
Debido a la naturaleza de los bloqueos web, es posible que los métodos de modificador no se ejecuten en el orden que definiste. Si la primera operación requiere un bloqueo y se retrasa, es posible que la segunda operación comience antes de que finalice la primera.
Por ejemplo:
// 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');
Ejemplo de modificación de varias claves
En este ejemplo, se usa un bloqueo para garantizar que las operaciones de lectura y eliminación dentro de la worklet se realicen juntas, lo que evita interferencias desde fuera de la worklet.
En el siguiente ejemplo de modify-multiple-keys.js
, se establecen valores nuevos para keyOne
y keyTwo
con modify-lock
y, luego, se ejecuta la operación modify-multiple-keys
desde la 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');
Luego, dentro de modify-multiple-keys-worklet.js
, puedes solicitar el bloqueo con navigator.locks.request()
para leer y modificar las claves según sea necesario.
// 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);
Cambio de contexto
Los datos de almacenamiento compartido se escriben en el origen (por ejemplo, https://example.adtech.com) del contexto de navegación desde el que se originó la llamada.
Cuando cargas el código de terceros con una etiqueta <script>
, el código se ejecuta en el contexto de navegación del incorporador. Por lo tanto, cuando el código de terceros llama a sharedStorage.set()
, los datos se escriben en el almacenamiento compartido del incorporador. Cuando cargas el código de terceros dentro de un iframe, el código recibe
un nuevo contexto de navegación, y su origen es el del iframe. Por lo tanto, la llamada a sharedStorage.set()
que se realiza desde el iframe almacena los datos en el almacenamiento compartido del origen del iframe.
Contexto propio
Si una página propia tiene incorporado un código JavaScript de terceros que llama a sharedStorage.set()
o sharedStorage.delete()
, el par clave-valor se almacena en el contexto propio.

Contexto de terceros
Para almacenar el par clave-valor en la tecnología publicitaria o en el contexto de terceros, crea un iframe y llama a set()
o delete()
en el código JavaScript desde el iframe.

API de Private Aggregation
Para medir los datos agregables almacenados en Shared Storage, puedes usar la API de Private Aggregation.
Para crear un informe, llama a contributeToHistogram()
dentro de una worklet con un bucket y un valor. El bucket se representa con un número entero de 128 bits sin firma que se debe pasar a la función como un BigInt
. El valor es un número entero positivo.
Para proteger la privacidad, la carga útil del informe, que contiene el bucket y el valor, se encripta en tránsito y solo se puede desencriptar y agregar con el servicio de agregación.
El navegador también limitará las contribuciones que un sitio puede realizar a una consulta de salida. Específicamente, el presupuesto de contribución limita el total de todos los informes de un solo sitio para un navegador determinado en un período determinado en todos los buckets. Si se supera el presupuesto actual, no se generará un informe.
privateAggregation.contributeToHistogram({
bucket: BigInt(myBucket),
value: parseInt(myBucketValue)
});
Ejecución de Shared Storage y Private Aggregation
Debes crear una tarea para acceder a los datos del almacenamiento compartido. Para ello, llama a createWorklet()
con la URL de la worklet. De forma predeterminada, cuando se usa el almacenamiento compartido con createWorklet()
, el origen de la partición de datos será el origen del contexto de navegación que realiza la invocación, no el origen de la propia secuencia de comandos de la worklet.
Para cambiar el comportamiento predeterminado, configura la propiedad dataOrigin
cuando llames a createWorklet
.
dataOrigin: "context-origin"
: (Predeterminado) Los datos se almacenan en el almacenamiento compartido del origen del contexto de navegación de invocación.dataOrigin: "script-origin"
: Los datos se almacenan en el almacenamiento compartido del origen de la secuencia de comandos de la worklet. Ten en cuenta que debes habilitar este modo.
sharedStorage.createWorklet(scriptUrl, {dataOrigin: "script-origin"});
Para habilitar esta opción, cuando uses "script-origin"
, el extremo de la secuencia de comandos deberá responder con el encabezado Shared-Storage-Cross-Origin-Worklet-Allowed
. Ten en cuenta que
CORS debe estar habilitado para
solicitudes de origen cruzado.
Shared-Storage-Cross-Origin-Worklet-Allowed : ?1
Usa un iframe de origen cruzado
Se necesita un iframe para invocar la worklet de almacenamiento compartido.
En el iframe del anuncio, llama a addModule()
para cargar el módulo de worklet. Para ejecutar el método que está registrado en el archivo de worklet sharedStorageWorklet.js
, en el mismo código JavaScript del iframe del anuncio, llama a sharedStorage.run()
.
const sharedStorageWorklet = await window.sharedStorage.createWorklet(
'https://any-origin.example/modules/sharedStorageWorklet.js'
);
await sharedStorageWorklet.run('shared-storage-report', {
data: { campaignId: '1234' },
});
En la secuencia de comandos de la worklet, deberás crear una clase con un método run
asíncrono y register
para que se ejecute en el iframe del anuncio. Dentro de sharedStorageWorklet.js
:
class SharedStorageReportOperation {
async run(data) {
// Other code goes here.
bucket = getBucket(...);
value = getValue(...);
privateAggregation.contributeToHistogram({
bucket,
value
});
}
}
register('shared-storage-report', SharedStorageReportOperation);
Usa una solicitud de origen cruzado
Shared Storage y Private Aggregation permiten crear worklets de origen cruzado sin necesidad de iframes de origen cruzado.
La página propia también puede invocar una llamada createWorklet()
al extremo de JavaScript de origen cruzado. Cuando crees la worklet, deberás establecer el origen de la partición de datos
de la worklet como el de script-origin.
async function crossOriginCall() {
const privateAggregationWorklet = await sharedStorage.createWorklet(
'https://cross-origin.example/js/worklet.js',
{ dataOrigin: 'script-origin' }
);
await privateAggregationWorklet.run('pa-worklet');
}
crossOriginCall();
El extremo de JavaScript de origen cruzado deberá responder con los encabezados Shared-Storage-Cross-Origin-Worklet-Allowed
y tener en cuenta que el CORS está habilitado para la solicitud.
Shared-Storage-Cross-Origin-Worklet-Allowed : ?1
Los worklets creados con createWorklet()
tendrán selectURL
y run()
.
addModule()
no está disponible para esto.
class CrossOriginWorklet {
async run(data){
// Other code goes here.
bucket = getBucket(...);
value = getValue(...);
privateAggregation.contributeToHistogram({
bucket,
value
});
}
}
Próximos pasos
En las siguientes páginas, se explican aspectos importantes de las APIs de Shared Storage y Private Aggregation.
- Introducción al almacenamiento compartido (Chrome para desarrolladores)
- Casos de uso de almacenamiento compartido (Chrome para desarrolladores)
- Introducción a la agregación privada (Chrome para desarrolladores)
- Explicación del almacenamiento compartido (GitHub)
- Explicación de la agregación privada (GitHub)
- Demo de Shared Storage y Private Aggregation
Una vez que conozcas las APIs, puedes comenzar a recopilar los informes, que se envían como una solicitud POST a los siguientes extremos como JSON en el cuerpo de la solicitud.
- Informes de depuración:
context-origin/.well-known/private-aggregation/debug/report-shared-storage
- Informes:
context-origin/.well-known/private-aggregation/report-shared-storage
Una vez que se recopilen los informes, puedes realizar pruebas con la herramienta de pruebas local o configurar el entorno de ejecución confiable para el servicio de agregación para obtener los informes agregados.
Comparte tus comentarios
Puedes compartir tus comentarios sobre las APIs y la documentación en GitHub.