diff --git a/services/ad-server/tsconfig.json b/services/ad-server/tsconfig.json index 115261cf..c7ad80bc 100644 --- a/services/ad-server/tsconfig.json +++ b/services/ad-server/tsconfig.json @@ -6,6 +6,6 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, - "skipLibCheck": true, - }, + "skipLibCheck": true + } } diff --git a/services/dsp-a/tsconfig.json b/services/dsp-a/tsconfig.json index f8c3d840..9c07f0c9 100644 --- a/services/dsp-a/tsconfig.json +++ b/services/dsp-a/tsconfig.json @@ -8,6 +8,6 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, - "skipLibCheck": true, - }, + "skipLibCheck": true + } } diff --git a/services/dsp-b/tsconfig.json b/services/dsp-b/tsconfig.json index f8c3d840..9c07f0c9 100644 --- a/services/dsp-b/tsconfig.json +++ b/services/dsp-b/tsconfig.json @@ -8,6 +8,6 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, - "skipLibCheck": true, - }, + "skipLibCheck": true + } } diff --git a/services/dsp/package-lock.json b/services/dsp/package-lock.json index d44e26e9..6fd7c495 100644 --- a/services/dsp/package-lock.json +++ b/services/dsp/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.0", "license": "apache-2.0", "dependencies": { - "cbor": "^9.0.0", + "cbor": "^9.0.2", "ejs": "^3.1.9", "express": "^4.18.2", "structured-field-values": "^2.0.1" @@ -280,9 +280,9 @@ } }, "node_modules/cbor": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.1.tgz", - "integrity": "sha512-/TQOWyamDxvVIv+DY9cOLNuABkoyz8K/F3QE56539pGVYohx0+MEA1f4lChFTX79dBTBS7R1PF6ovH7G+VtBfQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", + "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", "dependencies": { "nofilter": "^3.1.0" }, diff --git a/services/dsp/package.json b/services/dsp/package.json index d880f01f..74eb9571 100644 --- a/services/dsp/package.json +++ b/services/dsp/package.json @@ -10,7 +10,7 @@ "ncu": "npx npm-check-updates -u" }, "dependencies": { - "cbor": "^9.0.0", + "cbor": "^9.0.2", "ejs": "^3.1.9", "express": "^4.18.2", "structured-field-values": "^2.0.1" diff --git a/services/dsp/src/index.ts b/services/dsp/src/index.ts index 95bb1f8a..35761e5b 100644 --- a/services/dsp/src/index.ts +++ b/services/dsp/src/index.ts @@ -421,8 +421,12 @@ app.post( }, ); -app.get('/private-aggregation', (req, res) => { - res.render('private-aggregation'); +app.get('/private-aggregation-aws', (req, res) => { + res.render('private-aggregation-aws'); +}); + +app.get('/private-aggregation-gcp', (req, res) => { + res.render('private-aggregation-gcp'); }); app.post( diff --git a/services/dsp/src/public/js/dsp.js b/services/dsp/src/public/js/dsp.js index ac98465e..2fcaede0 100644 --- a/services/dsp/src/public/js/dsp.js +++ b/services/dsp/src/public/js/dsp.js @@ -1,7 +1,10 @@ let dsp = document.currentScript.getAttribute('dsp'); window.addEventListener('load', (event) => { - let iframe = document.createElement('iframe'); + let iframeAws = document.createElement('iframe'); + let iframeGcp = document.createElement('iframe'); // let dsp = document.currentScript.getAttribute('dsp'); - iframe.src = `https://${dsp}/private-aggregation`; - document.body.appendChild(iframe); + iframeAws.src = `https://${dsp}/private-aggregation-aws`; + iframeGcp.src = `https://${dsp}/private-aggregation-gcp`; + document.body.appendChild(iframeAws); + document.body.appendChild(iframeGcp); }); diff --git a/services/dsp/src/public/js/private-aggregation-aws.js b/services/dsp/src/public/js/private-aggregation-aws.js new file mode 100644 index 00000000..eb3d14b1 --- /dev/null +++ b/services/dsp/src/public/js/private-aggregation-aws.js @@ -0,0 +1,14 @@ +async function runPrivateAggregationAws() { + const privateAggCloud = { + 'privateAggregationConfig': { + 'aggregationCoordinatorOrigin': + 'https://publickeyservice.msmt.aws.privacysandboxservices.com', + }, + }; + await window.sharedStorage.worklet.addModule( + 'js/private-aggregation-worklet-aws.js', + ); + await window.sharedStorage.run('test-private-aggregation', privateAggCloud); +} + +runPrivateAggregationAws(); diff --git a/services/dsp/src/public/js/private-aggregation-gcp.js b/services/dsp/src/public/js/private-aggregation-gcp.js new file mode 100644 index 00000000..cefbb8be --- /dev/null +++ b/services/dsp/src/public/js/private-aggregation-gcp.js @@ -0,0 +1,14 @@ +async function runPrivateAggregationGcp() { + const privateAggCloud = { + 'privateAggregationConfig': { + 'aggregationCoordinatorOrigin': + 'https://publickeyservice.msmt.gcp.privacysandboxservices.com', + }, + }; + await window.sharedStorage.worklet.addModule( + 'js/private-aggregation-worklet-gcp.js', + ); + await window.sharedStorage.run('test-private-aggregation', privateAggCloud); +} + +runPrivateAggregationGcp(); diff --git a/services/dsp/src/public/js/private-aggregation-worklet.js b/services/dsp/src/public/js/private-aggregation-worklet-aws.js similarity index 91% rename from services/dsp/src/public/js/private-aggregation-worklet.js rename to services/dsp/src/public/js/private-aggregation-worklet-aws.js index dfc4b533..6c72ddde 100644 --- a/services/dsp/src/public/js/private-aggregation-worklet.js +++ b/services/dsp/src/public/js/private-aggregation-worklet-aws.js @@ -1,6 +1,6 @@ class TestPrivateAggregation { async run(data) { - console.log('Enabling Private Aggregation Debug Mode'); + console.log('Enabling AWS Private Aggregation Debug Mode'); privateAggregation.enableDebugMode({debugKey: 1234n}); let campaignId = await sharedStorage.get('campaignId'); if (!campaignId) { diff --git a/services/dsp/src/public/js/private-aggregation-worklet-gcp.js b/services/dsp/src/public/js/private-aggregation-worklet-gcp.js new file mode 100644 index 00000000..586ebd80 --- /dev/null +++ b/services/dsp/src/public/js/private-aggregation-worklet-gcp.js @@ -0,0 +1,24 @@ +class TestPrivateAggregation { + async run(data) { + console.log('Enabling GCP Private Aggregation Debug Mode'); + privateAggregation.enableDebugMode({debugKey: 1234n}); + let campaignId = await sharedStorage.get('campaignId'); + if (!campaignId) { + console.log( + 'No campaign id found for client. Adding campaignId 1234567890.', + ); + campaignId = '1234567890'; + sharedStorage.set('campaignId', campaignId); + } else { + console.log(`Campaign ID found: ${campaignId}`); + } + function convertToBucket(bucketId) { + return BigInt(bucketId); + } + const bucket = convertToBucket(campaignId); + const value = 128; + privateAggregation.contributeToHistogram({bucket, value}); + } +} + +register('test-private-aggregation', TestPrivateAggregation); diff --git a/services/dsp/src/public/js/private-aggregation.js b/services/dsp/src/public/js/private-aggregation.js deleted file mode 100644 index e071dc28..00000000 --- a/services/dsp/src/public/js/private-aggregation.js +++ /dev/null @@ -1,8 +0,0 @@ -async function runPrivateAggregation() { - await window.sharedStorage.worklet.addModule( - 'js/private-aggregation-worklet.js', - ); - await window.sharedStorage.run('test-private-aggregation'); -} - -runPrivateAggregation(); diff --git a/services/dsp/src/views/private-aggregation-aws.ejs b/services/dsp/src/views/private-aggregation-aws.ejs new file mode 100644 index 00000000..6e29dc87 --- /dev/null +++ b/services/dsp/src/views/private-aggregation-aws.ejs @@ -0,0 +1,5 @@ + +
+ +
+ \ No newline at end of file diff --git a/services/dsp/src/views/private-aggregation-gcp.ejs b/services/dsp/src/views/private-aggregation-gcp.ejs new file mode 100644 index 00000000..d3c8f54b --- /dev/null +++ b/services/dsp/src/views/private-aggregation-gcp.ejs @@ -0,0 +1,5 @@ + +
+ +
+ \ No newline at end of file diff --git a/services/dsp/tsconfig.json b/services/dsp/tsconfig.json index f8c3d840..9c07f0c9 100644 --- a/services/dsp/tsconfig.json +++ b/services/dsp/tsconfig.json @@ -8,6 +8,6 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, - "skipLibCheck": true, - }, + "skipLibCheck": true + } } diff --git a/services/home/docs/demos/img/instream-video-ad-hb-time.png b/services/home/docs/demos/img/instream-video-ad-hb-time.png new file mode 100644 index 00000000..3ffa4214 Binary files /dev/null and b/services/home/docs/demos/img/instream-video-ad-hb-time.png differ diff --git a/services/home/docs/demos/img/instream-video-ad-ig-time.png b/services/home/docs/demos/img/instream-video-ad-ig-time.png new file mode 100644 index 00000000..52bc038b Binary files /dev/null and b/services/home/docs/demos/img/instream-video-ad-ig-time.png differ diff --git a/services/home/docs/demos/img/instream-video-ad-render-time.png b/services/home/docs/demos/img/instream-video-ad-render-time.png new file mode 100644 index 00000000..fa81f755 Binary files /dev/null and b/services/home/docs/demos/img/instream-video-ad-render-time.png differ diff --git a/services/home/docs/demos/instream-video-ad-multi-seller.md b/services/home/docs/demos/instream-video-ad-multi-seller.md index 36d74be9..e9ed48c0 100644 --- a/services/home/docs/demos/instream-video-ad-multi-seller.md +++ b/services/home/docs/demos/instream-video-ad-multi-seller.md @@ -22,6 +22,8 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; +☝️ Use the tabs to navigate to other sections in this document + If you have any questions and comments for this instream video ad demo, use [the instream video ad demo post](https://github.com/privacysandbox/privacy-sandbox-demos/discussions/254) in the Discussions tab. @@ -185,6 +187,8 @@ DSPA ->> Browser: Add user to Interest Group
Set a render URL with SSP VAST m DSPB ->> Browser: Add user to Interest Group
Set a render URL with SSP VAST macro (%%SSP_VAST_URL%%) ``` +[Full-sized diagram](./img/instream-video-ad-ig-time.png) + #### Header bidding time This is the time period when the seller defines the macro substitution in the component auction config @@ -217,6 +221,8 @@ SSPB ->> HB: Respond with the header bid and component auction config HB ->> AS: Pass the header bidding auction result to the ad server client-side library ``` +[Full-sized diagram](./img/instream-video-ad-hb-time.png) + ### Ad rendering time This is the time period when the VAST is transformed and passed to the creative. @@ -255,33 +261,43 @@ AS ->> VP: The VAST is passed to the video player VP ->> Publisher: The instream video ad is rendered ``` -## Alternate mechanism +[Full-sized diagram](.//img/instream-video-ad-render-time.png) + +## Alternative approach In another approach, the SSP can provide the render URL. The DSP sets the following render URL in the IG: ```js const interestGroup = { // ... - ads: [{ - renderUrl: 'https://privacy-sandbox-demos-ssp-a.dev/video-ad.html?dspVastUri=https://privacy-sandbox-demos-dsp-a.dev/preroll.xml', - }] + ads: [ + { + renderUrl: 'https://privacy-sandbox-demos-ssp-a.dev/video-ad.html?dspVastUri=https://privacy-sandbox-demos-dsp-a.dev/preroll.xml', + metadata: { + seller: 'ssp-a' + } + }, + { + renderUrl: 'https://privacy-sandbox-demos-ssp-b.dev/video-ad.html?dspVastUri=https://privacy-sandbox-demos-dsp-a.dev/preroll.xml', + metadata: { + seller: 'ssp-b' + } + }, + ] } ``` - The render URL points to the SSP’s video ad serving endpoint, and the DSP’s VAST URI is added as query params. - The SSP is now responsible for serving the actual ad that is rendered inside the iframe, and it contains the SSP VAST XML that wraps the DSP VAST URI. + - To support multiple SSPs, the buyer adds a render URL for each SSP. During the bid generation time, the buyer can filter the ads object and return + a render URL for the matching seller. - When that ad wins the auction, the browser makes a request to the render URL which is the SSP's ad serving endpoint `/video-ad.html` with the DSP's VAST URI set in the query params - SSP’s HTML document is rendered in the ad iframe and parses the DSP's VAST URI from the query params - The code inside SSP's video-ad.html wraps the DSP's VAST URI with its own VAST - The finalized VAST XML is post-messaged out of the creative frame to the video player -To support multiple SSPs, the SSP's video ad serving endpoint can be substituted with a macro: -`https://%%SSP_VIDEO_AD%%?dspVastUri=https://privacy-sandbox-demos-dsp-a.dev/preroll.xml` . - -We will add a demo for this alternate approach in the future. -
diff --git a/services/news/tsconfig.json b/services/news/tsconfig.json index c08cb344..737857ba 100644 --- a/services/news/tsconfig.json +++ b/services/news/tsconfig.json @@ -6,7 +6,7 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, - "skipLibCheck": true, + "skipLibCheck": true }, - "exclude": ["src/public"], + "exclude": ["src/public"] } diff --git a/services/shop/tsconfig.json b/services/shop/tsconfig.json index ab41abbb..6f91aab8 100644 --- a/services/shop/tsconfig.json +++ b/services/shop/tsconfig.json @@ -7,6 +7,6 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, - "skipLibCheck": true, - }, + "skipLibCheck": true + } } diff --git a/services/topics-server/tsconfig.json b/services/topics-server/tsconfig.json index 115261cf..c7ad80bc 100644 --- a/services/topics-server/tsconfig.json +++ b/services/topics-server/tsconfig.json @@ -6,6 +6,6 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, - "skipLibCheck": true, - }, + "skipLibCheck": true + } } diff --git a/services/topics/tsconfig.json b/services/topics/tsconfig.json index 115261cf..c7ad80bc 100644 --- a/services/topics/tsconfig.json +++ b/services/topics/tsconfig.json @@ -6,6 +6,6 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, - "skipLibCheck": true, - }, + "skipLibCheck": true + } } diff --git a/services/travel/tsconfig.json b/services/travel/tsconfig.json index e21ce02a..ff6e0782 100644 --- a/services/travel/tsconfig.json +++ b/services/travel/tsconfig.json @@ -7,6 +7,6 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, - "skipLibCheck": true, - }, + "skipLibCheck": true + } } diff --git a/setup.sh b/setup.sh new file mode 100644 index 00000000..526ee842 --- /dev/null +++ b/setup.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +npm install + +npm run cert + +cd services/home + +npm install + +npm run build + +cd ../.. + +sudo npm run start