Este documento é um guia de início rápido para usar o Shared Storage e a Private Aggregation. Você precisa entender as duas APIs, porque o Shared Storage armazena os valores, e a Private Aggregation cria os relatórios agregáveis.
Público-alvo:empresas de adtechs e provedores de medição.
API Shared Storage
Para evitar o rastreamento entre sites, os navegadores começaram a particionar todas as formas de armazenamento, incluindo armazenamento local, cookies e assim por diante. No entanto, há casos de uso em que o armazenamento não particionado é necessário. A API Shared Storage oferece acesso de gravação ilimitado a diferentes sites de nível superior com acesso de leitura que preserva a privacidade.
O Shared Storage é restrito à origem do contexto (o autor da chamada de
sharedStorage
).
O armazenamento compartilhado tem um limite de capacidade por origem, com cada entrada limitada a um número máximo de caracteres. Se o limite for atingido, nenhuma outra entrada será armazenada. Os limites de armazenamento de dados estão descritos no explicador de armazenamento compartilhado.
Invocar o armazenamento compartilhado
As adtechs podem gravar no armazenamento compartilhado usando JavaScript ou cabeçalhos de resposta. A leitura do armazenamento compartilhado só ocorre em um ambiente JavaScript isolado chamado worklet.
Usar JavaScript: as adtechs podem executar funções específicas de armazenamento compartilhado, como definir, anexar e excluir valores fora de um worklet do JavaScript. No entanto, funções como ler o armazenamento compartilhado e realizar a agregação privada precisam ser concluídas usando um worklet JavaScript. Os métodos que podem ser usados fora de um worklet JavaScript podem ser encontrados em Proposed API Surface - Outside the worklet.
Os métodos usados no worklet durante uma operação podem ser encontrados em Proposed API Surface - In the worklet.
Como usar cabeçalhos de resposta
Assim como no JavaScript, apenas funções específicas, como definir, anexar e excluir valores no Shared Storage, podem ser realizadas usando cabeçalhos de resposta. Para trabalhar com o Shared Storage em um cabeçalho de resposta,
Shared-Storage-Writable: ?1
precisa ser incluído no cabeçalho da solicitação.Para iniciar uma solicitação do cliente, execute o código abaixo, dependendo do método escolhido:
Como usar o
fetch()
fetch("https://a.example/path/for/updates", {sharedStorageWritable: true});
Como usar uma tag
iframe
ouimg
<iframe src="https://a.example/path/for/updates" sharedstoragewritable></iframe>
Como usar um atributo IDL com uma tag
iframe
ouimg
let iframe = document.getElementById("my-iframe"); iframe.sharedStorageWritable = true; iframe.src = "https://a.example/path/for/updates";
Confira mais informações em Armazenamento compartilhado: cabeçalhos de resposta.
Como gravar no armazenamento compartilhado
Para gravar no Shared Storage, chame sharedStorage.set()
dentro ou fora de um
worklet do JavaScript. Se for chamado de fora do worklet, os dados serão gravados na
origem do contexto de navegação em que a chamada foi feita. Se forem chamados
dentro do worklet, os dados serão gravados na origem do contexto de navegação
que carregou o worklet. As chaves definidas têm uma data de validade de 30
dias a partir da última atualização.
O campo ignoreIfPresent
é opcional. Se estiver presente e definido como true
, a chave
não será atualizada se já existir. A validade da chave é renovada para 30 dias a partir
da chamada set()
, mesmo que a chave não seja atualizada.
Se o armazenamento compartilhado for acessado várias vezes na mesma carga de página com a mesma
chave, o valor dela será substituído. É recomendável usar
sharedStorage.append()
se a chave precisar manter o valor anterior.
Usando JavaScript
Fora do 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'}
Da mesma forma, dentro do worklet:
sharedStorage.set('myKey', 'myValue1', { ignoreIfPresent: true });
Como usar cabeçalhos de resposta
Também é possível gravar no armazenamento compartilhado usando cabeçalhos de resposta. Para fazer isso, use
Shared-Storage-Write
no cabeçalho de resposta com os seguintes comandos:Shared-Storage-Write : set;key="myKey";value="myValue";ignore_if_present
Shared-Storage-Write : set;key="myKey";value="myValue";ignore_if_present=?0
Vários itens podem ser separados por vírgulas e podem combinar
set
,append
,delete
eclear
.Shared-Storage-Write : set;key="hello";value="world";ignore_if_present, set;key="good";value="bye"
Como anexar um valor
É possível anexar um valor a uma chave usando o método de anexação. Se a chave
não existir, a chamada append()
vai criar a chave e definir o valor. Isso pode
ser feito usando JavaScript ou cabeçalhos de resposta.
Usando JavaScript
Para atualizar os valores das chaves atuais, use
sharedStorage.append()
dentro ou fora do 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 anexar dentro do worklet:
sharedStorage.append('myKey', 'myValue1');
Como usar cabeçalhos de resposta
Assim como na configuração de um valor no Armazenamento compartilhado, você pode usar o
Shared-Storage-Write
no cabeçalho de resposta para transmitir o par de chave-valor.Shared-Storage-Write : append;key="myKey";value="myValue2"
Atualização em lote de valores
É possível chamar sharedStorage.batchUpdate()
dentro ou fora de um worklet JavaScript e transmitir uma matriz ordenada de métodos que especificam as operações escolhidas. Cada construtor de método aceita os mesmos parâmetros que o método individual correspondente para definir, anexar, excluir e limpar.
É possível definir a trava usando JavaScript ou o cabeçalho de resposta:
Usando JavaScript
Os métodos JavaScript disponíveis que podem ser usados com
batchUpdate()
incluem:SharedStorageSetMethod()
: grava um par de chave-valor no armazenamento compartilhado.SharedStorageAppendMethod()
: anexa um valor a uma chave existente no armazenamento compartilhado.SharedStorageDeleteMethod()
: exclui um par de chave-valor do armazenamento compartilhado.SharedStorageClearMethod()
: limpa todas as chaves no armazenamento compartilhado.
sharedStorage.batchUpdate([ new SharedStorageSetMethod('keyOne', 'valueOne'), new SharedStorageAppendMethod('keyTwo', 'valueTwo'), new SharedStorageDeleteMethod('keyThree'), new SharedStorageClearMethod() ]);
Como usar cabeçalhos de resposta
Shared-Storage-Write : batchUpdate;methods="set;key=keyOne;value=valueOne, append;key=keyTwo;value=valueTwo,delete;key=keyThree,clear"
Como ler do armazenamento compartilhado
Só é possível ler do armazenamento compartilhado em um worklet.
await sharedStorage.get('mykey');
A origem do contexto de navegação em que o módulo de worklet foi carregado determina de quem o armazenamento compartilhado é lido.
Como excluir do armazenamento compartilhado
É possível excluir itens do armazenamento compartilhado usando JavaScript dentro
ou fora do worklet ou usando cabeçalhos de resposta com delete()
. Para excluir
todas as chaves de uma vez, use clear()
em qualquer uma delas.
Usando JavaScript
Para excluir do armazenamento compartilhado de fora do worklet:
window.sharedStorage.delete('myKey');
Para excluir do armazenamento compartilhado dentro do worklet:
sharedStorage.delete('myKey');
Para excluir todas as chaves de uma só vez fora do worklet:
window.sharedStorage.clear();
Para excluir todas as chaves de uma vez dentro do worklet:
sharedStorage.clear();
Como usar cabeçalhos de resposta
Para excluir valores usando cabeçalhos de resposta, você também pode usar
Shared-Storage-Write
no cabeçalho de resposta para transmitir a chave a ser excluída.delete;key="myKey"
Para excluir todas as chaves usando cabeçalhos de resposta:
clear;
Como ler grupos de interesse da API Protected Audience no Shared Storage
É possível ler os grupos de interesse da API Protected Audience em um worklet de armazenamento compartilhado. O método interestGroups()
retorna uma matriz de objetos StorageInterestGroup, incluindo os atributos AuctionInterestGroup e GenerateBidInterestGroup.
O exemplo a seguir mostra como ler os grupos de interesse do contexto de navegação e algumas operações possíveis que podem ser realizadas nos grupos de interesse recuperados. Duas operações possíveis são encontrar o número de grupos de interesse e o grupo de interesse com a contagem de lances mais alta.
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);
}
A origem do contexto de navegação em que o módulo do worklet foi carregado determina a origem dos grupos de interesse que estão sendo lidos por padrão. Para saber mais sobre a origem padrão do worklet e como mudá-la, consulte a seção Como executar a API Shared Storage e a Private Aggregation no tutorial da API Shared Storage.
Opções
Todos os métodos de modificador do Shared Storage oferecem suporte a um objeto de opções opcional como o último argumento.
withLock
A opção withLock
é opcional. Se especificada, essa opção instrui o método a adquirir uma trava para o recurso definido usando a API Web Locks antes de continuar. Um nome de bloqueio é transmitido ao solicitar o bloqueio. O nome representa um recurso cujo uso é coordenado em várias guias,workers ou códigos na origem.
A opção withLock
pode ser usada com os seguintes métodos de modificador de armazenamento compartilhado:
- set
- append
- excluir
- limpar
- atualização em lote
É possível definir a trava usando JavaScript ou o cabeçalho de resposta:
Usando JavaScript
sharedStorage.set('myKey', 'myValue', { withLock: 'myResource' });
Como usar cabeçalhos de resposta
Shared-Storage-Write : set;key="myKey";value="myValue";with_lock="myResource"
Os bloqueios do Armazenamento compartilhado são particionados pela origem dos dados. As fechaduras são independentes de qualquer fechadura obtida usando o método request() do LockManager, independentemente de estarem em um contexto window
ou worker
. No entanto, eles compartilham o mesmo escopo das fechaduras obtidas usando request()
no contexto SharedStorageWorklet.
Embora o método request()
permita várias opções de configuração, as fechaduras adquiridas no Shared Storage sempre seguem as seguintes configurações padrão:
mode: "exclusive"
: nenhuma outra fechadura com o mesmo nome pode ser mantida simultaneamente.steal: false
: as travas existentes com o mesmo nome não são liberadas para acomodar outras solicitações.ifAvailable: false
: as solicitações esperam indefinidamente até que a trava fique disponível.
Quando usar withLock
Os bloqueios são úteis em cenários em que pode haver vários worklets em execução simultaneamente (por exemplo, vários worklets em uma página ou em diferentes guias), cada um deles analisando os mesmos dados. Nesse cenário, é recomendável agrupar o código do worklet relevante com uma trava para garantir que apenas um worklet processe relatórios por vez.
Outra situação em que as fechaduras são úteis é quando há várias chaves que precisam ser lidas juntas em um worklet e o estado delas precisa ser sincronizado. Nesse caso, é necessário agrupar as chamadas get
com um bloqueio e adquirir o mesmo bloqueio ao gravar nessas chaves.
Ordem das fechaduras
Devido à natureza dos bloqueios da Web, os métodos modificadores podem não ser executados na ordem que você definiu. Se a primeira operação exigir um bloqueio e ele for atrasado, a segunda operação poderá ser iniciada antes que a primeira seja concluída.
Por exemplo:
// 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');
Exemplo de modificação de várias chaves
Este exemplo usa uma trava para garantir que as operações de leitura e exclusão no worklet aconteçam juntas, evitando interferências externas.
O exemplo de modify-multiple-keys.js
a seguir define novos valores para keyOne
e keyTwo
com modify-lock
e, em seguida, executa a operação modify-multiple-keys
do 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');
Em seguida, no modify-multiple-keys-worklet.js
, você pode solicitar a fechadura usando navigator.locks.request()
para ler e modificar as chaves conforme necessário.
// 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);
Troca de contexto
Os dados do Shared Storage são gravados na origem (por exemplo, https://example.adtech.com) do contexto de navegação de onde a chamada originou.
Quando você carrega o código de terceiros usando uma tag <script>
, ele é executado
no contexto de navegação do incorporador. Portanto, quando o código de terceiros
chama sharedStorage.set()
, os dados são gravados no armazenamento compartilhado
do incorporador. Quando você carrega o código de terceiros em um iframe, ele recebe
um novo contexto de navegação, e a origem dele é a origem do iframe. Portanto,
a chamada sharedStorage.set()
feita pelo iframe armazena os dados no
armazenamento compartilhado da origem do iframe.
Contexto próprio
Se uma página própria tiver um código JavaScript de terceiros incorporado que chame
sharedStorage.set()
ou sharedStorage.delete()
, o par de chave-valor será armazenado
no contexto próprio.

Contexto de terceiros
O par de chave-valor pode ser armazenado na adtech ou no contexto de terceiros criando um iframe e chamando set()
ou delete()
no código JavaScript dentro do iframe.

API Private Aggregation
Para medir dados agregáveis armazenados no Shared Storage, use a API Private Aggregation.
Para criar um relatório, chame contributeToHistogram()
em um worklet com um
bucket e um valor. O bucket é representado por um número inteiro de 128 bits sem assinatura, que
precisa ser transmitido para a função como um BigInt
. O valor é um número inteiro positivo.
Para proteger a privacidade, o payload do relatório, que contém o bucket e o valor, é criptografado em trânsito e só pode ser descriptografado e agregado usando o serviço de agregação.
O navegador também limita as contribuições que um site pode fazer para uma consulta de saída. Especificamente, o orçamento de contribuição limita o total de todos os relatórios de um único site para um determinado navegador em uma janela de tempo em todos os buckets. Se o orçamento atual for excedido, um relatório não será gerado.
privateAggregation.contributeToHistogram({
bucket: BigInt(myBucket),
value: parseInt(myBucketValue)
});
Como executar o Armazenamento compartilhado e a agregação particular
Você precisa criar um worklet para acessar dados do armazenamento compartilhado. Para fazer isso, chame
createWorklet()
com o URL do worklet. Por padrão, ao usar o armazenamento
compartilhado com createWorklet()
, a origem da partição de dados será a origem
do contexto de navegação
de invocação, não a origem do próprio script do worklet.
Para mudar o comportamento padrão, defina a propriedade dataOrigin
ao chamar
createWorklet
.
dataOrigin: "context-origin"
: (padrão) os dados são armazenados no armazenamento compartilhado da origem do contexto de navegação de invocação.dataOrigin: "script-origin"
: os dados são armazenados no armazenamento compartilhado da origem do script do worklet. É necessário ativar esse modo.
sharedStorage.createWorklet(scriptUrl, {dataOrigin: "script-origin"});
Para ativar, ao usar "script-origin"
, o endpoint do script precisará
responder com o cabeçalho Shared-Storage-Cross-Origin-Worklet-Allowed
. O
CORS precisa estar ativado para
solicitações entre origens.
Shared-Storage-Cross-Origin-Worklet-Allowed : ?1
Como usar iframes entre origens
Um iframe é necessário para invocar o worklet de armazenamento compartilhado.
No iframe do anúncio, chame addModule()
para carregar o módulo do worklet. Para executar o
método registrado no arquivo de worklet sharedStorageWorklet.js
, no
mesmo JavaScript do iframe do anúncio, chame sharedStorage.run()
.
const sharedStorageWorklet = await window.sharedStorage.createWorklet(
'https://any-origin.example/modules/sharedStorageWorklet.js'
);
await sharedStorageWorklet.run('shared-storage-report', {
data: { campaignId: '1234' },
});
No script do worklet, você precisa criar uma classe com um método run
assíncrono
e register
para que ele seja executado no iframe do anúncio. 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);
Como usar a solicitação entre origens
O Shared Storage e a Private Aggregation permitem a criação de worklets de origem cruzada sem a necessidade de iframes de origem cruzada.
A página própria também pode invocar uma chamada createWorklet()
para o
endpoint JavaScript entre origens. Você vai precisar definir a origem da partição de dados
do worklet como a da origem do script ao criar o 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();
O endpoint de JavaScript entre origens terá que responder com os cabeçalhos
Shared-Storage-Cross-Origin-Worklet-Allowed
e observar que o CORS está ativado para
a solicitação.
Shared-Storage-Cross-Origin-Worklet-Allowed : ?1
Os worklets criados usando o createWorklet()
terão selectURL
e run()
.
O addModule()
não está disponível para isso.
class CrossOriginWorklet {
async run(data){
// Other code goes here.
bucket = getBucket(...);
value = getValue(...);
privateAggregation.contributeToHistogram({
bucket,
value
});
}
}
Próximas etapas
As páginas a seguir explicam aspectos importantes das APIs Shared Storage e Private Aggregation.
- Introdução à Shared Storage (Chrome para desenvolvedores)
- Casos de uso de armazenamento compartilhado (Chrome para desenvolvedores)
- Introdução à agregação particular (Chrome para desenvolvedores)
- Explicação do armazenamento compartilhado (GitHub)
- Explicação sobre agregação privada (GitHub)
- Demonstração do Shared Storage e da Private Aggregation
Depois de conhecer as APIs, você pode começar a coletar os relatórios, que são enviados como uma solicitação POST para os endpoints a seguir como JSON no corpo da solicitação.
- Relatórios de depuração:
context-origin/.well-known/private-aggregation/debug/report-shared-storage
- Relatórios:
context-origin/.well-known/private-aggregation/report-shared-storage
Depois que os relatórios forem coletados, você poderá testar usando a ferramenta de teste local ou configurar o Ambiente de execução confiável para o serviço de agregação para receber os relatórios agregados.
Envie feedback
Compartilhe seu feedback sobre as APIs e a documentação no GitHub.