Skip to content

Commit d61bd18

Browse files
Merge branch 'main' into syw-UID2-6332-node-forge-vulnerability
2 parents 63e5816 + c938f88 commit d61bd18

File tree

15 files changed

+2032
-551
lines changed

15 files changed

+2032
-551
lines changed

web-integrations/google-secure-signals/client-side/Dockerfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ RUN apk add --no-cache gettext
66
# Copy static files from client-side directory
77
COPY html /usr/share/nginx/html/
88

9+
# Copy shared styles folder
10+
COPY web-integrations/styles /usr/share/nginx/html/styles/
11+
912
# Copy config and entrypoint
1013
COPY default.conf /etc/nginx/conf.d/default.conf
1114
COPY entrypoint.sh /entrypoint.sh

web-integrations/google-secure-signals/client-side/html/index.html

Lines changed: 192 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -12,76 +12,199 @@
1212
</script>
1313
</head>
1414
<body>
15-
<h1>Client-Side ${IDENTITY_NAME} SDK Integration Example with Google Secure Signals</h1>
16-
<p>
17-
This example demonstrates how a content publisher can follow the
18-
<a href="${DOCS_BASE_URL}/guides/integration-javascript-client-side">Client-Side Integration Guide for JavaScript</a> to implement ${IDENTITY_NAME} integration and generate ${IDENTITY_NAME} tokens.
19-
Secure Signals is updated when the page is reloaded.
20-
Reload the page in order to update Secure Signals in local storage.
21-
<strong>Note:</strong> This is a <em>test-only</em> integration environment—not for production use.
22-
It does not perform real user authentication or generate production-level tokens.
23-
Do not use real user data on this page.
24-
</p>
25-
<div id="page-content">
26-
<div id="video-container">
27-
<video id="video-element">
28-
<source src="https://storage.googleapis.com/interactive-media-ads/media/android.mp4">
29-
<source src="https://storage.googleapis.com/interactive-media-ads/media/android.webm">
30-
</video>
31-
<div id="ad-container"></div>
32-
</div>
33-
<button id="play-button">Play</button>
34-
</div>
35-
<div class="product-tables">
36-
<table id="uid2_state">
37-
<tr>
38-
<td class="label">Ready for Targeted Advertising:</td>
39-
<td class="value"><pre id="targeted_advertising_ready"></pre></td>
40-
</tr>
41-
<tr>
42-
<td class="label">${IDENTITY_NAME} Advertising Token:</td>
43-
<td class="value"><pre id="advertising_token"></pre></td>
44-
</tr>
45-
<tr>
46-
<td class="label">Is ${IDENTITY_NAME} Login Required?</td>
47-
<td class="value"><pre id="login_required"></pre></td>
48-
</tr>
49-
<tr>
50-
<td class="label">${IDENTITY_NAME} Identity Callback State:</td>
51-
<td class="value"><pre id="identity_state"></pre></td>
52-
</tr>
53-
<tr>
54-
<td class="label">Secure Signals Loaded?</td>
55-
<td class="value"><pre id="secure_signals_loaded"></pre></td>
56-
</tr>
57-
<tr>
58-
<td class="label">Secure Signals Value:</td>
59-
<td class="value"><pre id="secure_signals_value"></pre></td>
60-
</tr>
61-
</table>
62-
</div>
63-
<div id="optout_banner" style="display: none; border: 3px solid #ffc107; padding: 15px; margin: 20px 0;">
64-
<p style="margin: 0;">The email address you entered has opted out of ${IDENTITY_NAME}.</p>
65-
</div>
66-
<div id="optout_message" style="display: none" class="form">
67-
<button type="button" class="button" id="try_another">Try Another Email</button>
68-
</div>
69-
<div id="login_form" style="display: none" class="form">
70-
<div class="email_prompt">
71-
<input
72-
type="text"
73-
id="email"
74-
name="email"
75-
placeholder="Enter an email address"
76-
style="border-style: none"
77-
/>
15+
<div class="page-wrapper">
16+
<!-- Main Content Area -->
17+
<div class="main-content">
18+
<h1>Client-Side ${IDENTITY_NAME} Integration with Google Secure Signals</h1>
19+
<p class="intro">
20+
This example demonstrates how a content publisher can integrate ${IDENTITY_NAME} with <strong>Google Secure Signals</strong> for Google Ad Manager, using client-side token generation. For documentation, see the <a href="${DOCS_BASE_URL}/guides/integration-javascript-client-side">Client-Side Integration Guide for JavaScript</a> and <a href="${DOCS_BASE_URL}/guides/integration-google-ss">Google Ad Manager Secure Signals Integration Guide</a>.
21+
</p>
22+
23+
<h2>${IDENTITY_NAME} Integration Status</h2>
24+
25+
<table id="uid2_state">
26+
<tr>
27+
<td class="label">
28+
<div class="tooltip-wrapper">
29+
Ready for Targeted Advertising:
30+
<div class="tooltip">
31+
<span class="tooltip-trigger">?</span>
32+
<div class="tooltip-content">
33+
Indicates whether a valid ${IDENTITY_NAME} token is present and can be used for personalized ad targeting.
34+
</div>
35+
</div>
36+
</div>
37+
</td>
38+
<td class="value"><pre id="targeted_advertising_ready"></pre></td>
39+
</tr>
40+
<tr>
41+
<td class="label">
42+
<div class="tooltip-wrapper">
43+
Advertising Token:
44+
<div class="tooltip">
45+
<span class="tooltip-trigger">?</span>
46+
<div class="tooltip-content">
47+
The encrypted ${IDENTITY_NAME} token that is passed to ad systems without exposing raw user identity. It is automatically refreshed by the SDK in the background when expired.
48+
</div>
49+
</div>
50+
</div>
51+
</td>
52+
<td class="value"><pre id="advertising_token"></pre></td>
53+
</tr>
54+
<tr>
55+
<td class="label">
56+
<div class="tooltip-wrapper">
57+
Is Login Required?
58+
<div class="tooltip">
59+
<span class="tooltip-trigger">?</span>
60+
<div class="tooltip-content">
61+
Indicates whether a new ${IDENTITY_NAME} token needs to be generated. Returns "yes" when no valid identity exists or the current identity has expired.
62+
</div>
63+
</div>
64+
</div>
65+
</td>
66+
<td class="value"><pre id="login_required"></pre></td>
67+
</tr>
68+
<tr>
69+
<td class="label">
70+
<div class="tooltip-wrapper">
71+
Has Opted Out?
72+
<div class="tooltip">
73+
<span class="tooltip-trigger">?</span>
74+
<div class="tooltip-content">
75+
Shows whether the user has exercised opt-out, in which case no advertising token may be generated or used.
76+
</div>
77+
</div>
78+
</div>
79+
</td>
80+
<td class="value"><pre id="has_opted_out"></pre></td>
81+
</tr>
82+
<tr>
83+
<td class="label">
84+
<div class="tooltip-wrapper">
85+
Identity Callback State:
86+
<div class="tooltip">
87+
<span class="tooltip-trigger">?</span>
88+
<div class="tooltip-content">
89+
The complete identity object returned by the SDK. Contains the full ${IDENTITY_NAME} identity data including refresh tokens and metadata.
90+
</div>
91+
</div>
92+
</div>
93+
</td>
94+
<td class="value"><pre id="identity_state"></pre></td>
95+
</tr>
96+
<tr>
97+
<td class="label">
98+
<div class="tooltip-wrapper">
99+
Secure Signals Loaded?
100+
<div class="tooltip">
101+
<span class="tooltip-trigger">?</span>
102+
<div class="tooltip-content">
103+
Indicates whether Google Secure Signals has successfully loaded and stored the ${IDENTITY_NAME} token. Returns "yes" when signals are available in localStorage.
104+
</div>
105+
</div>
106+
</div>
107+
</td>
108+
<td class="value"><pre id="secure_signals_loaded"></pre></td>
109+
</tr>
110+
<tr>
111+
<td class="label">
112+
<div class="tooltip-wrapper">
113+
Secure Signals Value:
114+
<div class="tooltip">
115+
<span class="tooltip-trigger">?</span>
116+
<div class="tooltip-content">
117+
The encrypted ${IDENTITY_NAME} signals stored by Google in localStorage under the key '${UID_SECURE_SIGNALS_STORAGE_KEY}'. These signals are shared with Google Ad Manager.
118+
</div>
119+
</div>
120+
</div>
121+
</td>
122+
<td class="value"><pre id="secure_signals_value"></pre></td>
123+
</tr>
124+
</table>
125+
126+
<div id="page-content">
127+
<div id="video-container">
128+
<video id="video-element">
129+
<source src="https://storage.googleapis.com/interactive-media-ads/media/android.mp4">
130+
<source src="https://storage.googleapis.com/interactive-media-ads/media/android.webm">
131+
</video>
132+
<div id="ad-container"></div>
133+
</div>
134+
<button id="play-button">Play</button>
135+
</div>
136+
137+
<div id="login_form" style="display: none" class="form">
138+
<div class="email_prompt">
139+
<input
140+
type="text"
141+
id="email"
142+
name="email"
143+
placeholder="Enter an email address"
144+
/>
145+
<button type="button" class="button" id="login">Generate ${IDENTITY_NAME}</button>
146+
</div>
147+
</div>
148+
<div id="logout_form" style="display: none" class="form">
149+
<button type="button" class="button" id="logout">Clear ${IDENTITY_NAME}</button>
150+
</div>
78151
</div>
79-
<div><button type="button" class="button" id="login">Generate ${IDENTITY_NAME}</button></div>
80-
</div>
81-
<div id="logout_form" style="display: none" class="form">
82-
<form>
83-
<button type="button" class="button" id="logout">Clear ${IDENTITY_NAME}</button>
84-
</form>
152+
153+
<!-- Sidebar for Instructions -->
154+
<aside class="sidebar">
155+
<h3>📋 How to Test</h3>
156+
157+
<div class="section">
158+
<h4>Step 1: Generate ${IDENTITY_NAME}</h4>
159+
<ul>
160+
<li>Enter an email address in the input field</li>
161+
<li>Click "Generate ${IDENTITY_NAME}" button</li>
162+
<li>Wait for the SDK to initialize the token</li>
163+
</ul>
164+
</div>
165+
166+
<div class="section">
167+
<h4>Step 2: Observe Integration</h4>
168+
<ul>
169+
<li>Check "Integration Status" table for token values</li>
170+
<li>Verify Secure Signals data appears</li>
171+
<li>Note: Reload the page to update Secure Signals in localStorage</li>
172+
</ul>
173+
</div>
174+
175+
<div class="section">
176+
<h4>Step 3: View Video Ad</h4>
177+
<ul>
178+
<li>Video player appears after successful token generation</li>
179+
<li>Click "Play" to watch the ad</li>
180+
<li>Ad request includes ${IDENTITY_NAME} token via Secure Signals</li>
181+
</ul>
182+
</div>
183+
184+
<div class="section">
185+
<h4>Step 4: Test Opt-Out</h4>
186+
<ul>
187+
<li>Try the special email: <code>[email protected]</code></li>
188+
<li>Observe "Has opted out?" changes to "yes"</li>
189+
<li>No advertising token is generated</li>
190+
</ul>
191+
</div>
192+
193+
<div class="section">
194+
<h4>What's Happening?</h4>
195+
<ul>
196+
<li><strong>Client-Side Token Generation:</strong> The SDK generates tokens directly in the browser</li>
197+
<li><strong>Auto-Refresh:</strong> Tokens are automatically refreshed by the SDK in the background when expired</li>
198+
<li><strong>Local Storage:</strong> The SDK stores identity in localStorage (__uid2_advertising_token or __euid_advertising_token) for persistence across page loads</li>
199+
<li><strong>Google Secure Signals:</strong> Encrypted tokens are stored in localStorage under ${UID_SECURE_SIGNALS_STORAGE_KEY} and shared with Google Ad Manager</li>
200+
<li><strong>IMA SDK:</strong> Displays video ads with ${IDENTITY_NAME} targeting</li>
201+
</ul>
202+
</div>
203+
204+
<div class="note">
205+
<strong>Note:</strong> This is a test-only environment. Do not use real user data.
206+
</div>
207+
</aside>
85208
</div>
86209
<script src="${UID_JS_SDK_URL}"></script>
87210
<script src="${UID_SECURE_SIGNALS_SDK_URL}"></script>

web-integrations/google-secure-signals/client-side/html/scripts/scripts.js

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,17 @@ function updateGuiElements(state) {
2323

2424
// Check for opt-out: only if user attempted login, and we got identity null with no token
2525
const isOptedOut = loginAttempted && !token && state?.identity === null;
26+
$('#has_opted_out').text(isOptedOut ? 'yes' : 'no');
2627

2728
if (isOptedOut) {
2829
$('#login_form').hide();
29-
$('#logout_form').hide();
30-
$('#optout_message').show();
31-
$('#optout_banner').show();
30+
$('#logout_form').show();
3231
} else if (loginRequired) {
3332
$('#login_form').show();
3433
$('#logout_form').hide();
35-
$('#optout_message').hide();
36-
$('#optout_banner').hide();
3734
} else {
3835
$('#login_form').hide();
3936
$('#logout_form').show();
40-
$('#optout_message').hide();
41-
$('#optout_banner').hide();
4237
}
4338

4439
const secureSignalsStorageKey = '${UID_SECURE_SIGNALS_STORAGE_KEY}';
@@ -81,13 +76,6 @@ function onDocumentReady() {
8176
console.error('setIdentityFromEmail failed', e);
8277
}
8378
});
84-
85-
$('#try_another').click(() => {
86-
window.googletag.secureSignalProviders.clearAllCache();
87-
sdk.disconnect();
88-
$('#email').val('');
89-
loginAttempted = false; // Reset flag
90-
});
9179
}
9280

9381
sdk.callbacks.push(onIdentityUpdated);
@@ -106,8 +94,6 @@ sdk.callbacks.push((eventType, payload) => {
10694
// Set initial UI state - updateGuiElements will adjust based on actual identity state
10795
$('#login_form').show();
10896
$('#logout_form').hide();
109-
$('#optout_message').hide();
110-
$('#optout_banner').hide();
11197
});
11298
}
11399
});

0 commit comments

Comments
 (0)