Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 32 additions & 7 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -1,16 +1,41 @@
# for local development
# UID2_BASE_URL="http://host.docker.internal:8080"
# ==============================================================================
# UID2 Examples Environment Configuration
# ==============================================================================
# Copy this file to .env and update the values for your local development setup.
#
# This file contains configuration for different UID2 integration examples.
# Not all variables are needed for all examples - see comments below.
# ==============================================================================

UID2_BASE_URL="https://operator-integ.uidapi.com"
UID2_CSTG_SERVER_PUBLIC_KEY="UID2-X-I-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEo+jcPlk8GWn3iG0R5Il2cbFQI9hR3TvHxaBUKHl5Vh+ugr+9uLMiXihka8To07ETFGghEifY96Hrpe5RnYko7Q=="
UID2_CSTG_SUBSCRIPTION_ID="DMr7uHxqLU"
# ------------------------------------------------------------------------------
# Server-Side & Client-Server Examples
# ------------------------------------------------------------------------------

UID2_BASE_URL="https://operator-integ.uidapi.com" # For local development using Docker, use: http://host.docker.internal:8080
UID2_API_KEY="your-api-key"
UID2_CLIENT_SECRET="your-client-secret"
SESSION_KEY="your-session-key-here"

# ------------------------------------------------------------------------------
# Client-Side Examples (all client-side token generation examples)
# ------------------------------------------------------------------------------

# For local development with Docker, use UID2_BASE_URL="http://localhost:8080"
UID2_CSTG_SERVER_PUBLIC_KEY="UID2-X-I-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEo+jcPlk8GWn3iG0R5Il2cbFQI9hR3TvHxaBUKHl5Vh+ugr+9uLMiXihka8To07ETFGghEifY96Hrpe5RnYko7Q=="
UID2_CSTG_SUBSCRIPTION_ID="DMr7uHxqLU"

# ------------------------------------------------------------------------------
# JavaScript SDK Configuration
# ------------------------------------------------------------------------------

UID2_JS_SDK_URL="https://cdn.integ.uidapi.com/uid2-sdk-4.0.1.js"
UID2_JS_SDK_NAME="__uid2"
UID2_STORAGE_KEY="__uid2_advertising_token"

REACT_APP_UID2_BASE_URL="https://operator-integ.uidapi.com"
# ------------------------------------------------------------------------------
# React Client-Side Example
# ------------------------------------------------------------------------------

REACT_APP_UID2_BASE_URL="https://operator-integ.uidapi.com" # For local development using npm start, use: http://localhost:8080
REACT_APP_UID2_CSTG_SERVER_PUBLIC_KEY="UID2-X-I-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEo+jcPlk8GWn3iG0R5Il2cbFQI9hR3TvHxaBUKHl5Vh+ugr+9uLMiXihka8To07ETFGghEifY96Hrpe5RnYko7Q=="
REACT_APP_UID2_CSTG_SUBSCRIPTION_ID="DMr7uHxqLU"
REACT_APP_UID2_CSTG_SUBSCRIPTION_ID="DMr7uHxqLU"
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,12 @@ app.post('/login', async (req, res) => {
); //if HTTP response code is not 200, this throws and is caught in the catch handler below.
const response = decrypt(encryptedResponse.data, uid2ClientSecret, nonce);

if (response.status !== 'success') {
if (response.status === 'optout') {
res.render('optout', {
uid2BaseUrl: uid2BaseUrl,
uid2JsSdkUrl: uid2JsSdkUrl,
});
} else if (response.status !== 'success') {
res.render('error', {
error: 'Got unexpected token generate status in decrypted response: ' + response.status,
response: response,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Example for Client-Server UID2 SDK Integration with Google Secure Signals</title>
<link rel="stylesheet" type="text/css" href="/stylesheets/app.css" />
<link rel="shortcut icon" href="/images/favicon.png" />
</head>
<body>
<%- include('intro.html'); -%>
<p class="message">This email has opted out</p>
<p>
The email address you entered has opted out of UID2. No UID2 token can be generated for this
email.
</p>
<p><a href="/">Back to the main page</a></p>
</body>
</html>

Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ <h1>UID2 Publisher Client-Side Integration Example using UID2 JavaScript SDK, Se
</tr>
</table>
</div>
<div id="optout_banner" style="display: none; border: 3px solid #ffc107; padding: 15px; margin: 20px 0;">
<p style="margin: 0;">The email address you entered has opted out of UID2.</p>
</div>
<div id="optout_message" style="display: none" class="form">
<button type="button" class="button" id="try_another">Try Another Email</button>
</div>
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also created an optout banner because the response for opt-out and initial page load is the same.

<div id="login_form" style="display: none" class="form">
<div class="email_prompt">
<input
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ const clientSideIdentityOptions = {
serverPublicKey: '${SERVER_PUBLIC_KEY}',
};

// Track whether user has attempted to generate a token
let loginAttempted = false;

function updateGuiElements(state) {
$('#targeted_advertising_ready').text(__uid2.getAdvertisingToken() ? 'yes' : 'no');
const token = __uid2.getAdvertisingToken();
Expand All @@ -13,12 +16,25 @@ function updateGuiElements(state) {
$('#identity_state').text(String(JSON.stringify(state, null, 2)));

const uid2LoginRequired = __uid2.isLoginRequired();
if (uid2LoginRequired) {

// Check for opt-out: only if user attempted login, and we got identity null with no token
const isOptedOut = loginAttempted && !token && state?.identity === null;

if (isOptedOut) {
$('#login_form').hide();
$('#logout_form').hide();
$('#optout_message').show();
$('#optout_banner').show();
} else if (uid2LoginRequired) {
$('#login_form').show();
$('#logout_form').hide();
$('#optout_message').hide();
$('#optout_banner').hide();
} else {
$('#login_form').hide();
$('#logout_form').show();
$('#optout_message').hide();
$('#optout_banner').hide();
}

const secureSignalsStorage = localStorage['_GESPSK-uidapi.com'];
Expand Down Expand Up @@ -46,18 +62,27 @@ function onDocumentReady() {
$('#logout').click(() => {
window.googletag.secureSignalProviders.clearAllCache();
__uid2.disconnect();
loginAttempted = false; // Reset flag
});

$('#login').click(async () => {
window.googletag.secureSignalProviders.clearAllCache();
const email = $('#email').val();
loginAttempted = true; // Mark that user attempted to generate a token

try {
await __uid2.setIdentityFromEmail(email, clientSideIdentityOptions);
} catch (e) {
console.error('setIdentityFromEmail failed', e);
}
});

$('#try_another').click(() => {
window.googletag.secureSignalProviders.clearAllCache();
__uid2.disconnect();
$('#email').val('');
loginAttempted = false; // Reset flag
});
}

window.__uid2 = window.__uid2 || {};
Expand All @@ -69,6 +94,17 @@ window.__uid2.callbacks.push((eventType, payload) => {
window.__uid2.init({
baseUrl: '${UID_BASE_URL}',
});
$(document).ready(onDocumentReady);
$(document).ready(() => {
// Clear any existing identity on page load for clean state
__uid2.disconnect();
loginAttempted = false;

onDocumentReady();
// Always show login form on initial page load
$('#login_form').show();
$('#logout_form').hide();
$('#optout_message').hide();
$('#optout_banner').hide();
});
}
});
36 changes: 32 additions & 4 deletions web-integrations/google-secure-signals/react-client-side/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,42 @@ This example demonstrates how a content publisher who is working with [Google In

## Build and Run the Example Application

The easiest way to try the example is to use the following docker build command:
You can run this example in two ways:

### Option 1: Running Locally with npm (Recommended)

The fastest way to try the example is to run it locally:

1. Ensure you have a local UID2 operator running at `http://localhost:8080`

2. Add the following environment variables to the `.env` file at the root of the repository (`uid2-examples/.env`):
```
REACT_APP_UID2_BASE_URL="http://localhost:8080"
REACT_APP_UID2_CSTG_SUBSCRIPTION_ID="<your_subscription_id>"
REACT_APP_UID2_CSTG_SERVER_PUBLIC_KEY="<your_server_public_key>"
```

3. Run the application:
```bash
cd web-integrations/google-secure-signals/react-client-side
npm install
npm start
```

The example app will be up and running at `http://localhost:3044`

**Note:** The React app uses `dotenv-cli` to load environment variables from the parent `.env` file. Environment variables for React must be prefixed with `REACT_APP_` to be accessible in the browser.

### Option 2: Build and Run with Docker

Alternatively, you can build and run the example using Docker (note: this may take several minutes):

```
docker build . -t uid2-secure-signals-react
docker run -it --rm -p 3000:3000 uid2-secure-signals-react
docker run -it --rm -p 3044:3044 uid2-secure-signals-react
```

The example app will be up and running at localhost:3000
The example app will be up and running at localhost:3044

If needed, to close the application, terminate the docker container or use the `Ctrl+C` keyboard shortcut.

Expand All @@ -23,7 +51,7 @@ The following table outlines and annotates the steps you may take to test and ex

| Step | Description | Comments |
| :--: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1 | In your browser, navigate to the application main page at `http://localhost:3000`. | The displayed main [page](src/SecureSignalsApp.tsx) of the example application provides a login form for the user to complete the UID2 login process.</br>IMPORTANT: A real-life application must also display a form for the user to express their consent to targeted advertising. |
| 1 | In your browser, navigate to the application main page at `http://localhost:3044`. | The displayed main [page](src/SecureSignalsApp.tsx) of the example application provides a login form for the user to complete the UID2 login process.</br>IMPORTANT: A real-life application must also display a form for the user to express their consent to targeted advertising. |
| 2 | In the text field at the bottom, enter the user email address that you want to use for testing and click **Generate UID2**. Note: The button may be labeled different here as it is a testing environment; in a real production environment, labels may differ. | The click calls the Secure Signal [`clearAllCache()`](https://developers.google.com/publisher-tag/reference#googletag.secureSignals.SecureSignalProvidersArray_clearAllCache) function, to clear all cached signals from local storage. Then, it makes a call on the client side to the `setIdentityFromEmail` function of the JS SDK ([Configuring the SDK for Javascript](https://unifiedid.com/docs/guides/integration-javascript-client-side#configure-the-sdk-for-javascript)). |
| 3 | A confirmation message appears with the established UID2 identity information. | The displayed identity information is the `body` property of the [JSON response payload](https://unifiedid.com/docs/endpoints/post-token-generate#decrypted-json-response-format) from the `client-generate` response. Next, the identity information is passed to the UID2 SDK [`setIdentity()`](https://unifiedid.com/docs/sdks/sdk-ref-javascript#setidentityidentity-identity-void) function. If the identity is valid, the SDK stores it either in local storage or a first-party UID2 cookie (see [UID2 Storage Format](https://unifiedid.com/docs/sdks/sdk-ref-javascript#uid2-storage-format) for use on subsequent page loads.) |
| 4 | Click the **Back to the main page** link. | On the updated application main page, note the newly populated **UID2 Advertising Token** value and a video player. While the [page](src/SecureSignalsApp.tsx) is loading, [GPT](https://developers.google.com/publisher-tag/reference#googletag) auto-loads the Secure Signal UID2 script which pushes the advertising token to GPT local storage, and the [IMA](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side) makes an ad request which transmits the encoded signal in the request. The [page](src/SecureSignalsApp.tsx) calls the [init()](https://unifiedid.com/docs/sdks/sdk-ref-javascript#initopts-object-void) function again, but this time without passing an explicit identity. Instead, the identity is loaded from the first-party cookie or local storage. |
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@
"svgo": "^3.3.2"
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.0"
"@babel/plugin-proposal-private-property-in-object": "^7.21.0",
"dotenv-cli": "^10.0.0"
},
"overrides": {
"nth-check": "^2.0.1",
"form-data": "^4.0.4"
},
"scripts": {
"start": "react-scripts start",
"start": "PORT=3044 dotenv -e ../../../.env -- react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
Expand All @@ -38,4 +39,4 @@
"browserslist": [
"defaults"
]
}
}
Loading