diff --git a/firebase.json b/firebase.json
index 4d94824..198ef62 100644
--- a/firebase.json
+++ b/firebase.json
@@ -70,6 +70,14 @@
{
"key": "Supports-Loading-Mode",
"value": "fenced-frame"
+ },
+ {
+ "key": "Access-Control-Allow-Origin",
+ "value": "*"
+ },
+ {
+ "key": "Shared-Storage-Cross-Origin-Worklet-Allowed",
+ "value": "?1"
}
]
}
diff --git a/functions/app/helpers/setup-view.js b/functions/app/helpers/setup-view.js
index 5ab32af..5b9407d 100644
--- a/functions/app/helpers/setup-view.js
+++ b/functions/app/helpers/setup-view.js
@@ -25,6 +25,7 @@ module.exports = (app, viewName) => {
hbs.engine({
extname: '.hbs',
layoutsDir: path.join(__dirname + '/../../view'),
+ partialsDir: path.join(__dirname + '/../../view/partials')
})
);
diff --git a/functions/view/main.hbs b/functions/view/main.hbs
index 3c13b09..a872f06 100644
--- a/functions/view/main.hbs
+++ b/functions/view/main.hbs
@@ -31,9 +31,16 @@
diff --git a/functions/view/partials/creativeRotationDemoControls.hbs b/functions/view/partials/creativeRotationDemoControls.hbs
new file mode 100644
index 0000000..e32cbd1
--- /dev/null
+++ b/functions/view/partials/creativeRotationDemoControls.hbs
@@ -0,0 +1,26 @@
+
-
+ {{> creativeRotationDemoControls}}
Description
@@ -55,6 +55,7 @@
+
diff --git a/functions/view/publisher-b/creative-rotation.hbs b/functions/view/publisher-b/creative-rotation.hbs
index 4908500..249ed6b 100644
--- a/functions/view/publisher-b/creative-rotation.hbs
+++ b/functions/view/publisher-b/creative-rotation.hbs
@@ -13,7 +13,7 @@
Shared storage - Creative rotation demo
-
+ {{> creativeRotationDemoControls}}
Description
@@ -55,6 +55,7 @@
+
diff --git a/sites/content-producer/url-selection/ab-testing.js b/sites/content-producer/url-selection/ab-testing.js
index 576fbe7..bf54113 100644
--- a/sites/content-producer/url-selection/ab-testing.js
+++ b/sites/content-producer/url-selection/ab-testing.js
@@ -42,7 +42,9 @@ function getRandomExperiment() {
async function injectAd() {
// Load the worklet module
- await window.sharedStorage.worklet.addModule('ab-testing-worklet.js');
+ const abTestingWorklet = await window.sharedStorage.createWorklet(
+ 'ab-testing-worklet.js'
+ );
// Set the initial value in the storage to a random experiment group
window.sharedStorage.set('ab-testing-group', getRandomExperiment(), {
@@ -56,7 +58,7 @@ async function injectAd() {
const resolveToConfig = typeof window.FencedFrameConfig !== 'undefined';
// Run the URL selection operation to select an ad based on the experiment group in shared storage
- const selectedUrl = await window.sharedStorage.selectURL('ab-testing', urls, {
+ const selectedUrl = await abTestingWorklet.selectURL('ab-testing', urls, {
data: groups,
resolveToConfig,
keepAlive: true,
@@ -71,7 +73,7 @@ async function injectAd() {
}
// Run the reporting operation
- await window.sharedStorage.run('experiment-group-reporting')
+ await abTestingWorklet.run('experiment-group-reporting')
}
injectAd();
diff --git a/sites/content-producer/url-selection/creative-rotation-worklet.js b/sites/content-producer/url-selection/creative-rotation-worklet.js
index d276d9c..2bb9ef1 100644
--- a/sites/content-producer/url-selection/creative-rotation-worklet.js
+++ b/sites/content-producer/url-selection/creative-rotation-worklet.js
@@ -16,6 +16,9 @@
class SelectURLOperation {
async run(urls, data) {
+ // Initially set the storage to sequential mode for the demo
+ await SelectURLOperation.seedStorage();
+
// Read the rotation mode from Shared Storage
const rotationMode = await sharedStorage.get('creative-rotation-mode');
@@ -77,7 +80,25 @@ class SelectURLOperation {
console.log(JSON.stringify({ index, randomNumber, rotationMode }));
return index;
}
+
+ // Set the mode to sequential and set the starting index to 0.
+ static async seedStorage() {
+ await sharedStorage.set('creative-rotation-mode', 'sequential', {
+ ignoreIfPresent: true,
+ });
+
+ await sharedStorage.set('creative-rotation-index', 0, {
+ ignoreIfPresent: true,
+ });
+ }
+}
+
+class SetRotationModeOperation {
+ async run({ rotationMode }) {
+ await sharedStorage.set('creative-rotation-mode', rotationMode);
+ }
}
// Register the operation as 'creative-rotation'
register('creative-rotation', SelectURLOperation);
+register('set-rotation-mode', SetRotationModeOperation);
diff --git a/sites/content-producer/url-selection/creative-rotation.html b/sites/content-producer/url-selection/creative-rotation.html
deleted file mode 100644
index 0dcfd77..0000000
--- a/sites/content-producer/url-selection/creative-rotation.html
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-
-
-
-
-
-
Shared storage demo
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Demo control
-
-
- Set rotation mode to "Sequential"
-
-
- Set rotation mode to "Even distribution" (~33% / ~33% / ~33%)
-
-
- Set rotation mode to "Weighted distribution" (70% / 20% / 10%)
-
-
-
-
-
diff --git a/sites/content-producer/url-selection/creative-rotation.js b/sites/content-producer/url-selection/creative-rotation.js
index 845d90d..5f0db96 100644
--- a/sites/content-producer/url-selection/creative-rotation.js
+++ b/sites/content-producer/url-selection/creative-rotation.js
@@ -16,41 +16,43 @@
// For demo purposes. The hostname is used to determine the usage of
// development localhost URL vs production URL
-const contentProducerUrl = window.location.host;
+const contentProducerUrl = window.getContentProducerUrl();
// Ad confg with the URL of the ad, a probability weight for rotation, and the clickthrough rate.
const DEMO_AD_CONFIG = [
{
- url: `https://${contentProducerUrl}/ads/ad-1.html`,
+ url: `${contentProducerUrl}/ads/ad-1.html`,
weight: 0.7,
},
{
- url: `https://${contentProducerUrl}/ads/ad-2.html`,
+ url: `${contentProducerUrl}/ads/ad-2.html`,
weight: 0.2,
},
{
- url: `https://${contentProducerUrl}/ads/ad-3.html`,
+ url: `${contentProducerUrl}/ads/ad-3.html`,
weight: 0.1,
},
];
-// Set the mode to sequential and set the starting index to 0.
-async function seedStorage() {
- await window.sharedStorage.set('creative-rotation-mode', 'sequential', {
- ignoreIfPresent: true,
- });
+async function setRotationMode(rotationMode) {
+ // Load the worklet module
+ const creativeRotationWorklet = await window.sharedStorage.createWorklet(
+ `${contentProducerUrl}/url-selection/creative-rotation-worklet.js`,
+ { dataOrigin: 'script-origin' }
+ );
- await window.sharedStorage.set('creative-rotation-index', 0, {
- ignoreIfPresent: true,
+ await creativeRotationWorklet.run('set-rotation-mode', {
+ data: { rotationMode }
});
+ console.log(`creative rotation mode set to ${rotationMode}`);
}
async function injectAd() {
// Load the worklet module
- await window.sharedStorage.worklet.addModule('creative-rotation-worklet.js');
-
- // Initially set the storage to sequential mode for the demo
- seedStorage();
+ const creativeRotationWorklet = await window.sharedStorage.createWorklet(
+ `${contentProducerUrl}/url-selection/creative-rotation-worklet.js`,
+ { dataOrigin: 'script-origin' }
+ );
const urls = DEMO_AD_CONFIG.map(({ url }) => ({ url }));
@@ -58,7 +60,7 @@ async function injectAd() {
const resolveToConfig = typeof window.FencedFrameConfig !== 'undefined';
// Run the URL selection operation to determine the next ad that should be rendered
- const selectedUrl = await window.sharedStorage.selectURL('creative-rotation', urls, {
+ const selectedUrl = await creativeRotationWorklet.selectURL('creative-rotation', urls, {
data: DEMO_AD_CONFIG,
resolveToConfig
});
diff --git a/sites/publisher-a/index.css b/sites/publisher-a/index.css
index 181a4a7..5bdb461 100644
--- a/sites/publisher-a/index.css
+++ b/sites/publisher-a/index.css
@@ -105,3 +105,51 @@ card {
background-color: var(--orange-9);
}
}
+
+.demo__controls-section {
+ width: 300px;
+}
+#ad-slot {
+ height: 250px;
+ border: none;
+}
+
+#button-slot {
+ height: 100px;
+ border: none;
+}
+
+.demo__card,
+.demo__controls {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: var(--size-2);
+ background: var(--surface-3);
+ border: 1px solid var(--surface-1);
+ padding: var(--size-3);
+ margin: var(--size-3) 0;
+ border-radius: var(--radius-3);
+ box-shadow: var(--shadow-2);
+ margin-top: 0;
+}
+
+.demo__controls h5 {
+ margin-bottom: var(--size-2);
+}
+
+.demo__buttons-container {
+ display: flex;
+ flex-direction: column;
+ width: fit-content;
+}
+
+.demo__button {
+ zoom: 90%;
+ /* max-width: var(--size-13); */
+ --_bg: linear-gradient(var(--indigo-5), var(--indigo-7));
+ --_border: var(--indigo-6);
+ --_text: var(--indigo-0);
+ --_ink-shadow: 0 1px 0 var(--indigo-9);
+ margin: 5px;
+}
diff --git a/sites/publisher-b/index.css b/sites/publisher-b/index.css
index 6ef5157..ce7a9f5 100644
--- a/sites/publisher-b/index.css
+++ b/sites/publisher-b/index.css
@@ -101,3 +101,52 @@ card {
background-color: var(--orange-9);
}
}
+
+.demo__controls-section {
+ width: 300px;
+}
+
+#ad-slot {
+ height: 250px;
+ border: none;
+}
+
+#button-slot {
+ height: 100px;
+ border: none;
+}
+
+.demo__card,
+.demo__controls {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: var(--size-2);
+ background: var(--surface-3);
+ border: 1px solid var(--surface-1);
+ padding: var(--size-3);
+ margin: var(--size-3) 0;
+ border-radius: var(--radius-3);
+ box-shadow: var(--shadow-2);
+ margin-top: 0;
+}
+
+.demo__controls h5 {
+ margin-bottom: var(--size-2);
+}
+
+.demo__buttons-container {
+ display: flex;
+ flex-direction: column;
+ width: fit-content;
+}
+
+.demo__button {
+ zoom: 90%;
+ /* max-width: var(--size-13); */
+ --_bg: linear-gradient(var(--indigo-5), var(--indigo-7));
+ --_border: var(--indigo-6);
+ --_text: var(--indigo-0);
+ --_ink-shadow: 0 1px 0 var(--indigo-9);
+ margin: 5px;
+}