A generic way to process some shared storage data. Used, for example, by the Private Aggregation API to process shared storage data and generate aggregated reports.
In more advanced cases, it is possible to define and register multiple operations in the same shared storage worklet module script with different names. In the following worklet module script, we define a URL Selection operation called SelectURLOperation that selects a URL for A/B testing, and a Run operation called ExperimentGroupReportingOperation, which runs a histogram report based on the user's A/B testing group:
js
// ab-testing-worklet.jsclassSelectURLOperation{asyncrun(urls, data){// Read the user's group from shared storageconst experimentGroup =await sharedStorage.get("ab-testing-group");// Log to console for the demo
console.log(`urls = ${JSON.stringify(urls)}`);
console.log(`data = ${JSON.stringify(data)}`);
console.log(`ab-testing-group in shared storage is ${experimentGroup}`);// Return the index of the groupreturn data.indexOf(experimentGroup);}}functiongetBucketForTestingGroup(testingGroup){switch(testingGroup){case"control":return0;case"experiment-a":return1;case"experiment-b":return2;}}classExperimentGroupReportingOperation{asyncrun(){const experimentGroup =await sharedStorage.get("ab-testing-group");const bucket =BigInt(getBucketForTestingGroup(experimentGroup));
privateAggregation.contributeToHistogram({ bucket,value:1});}}// Register the operationsregister("ab-testing", SelectURLOperation);register("experiment-group-reporting", ExperimentGroupReportingOperation);
In the main browsing context, these operations are invoked by selectURL() and run(), respectively. The operations to invoke via these methods are selected using the names they were registered with, and they are also required to conform to the structures defined by the SharedStorageSelectURLOperation and SharedStorageRunOperation classes and their run() methods.
js
// For demo purposes. The hostname is used to determine the usage of// development localhost URL vs production URLconst contentProducerUrl = window.location.host;// Map the experiment groups to the URLsconstEXPERIMENT_MAP=[{group:"control",url:`https://${contentProducerUrl}/ads/default-ad.html`,},{group:"experiment-a",url:`https://${contentProducerUrl}/ads/experiment-ad-a.html`,},{group:"experiment-b",url:`https://${contentProducerUrl}/ads/experiment-ad-b.html`,},];// Choose a random group for the initial experimentfunctiongetRandomExperiment(){const randomIndex = Math.floor(Math.random()*EXPERIMENT_MAP.length);returnEXPERIMENT_MAP[randomIndex].group;}asyncfunctioninjectAd(){// Load the worklet moduleawait window.sharedStorage.worklet.addModule("ab-testing-worklet.js");// Set the initial value in the storage to a random experiment group
window.sharedStorage.set("ab-testing-group",getRandomExperiment(),{ignoreIfPresent:true,});const urls =EXPERIMENT_MAP.map(({ url })=>({ url }));const groups =EXPERIMENT_MAP.map(({ group })=> group);// Resolve the selectURL call to a fenced frame config only when it exists on the pageconst resolveToConfig =typeof window.FencedFrameConfig !=="undefined";// Run the URL selection operation to select an ad based on the experiment group in shared storageconst selectedUrl =await window.sharedStorage.selectURL("ab-testing", urls,{data: groups,
resolveToConfig,keepAlive:true,});const adSlot = document.getElementById("ad-slot");if(resolveToConfig && selectedUrl instanceofFencedFrameConfig){
adSlot.config = selectedUrl;}else{
adSlot.src = selectedUrl;}// Run the reporting operationawait window.sharedStorage.run("experiment-group-reporting");}injectAd();