diff --git a/.env.sample b/.env.sample deleted file mode 100644 index c89974be..00000000 --- a/.env.sample +++ /dev/null @@ -1,41 +0,0 @@ -# ============================================================================== -# 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. -# ============================================================================== - -# ------------------------------------------------------------------------------ -# 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 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" diff --git a/.env.sample.euid b/.env.sample.euid new file mode 100644 index 00000000..421bd811 --- /dev/null +++ b/.env.sample.euid @@ -0,0 +1,60 @@ +# ============================================================================== +# EUID Environment Configuration +# ============================================================================== +# This file provides default EUID integration settings. +# Edit the first section with your EUID credentials and keys. +# The values in the bottom section are EUID-specific constants and should NOT +# be changed unless you are configuring for a different EUID environment. +# +# ⚠️ EDIT THESE VALUES FIRST - Your EUID Credentials ⚠️ +# ============================================================================== + +# Server-Side & Client-Server Examples - Provided by your EUID integration representative +UID_API_KEY="your-api-key" +UID_CLIENT_SECRET="your-client-secret" + +# Server-Side Examples - Any secure random string for session encryption +SESSION_KEY="your-session-key-here" + +# Client-Side Token Generation (CSTG) - Provided by your EUID integration representative +UID_CSTG_SERVER_PUBLIC_KEY="your-euid-server-public-key" +UID_CSTG_SUBSCRIPTION_ID="your-euid-subscription-id" + +# React Client-Side Examples - Provided by your EUID integration representative +# Note: These are the same values as the variables above, prefixed with REACT_APP_ +# for use in React applications. Use your same EUID credentials from above. +REACT_APP_UID_CSTG_SERVER_PUBLIC_KEY="your-euid-server-public-key" +REACT_APP_UID_CSTG_SUBSCRIPTION_ID="your-euid-subscription-id" + +# ============================================================================== +# EUID Constants (Do NOT change unless working with different EUID environment) +# ============================================================================== + +# API Endpoints (Integration environment) +UID_SERVER_BASE_URL="https://integ.euid.eu" # ← For local development, use: http://host.docker.internal:8080 +UID_CLIENT_BASE_URL="https://integ.euid.eu" # ← For local development, use: http://localhost:8080 + +# JavaScript SDK Configuration +UID_JS_SDK_URL="https://cdn.integ.euid.eu/euid-sdk-4.0.1.js" +UID_JS_SDK_NAME="__euid" + +# Google Secure Signals Configuration +UID_SECURE_SIGNALS_SDK_URL="https://cdn.integ.euid.eu/euidSecureSignal.js" +UID_SECURE_SIGNALS_STORAGE_KEY="_GESPSK-euid.eu" + +# Prebid Configuration +UID_STORAGE_KEY="__euid_advertising_token" + +# UI Display Configuration +IDENTITY_NAME="EUID" +DOCS_BASE_URL="https://euid.eu/docs" + + +# React Constants (for React-based examples) +REACT_APP_UID_CLIENT_BASE_URL="https://integ.euid.eu" # ← For local development, use: http://localhost:8080 +REACT_APP_UID_JS_SDK_NAME="__euid" +REACT_APP_UID_SECURE_SIGNALS_SDK_URL="https://cdn.integ.euid.eu/euidSecureSignal.js" +REACT_APP_UID_SECURE_SIGNALS_STORAGE_KEY="_GESPSK-euid.eu" +REACT_APP_IDENTITY_NAME="EUID" +REACT_APP_DOCS_BASE_URL="https://euid.eu/docs" + diff --git a/.env.sample.uid2 b/.env.sample.uid2 new file mode 100644 index 00000000..f57c04b0 --- /dev/null +++ b/.env.sample.uid2 @@ -0,0 +1,58 @@ +# ============================================================================== +# UID2 Environment Configuration +# ============================================================================== +# This file provides default UID2 integration settings. +# Edit the first section with your UID2 credentials and keys. +# The values in the bottom section are UID2-specific constants and should NOT +# be changed unless you are configuring for a different UID2 environment. +# +# ⚠️ EDIT THESE VALUES FIRST - Your UID2 Credentials ⚠️ +# ============================================================================== + +# Server-Side & Client-Server Examples +UID_API_KEY="your-api-key" +UID_CLIENT_SECRET="your-client-secret" + +# Server-Side Examples - Any secure random string for session encryption +SESSION_KEY="your-session-key-here" + +# Client-Side Token Generation (CSTG) +UID_CSTG_SERVER_PUBLIC_KEY="UID2-X-I-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEo+jcPlk8GWn3iG0R5Il2cbFQI9hR3TvHxaBUKHl5Vh+ugr+9uLMiXihka8To07ETFGghEifY96Hrpe5RnYko7Q==" +UID_CSTG_SUBSCRIPTION_ID="DMr7uHxqLU" + +# React Client-Side Examples +# Note: These are the same values as the variables above, prefixed with REACT_APP_ +# for use in React applications. Use your same UID2 credentials from above. +REACT_APP_UID_CSTG_SERVER_PUBLIC_KEY="UID2-X-I-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEo+jcPlk8GWn3iG0R5Il2cbFQI9hR3TvHxaBUKHl5Vh+ugr+9uLMiXihka8To07ETFGghEifY96Hrpe5RnYko7Q==" +REACT_APP_UID_CSTG_SUBSCRIPTION_ID="DMr7uHxqLU" + +# ============================================================================== +# UID2 Constants (Do NOT change unless working with different UID2 environment) +# ============================================================================== + +# API Endpoints (Integration environment) +UID_SERVER_BASE_URL="https://operator-integ.uidapi.com" # ← For local development, use: http://host.docker.internal:8080 +UID_CLIENT_BASE_URL="https://operator-integ.uidapi.com" # ← For local development, use: http://localhost:8080 + +# JavaScript SDK Configuration +UID_JS_SDK_URL="https://cdn.integ.uidapi.com/uid2-sdk-4.0.1.js" +UID_JS_SDK_NAME="__uid2" + +# Google Secure Signals Configuration +UID_SECURE_SIGNALS_SDK_URL="https://cdn.integ.uidapi.com/uid2SecureSignal.js" +UID_SECURE_SIGNALS_STORAGE_KEY="_GESPSK-uidapi.com" + +# Prebid Configuration +UID_STORAGE_KEY="__uid2_advertising_token" + +# UI Display Configuration +IDENTITY_NAME="UID2" +DOCS_BASE_URL="https://unifiedid.com/docs" + +# React Constants (for React-based examples) +REACT_APP_UID_CLIENT_BASE_URL="https://operator-integ.uidapi.com" # ← For local development, use: http://localhost:8080 +REACT_APP_UID_JS_SDK_NAME="__uid2" +REACT_APP_UID_SECURE_SIGNALS_SDK_URL="https://cdn.integ.uidapi.com/uid2SecureSignal.js" +REACT_APP_UID_SECURE_SIGNALS_STORAGE_KEY="_GESPSK-uidapi.com" +REACT_APP_IDENTITY_NAME="UID2" +REACT_APP_DOCS_BASE_URL="https://unifiedid.com/docs" \ No newline at end of file diff --git a/README.md b/README.md index 31ae2531..dfec8c8b 100644 --- a/README.md +++ b/README.md @@ -77,15 +77,32 @@ docker-compose up -d --build prebid-client ### Environment Configuration -Edit the `.env` file in the base directory to configure your UID2 settings: -``` -# UID2 Configuration for all services -UID2_BASE_URL="http://localhost:8080" -SERVER_PUBLIC_KEY="your-public-key" -SUBSCRIPTION_ID="your-subscription-id" - -# Additional variables for client-server example -UID2_API_KEY="your-api-key" -UID2_CLIENT_SECRET="your-client-secret" -``` +This repository includes sample environment files for both UID2 and EUID configurations: + +- **`.env.sample.uid2`** - UID2 configuration template +- **`.env.sample.euid`** - EUID configuration template + +**To get started:** + +1. Copy the appropriate sample file to `.env`: + ```bash + # For UID2 + cp .env.sample.uid2 .env + + # For EUID + cp .env.sample.euid .env + ``` + +2. Update the `.env` file with your credentials: + - Replace `your-api-key` with your actual API key + - Replace `your-client-secret` with your actual client secret + - Update other placeholder values as needed + +The sample files include all necessary environment variables for running the examples, including configuration for: +- Core API endpoints +- JavaScript SDK settings +- Google Secure Signals integration +- Prebid integration +- React client examples +- UI/Display preferences diff --git a/web-integrations/google-secure-signals/client-server/README.md b/web-integrations/google-secure-signals/client-server/README.md index 6f4e3edd..391f7917 100644 --- a/web-integrations/google-secure-signals/client-server/README.md +++ b/web-integrations/google-secure-signals/client-server/README.md @@ -1,8 +1,13 @@ -# Client-Server UID2 SDK Integration Example with Google Secure Signals +# Client-Server UID2 or EUID SDK Integration Example with Google Secure Signals -This example demonstrates how a content publisher who is working with [Google Interactive Media Ads(IMA) SDKs](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side) can use [Google Secure Signal](https://support.google.com/admanager/answer/10488752) and the [UID2 SDK for JavaScript](https://unifiedid.com/docs/sdks/sdk-ref-javascript) to share UID2 directly with bidders, in an implementation that uses this SDK. +This example demonstrates how a content publisher who is working with [Google Interactive Media Ads(IMA) SDKs](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side) can use [Google Secure Signal](https://support.google.com/admanager/answer/10488752) and either the UID2 or EUID SDK for JavaScript to share tokens directly with bidders, in a client-server implementation that uses this SDK. -For an example application without using the UID2 SDK, see [Server-Side UID2 Integration Example with Google Secure Signals](../server-side/README.md). +- For UID2: [UID2 SDK for JavaScript](https://unifiedid.com/docs/sdks/sdk-ref-javascript), [Google Ad Manager Secure Signals Integration Guide](https://unifiedid.com/docs/guides/integration-google-ss#sdk-for-javascript-client-server-integration) +- For EUID: [EUID SDK for JavaScript](https://euid.eu/docs/sdks/sdk-ref-javascript), [EUID Google Ad Manager Secure Signals Integration Guide](https://euid.eu/docs/guides/integration-google-ss#sdk-for-javascript-client-server-integration) + +This example can be configured for either UID2 or EUID — the behavior is determined by your environment variable configuration. You cannot use both simultaneously. + +For an example application without using the SDK, see [Server-Side UID2 or EUID Integration Example with Google Secure Signals](../server-side/README.md). > NOTE: Although the server side of the example application is implemented in JavaScript using node.js, it is not a requirement. You can use any technology of your choice and refer to the example application for an illustration of the functionality that needs to be implemented. @@ -10,29 +15,33 @@ For an example application without using the UID2 SDK, see [Server-Side UID2 Int ### Using Docker Compose (Recommended) -From the base directory: +From the repository root directory: ```bash # Start the service -docker-compose up -d google-secure-signals-client +docker compose up google-secure-signals-client-server +``` + +The application will be available at http://localhost:3041 + +To view logs or stop the service: -# View logs -docker-compose logs google-secure-signals-client +```bash +# View logs (in another terminal) +docker compose logs google-secure-signals-client-server # Stop the service -docker-compose down google-secure-signals-client +docker compose stop google-secure-signals-client-server ``` -### Using Docker directly - -From the base directory: +### Using Docker Build ```bash # Build the image -docker build -f web-integrations/google-secure-signals/client-server/Dockerfile -t google-secure-signals-client . +docker build -f web-integrations/google-secure-signals/client-server/Dockerfile -t google-secure-signals-client-server . # Run the container -docker run -p 3052:3052 --env-file .env google-secure-signals-client +docker run -it --rm -p 3041:3041 --env-file .env google-secure-signals-client-server ``` ### Using the VS Code Debugger @@ -40,28 +49,33 @@ docker run -p 3052:3052 --env-file .env google-secure-signals-client The easiest way to try the example is to do the following: 1. Open this repo in VS Code -1. Create a `.env` file in the base directory and populate the required variables: - ``` - UID2_BASE_URL=http://localhost:8080 - UID2_API_KEY= - UID2_CLIENT_SECRET= - AD_TAG_URL=https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/extrernal/adx-test-tag&tfcd=0&npa=0&sz=640x480&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator= - UID2_JS_SDK_URL=http://localhost:9091/uid2-sdk.js - PORT=3052 +1. Copy the appropriate sample environment file to `.env` in the base directory: + ```bash + # For UID2 + cp .env.sample.uid2 .env + + # For EUID + cp .env.sample.euid .env ``` +1. Update the `.env` file with your credentials 1. Click the Run and Debug tab or hit `Crtl+Shift+D` 1. Select `Launch Secure Signals (Chrome)` from the configuration dropdown 1. Click `Start Debugging` or hit F5 -The following table lists the environment variables that you must specify to start the application. +### Environment Variables -| Parameter | Data Type | Description | -| :------------------- | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `UID2_BASE_URL` | string | The base URL of the UID2 service. For example:
Testing environment: `https://integ.uidapi.com`
Production environment: `https://prod.uidapi.com` | -| `UID2_API_KEY` | string | Your UID2 authentication key for the UID2 service specified in `UID2_BASE_URL`. | -| `UID2_CLIENT_SECRET` | string | Your UID2 client secret for the UID2 service specified in `UID2_BASE_URL`. | -| `AD_TAG_URL` | string | The ad tag URL to test ad requests. | -| `UID2_JS_SDK_URL` | string | The UID2 JS SDK. If this optional parameter it not provided, it will default to the integ URL specified in `server.js` | +| Variable | Description | Example Values | +|:---------|:------------|:---------------| +| `UID_SERVER_BASE_URL` | The base URL of the UID2/EUID service for server-side API calls | UID2: `https://operator-integ.uidapi.com`
EUID: `https://integ.euid.eu` | +| `UID_API_KEY` | Your UID2/EUID authentication key for the UID2/EUID service specified in UID_SERVER_BASE_URL. | Your assigned API key | +| `UID_CLIENT_SECRET` | Your UID2/EUID client secret for the UID2/EUID service specified in UID_SERVER_BASE_URL. | Your assigned client secret | +| `UID_JS_SDK_URL` | URL to the JavaScript SDK | UID2: `https://cdn.integ.uidapi.com/uid2-sdk-4.0.1.js`
EUID: `https://cdn.integ.euid.eu/euid-sdk-4.0.1.js` | +| `UID_JS_SDK_NAME` | Global variable name for the SDK | UID2: `__uid2`
EUID: `__euid` | +| `UID_SECURE_SIGNALS_SDK_URL` | URL to the Secure Signals SDK | UID2: `https://cdn.integ.uidapi.com/uid2SecureSignal.js`
EUID: `https://cdn.integ.euid.eu/euidSecureSignal.js` | +| `IDENTITY_NAME` | Identity name for UI display | UID2: `UID2`
EUID: `EUID` | +| `DOCS_BASE_URL` | Documentation base URL | UID2: `https://unifiedid.com/docs`
EUID: `https://euid.eu/docs` | + +**Note:** The example uses a Google IMA sample ad tag URL in `public/ads.js`. To test with your own ad tag, edit line 56 in `public/ads.js` to use your ad tag URL. Output similar to the following indicates that the example application is up and running. @@ -69,21 +83,23 @@ Output similar to the following indicates that the example application is up and > uid2-publisher@1.0.0 start /usr/src/app > node server.js -Example app listening at http://localhost:3052 +Example app listening at http://localhost:3041 ``` If needed, to close the application, terminate the Docker container or use the `Ctrl+C` keyboard shortcut. ## Test the Example Application +**Note:** For API endpoint documentation, see the UID2 or EUID docs based on your configuration. + The following table outlines and annotates the steps you can take to test and explore the example application. | Step | Description | Comments | | :--: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| 1 | In your browser, navigate to the application main page at `http://localhost:3052`. | The displayed main ([index](views/index.html)) page of the example application provides a login form for the user to complete the UID2 login process.
IMPORTANT: A real-life application must also display a form for the user to consent to targeted advertising. | -| 2 | In the text field at the bottom, enter the 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, and then calls the `/login` endpoint ([server.js](server.js)). The login initiated on the server side then calls the [POST /token/generate](https://unifiedid.com/docs/endpoints/post-token-generate#decrypted-json-response-format) endpoint and processes the received response. | -| | 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 `POST /token/generate` response. It has been passed to the `login` [view](views/login.html) for rendering client-side JavaScript. Next, the identity information is passed to the UID2 SDK [`init()`](https://unifiedid.com/docs/sdks/sdk-ref-javascript#initopts-object-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. | -| 3 | 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 view](views/index.html) 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 view](views/index.html) 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. | +| 1 | In your browser, navigate to the application main page at `http://localhost:3041`. | The displayed main ([index](views/index.html)) page of the example application provides a login form for the user to complete the UID2/EUID login process.
IMPORTANT: A real-life application must also display a form for the user to consent to targeted advertising. | +| 2 | In the text field at the bottom, enter the email address that you want to use for testing and click **Generate UID2** or **Generate EUID**. Note: The button label depends on your environment configuration; 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, and then calls the `/login` endpoint ([server.js](server.js)). The login initiated on the server side then calls the POST /token/generate endpoint (see [POST /token/generate](https://unifiedid.com/docs/endpoints/post-token-generate#decrypted-json-response-format) for UID2 or [POST /token/generate](https://euid.eu/docs/endpoints/post-token-generate#decrypted-json-response-format) for EUID) and processes the received response. | +| | A confirmation message appears with the established identity information. | The displayed identity information is the `body` property of the JSON response payload from the POST /token/generate response (see [Decrypted JSON Response Format](https://unifiedid.com/docs/endpoints/post-token-generate#decrypted-json-response-format) for UID2 or [Decrypted JSON Response Format](https://euid.eu/docs/endpoints/post-token-generate#decrypted-json-response-format) for EUID). It has been passed to the `login` [view](views/login.html) for rendering client-side JavaScript. Next, the identity information is passed to the SDK [`init()`](https://unifiedid.com/docs/sdks/sdk-ref-javascript#initopts-object-void) function. If the identity is valid, the SDK stores it either in local storage or a first-party cookie for use on subsequent page loads. | +| 3 | Click the **Back to the main page** link. | On the updated application main page, note the newly populated **Advertising Token** value and a video player. While the [page view](views/index.html) is loading, [GPT](https://developers.google.com/publisher-tag/reference#googletag) auto-loads the Secure Signal 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 view](views/index.html) 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. | | 4 | Click **Play**. | This triggers AdsManager to insert the ad returned from the ad request, for display. The ad tag used in this example contains a 10-second pre-roll ad. | -| 5 | Keep the application main page open, or refresh it after a while, and note the UID2 identity state, updated counter, and login information values. | In the background, the UID2 SDK continuously validates whether the advertising token is up to date, and refreshes it automatically when needed. If the refresh succeeds, the user opts out, or the refresh token expires, the callback function is invoked, and the UI elements are updated with the current state of the UID2 identity. For details, see [Workflow Overview](https://unifiedid.com/docs/sdks/sdk-ref-javascript#workflow-overview) and [Background Token Auto-Refresh](https://unifiedid.com/docs/sdks/sdk-ref-javascript#background-token-auto-refresh). | -| 6 | To exit the application, click **Clear UID2**. | This event calls the UID2 SDK [`disconnect()`](https://unifiedid.com/docs/sdks/sdk-ref-javascript#disconnect-void) function, which clears the UID2 session and the first-party cookie and calls the Secure Signal [`clearAllCache()`](https://developers.google.com/publisher-tag/reference#googletag.secureSignals.SecureSignalProvidersArray_clearAllCache) function to clear all cached signals. This call also makes the UID2 SDK [`isLoginRequired()`](https://unifiedid.com/docs/sdks/sdk-ref-javascript#isloginrequired-boolean) function return `true`, which presents the user with the login form again.
NOTE: The page displays the **Clear UID2** button as long as the user identity is valid and refreshable within the integration test environment. | +| 5 | Keep the application main page open, or refresh it after a while, and note the identity state, updated counter, and login information values. | In the background, the SDK continuously validates whether the advertising token is up to date, and refreshes it automatically when needed. If the refresh succeeds, the user opts out, or the refresh token expires, the callback function is invoked, and the UI elements are updated with the current state of the identity. For details, see [Workflow Overview](https://unifiedid.com/docs/sdks/sdk-ref-javascript#workflow-overview) (UID2) or [Workflow Overview](https://euid.eu/docs/sdks/sdk-ref-javascript#workflow-overview) (EUID), and [Background Token Auto-Refresh](https://unifiedid.com/docs/sdks/sdk-ref-javascript#background-token-auto-refresh). | +| 6 | To exit the application, click **Clear UID2** or **Clear EUID**. | This event calls the SDK [`disconnect()`](https://unifiedid.com/docs/sdks/sdk-ref-javascript#disconnect-void) function, which clears the session and the first-party cookie and calls the Secure Signal [`clearAllCache()`](https://developers.google.com/publisher-tag/reference#googletag.secureSignals.SecureSignalProvidersArray_clearAllCache) function to clear all cached signals. This call also makes the SDK [`isLoginRequired()`](https://unifiedid.com/docs/sdks/sdk-ref-javascript#isloginrequired-boolean) function return `true`, which presents the user with the login form again.
NOTE: The page displays the **Clear** button as long as the user identity is valid and refreshable within the integration test environment. | diff --git a/web-integrations/google-secure-signals/client-server/public/ads.js b/web-integrations/google-secure-signals/client-server/public/ads.js index fc92752e..98ce8b29 100644 --- a/web-integrations/google-secure-signals/client-server/public/ads.js +++ b/web-integrations/google-secure-signals/client-server/public/ads.js @@ -52,7 +52,8 @@ function setUpIMA() { // Request video ads. const adsRequest = new google.ima.AdsRequest(); - adsRequest.adTagUrl = '${AD_TAG_URL}'; + // Using Google IMA sample ad tag - replace with your own ad tag URL for production + adsRequest.adTagUrl = 'https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_ad_samples&sz=640x480&cust_params=sample_ct%3Dlinear&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator='; // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. diff --git a/web-integrations/google-secure-signals/client-server/server.js b/web-integrations/google-secure-signals/client-server/server.js index ab2c8145..b8ddb6bd 100644 --- a/web-integrations/google-secure-signals/client-server/server.js +++ b/web-integrations/google-secure-signals/client-server/server.js @@ -9,11 +9,20 @@ const crypto = require('crypto'); const app = express(); const port = process.env.PORT || 3041; -const uid2BaseUrl = process.env.UID2_BASE_URL; -const uid2ApiKey = process.env.UID2_API_KEY; -const uid2ClientSecret = process.env.UID2_CLIENT_SECRET; -const uid2JsSdkUrl = - process.env.UID2_JS_SDK_URL || 'https://cdn.integ.uidapi.com/uid2-sdk-4.0.1.js'; +const uidBaseUrl = process.env.UID_SERVER_BASE_URL; +const uidApiKey = process.env.UID_API_KEY; +const uidClientSecret = process.env.UID_CLIENT_SECRET; + +// JavaScript SDK configuration +const uidJsSdkUrl = process.env.UID_JS_SDK_URL || 'https://cdn.integ.uidapi.com/uid2-sdk-4.0.1.js'; +const uidJsSdkName = process.env.UID_JS_SDK_NAME || '__uid2'; + +// Secure Signals configuration +const secureSignalsSdkUrl = process.env.UID_SECURE_SIGNALS_SDK_URL || 'https://cdn.integ.uidapi.com/uid2SecureSignal.js'; + +// UI/Display configuration +const identityName = process.env.IDENTITY_NAME; +const docsBaseUrl = process.env.DOCS_BASE_URL; const ivLength = 12; const nonceLength = 8; @@ -27,7 +36,14 @@ app.engine('.html', ejs.__express); app.set('view engine', 'html'); app.get('/', (req, res) => { - res.render('index', { uid2BaseUrl: uid2BaseUrl, uid2JsSdkUrl: uid2JsSdkUrl }); + res.render('index', { + uidBaseUrl, + uidJsSdkUrl, + uidJsSdkName, + secureSignalsSdkUrl, + identityName, + docsBaseUrl + }); }); function bufferToBase64(arrayBuffer) { @@ -90,7 +106,7 @@ function createEnvelope(payload) { const payloadEncoded = new TextEncoder().encode(payload); const body = Buffer.concat([Buffer.from(new Uint8Array(bufferMillisec)), nonce, payloadEncoded]); - const { ciphertext, iv } = encryptRequest(body, uid2ClientSecret); + const { ciphertext, iv } = encryptRequest(body, uidClientSecret); const envelopeVersion = Buffer.alloc(1, 1); const envelope = bufferToBase64( @@ -104,41 +120,58 @@ app.post('/login', async (req, res) => { const { envelope, nonce } = createEnvelope(jsonEmail); const headers = { - headers: { Authorization: 'Bearer ' + uid2ApiKey }, + headers: { Authorization: 'Bearer ' + uidApiKey }, }; try { const encryptedResponse = await axios.post( - uid2BaseUrl + '/v2/token/generate', + uidBaseUrl + '/v2/token/generate', envelope, headers ); //if HTTP response code is not 200, this throws and is caught in the catch handler below. - const response = decrypt(encryptedResponse.data, uid2ClientSecret, nonce); + const response = decrypt(encryptedResponse.data, uidClientSecret, nonce); if (response.status === 'optout') { res.render('optout', { - uid2BaseUrl: uid2BaseUrl, - uid2JsSdkUrl: uid2JsSdkUrl, + uidBaseUrl, + uidJsSdkUrl, + uidJsSdkName, + secureSignalsSdkUrl, + identityName, + docsBaseUrl }); } else if (response.status !== 'success') { res.render('error', { error: 'Got unexpected token generate status in decrypted response: ' + response.status, - response: response, + response, + identityName, + docsBaseUrl }); } else if (typeof response.body !== 'object') { res.render('error', { error: 'Unexpected token generate response format in decrypted response: ' + response, - response: response, + response, + identityName, + docsBaseUrl }); } else { res.render('login', { identity: response.body, - uid2BaseUrl: uid2BaseUrl, - uid2JsSdkUrl: uid2JsSdkUrl, + uidBaseUrl, + uidJsSdkUrl, + uidJsSdkName, + secureSignalsSdkUrl, + identityName, + docsBaseUrl }); } } catch (error) { - res.render('error', { error: error, response: error.response }); + res.render('error', { + error, + response: error.response, + identityName, + docsBaseUrl + }); } }); diff --git a/web-integrations/google-secure-signals/client-server/views/error.html b/web-integrations/google-secure-signals/client-server/views/error.html index a7968c55..b27b697b 100644 --- a/web-integrations/google-secure-signals/client-server/views/error.html +++ b/web-integrations/google-secure-signals/client-server/views/error.html @@ -2,7 +2,7 @@ - Error - Client-Server UID2 SDK Integration Example with Google Secure Signals + Error - Client-Server <%- identityName %> SDK Integration Example with Google Secure Signals @@ -10,7 +10,7 @@ <%- include('intro.html'); -%>

Something went wrong:

<%= error %>
-

Response from the UID2 operator:

+

Response from the <%- identityName %> operator:

<%= response ? JSON.stringify(response.data) : '' %>

HTTP error:

<%= response ? (response.status + ' ' + response.statusText) : '' %>
diff --git a/web-integrations/google-secure-signals/client-server/views/index.html b/web-integrations/google-secure-signals/client-server/views/index.html index ece21b81..fe5ba606 100644 --- a/web-integrations/google-secure-signals/client-server/views/index.html +++ b/web-integrations/google-secure-signals/client-server/views/index.html @@ -2,7 +2,7 @@ - Client-Server UID2 SDK Integration Example with Google Secure Signals + Client-Server <%- identityName %> SDK Integration Example with Google Secure Signals @@ -11,17 +11,20 @@ @@ -76,8 +77,8 @@ - - + + @@ -93,19 +94,19 @@

       
       
-        UID2 Advertising Token:
+        <%- identityName %> Advertising Token:
         

       
       
-        Is UID2 Login Required?
+        Is <%- identityName %> Login Required?
         

       
       
-        UID2 Identity Updated Counter:
+        <%- identityName %> Identity Updated Counter:
         

       
       
-        UID2 Identity Callback State:
+        <%- identityName %> Identity Callback State:
         

       
     
@@ -120,12 +121,12 @@
             style="border-style: none"
           />
         
-        
+
diff --git a/web-integrations/google-secure-signals/client-server/views/intro.html b/web-integrations/google-secure-signals/client-server/views/intro.html index d8473160..fbfb4098 100644 --- a/web-integrations/google-secure-signals/client-server/views/intro.html +++ b/web-integrations/google-secure-signals/client-server/views/intro.html @@ -1,13 +1,13 @@ -

Client-Server UID2 SDK Integration Example with Google Secure Signals

+

Client-Server <%- identityName %> SDK Integration Example with Google Secure Signals

- This example demonstrates how a content publisher can use the UID2 services and the - UID2 SDK for JavaScript services and the + <%- identityName %> SDK for JavaScript to implement the client-server UID2 integration with Secure Signalsclient-server <%- identityName %> integration with Secure Signals. [Source Code - Login - Client-Server UID2 SDK Integration Example with Google Secure Signals + Login - Client-Server <%- identityName %> SDK Integration Example with Google Secure Signals - - + + <%- include('intro.html'); -%> -

Generate UID2 completed

-

UID2 identity:

+

Generate <%- identityName %> completed

+

<%- identityName %> identity:

<%- JSON.stringify(identity, null, 2) %>

Back to the main page

- Normally user would be redirected automatically, but this example demonstrates one way UID2 + Normally user would be redirected automatically, but this example demonstrates one way <%- identityName %> generation could be handled.

diff --git a/web-integrations/google-secure-signals/client-server/views/optout.html b/web-integrations/google-secure-signals/client-server/views/optout.html index 00b1e2e7..b6957e4c 100644 --- a/web-integrations/google-secure-signals/client-server/views/optout.html +++ b/web-integrations/google-secure-signals/client-server/views/optout.html @@ -2,7 +2,7 @@ - Opted Out - Client-Server UID2 SDK Integration Example with Google Secure Signals + Opted Out - Client-Server <%- identityName %> SDK Integration Example with Google Secure Signals @@ -10,7 +10,7 @@ <%- include('intro.html'); -%>

This email has opted out

- The email address you entered has opted out of UID2. No UID2 token can be generated for this + The email address you entered has opted out of <%- identityName %>. No <%- identityName %> token can be generated for this email.

Back to the main page

diff --git a/web-integrations/google-secure-signals/client-side/README.md b/web-integrations/google-secure-signals/client-side/README.md index 20cac11b..2e012a33 100644 --- a/web-integrations/google-secure-signals/client-side/README.md +++ b/web-integrations/google-secure-signals/client-side/README.md @@ -1,33 +1,95 @@ -# Client-Side UID2 SDK Integration Example with Google Secure Signals +# Client-Side UID2 or EUID SDK Integration Example with Google Secure Signals -This example demonstrates how a content publisher who is working with [Google Interactive Media Ads(IMA) SDKs](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side) can use [Google Secure Signal](https://support.google.com/admanager/answer/10488752) and the [UID2 SDK for JavaScript](https://unifiedid.com/docs/sdks/sdk-ref-javascript) to share UID2 directly with bidders, in an implementation that uses this JS SDK on the client side. +This example demonstrates how a content publisher who is working with [Google Interactive Media Ads(IMA) SDKs](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side) can use [Google Secure Signal](https://support.google.com/admanager/answer/10488752) and either the UID2 or EUID SDK for JavaScript to share tokens directly with bidders, in a client-side implementation that uses this SDK. + +- For UID2: [UID2 SDK for JavaScript](https://unifiedid.com/docs/sdks/sdk-ref-javascript), [Google Ad Manager Secure Signals Integration Guide](https://unifiedid.com/docs/guides/integration-google-ss) +- For EUID: [EUID SDK for JavaScript](https://euid.eu/docs/sdks/sdk-ref-javascript), [EUID Google Ad Manager Secure Signals Integration Guide](https://euid.eu/docs/guides/integration-google-ss) + +This example can be configured for either UID2 or EUID — the behavior is determined by your environment variable configuration. You cannot use both simultaneously. ## Build and Run the Example Application -The easiest way to try the example is to use the following docker build command: +### Environment Configuration + +Copy the appropriate sample environment file: + +```bash +# For UID2 +cp .env.sample.uid2 .env + +# For EUID +cp .env.sample.euid .env +``` + +Then update the `.env` file with your credentials. + +### Running with Docker + +#### Using Docker Compose (Recommended) + +From the repository root directory: +```bash +# Start the service +docker compose up google-secure-signals-client-side ``` -docker build . -t uid2-secure-signals-client-side -docker run -it --rm -p 3000:3000 uid2-secure-signals-client-side + +The application will be available at http://localhost:3042 + +To view logs or stop the service: + +```bash +# View logs (in another terminal) +docker compose logs google-secure-signals-client-side + +# Stop the service +docker compose stop google-secure-signals-client-side +``` + +#### Using Docker Build + +```bash +# Build the image +docker build -f web-integrations/google-secure-signals/client-side/Dockerfile -t google-secure-signals-client-side . + +# Run the container +docker run -it --rm -p 3042:3042 --env-file .env google-secure-signals-client-side ``` -The example app will be up and running at localhost:3000 +### Environment Variables + +| Variable | Description | Example Values | +|:---------|:------------|:---------------| +| `UID_CLIENT_BASE_URL` | API base URL for client-side/browser calls | UID2: `https://operator-integ.uidapi.com`
EUID: `https://integ.euid.eu` | +| `UID_BASE_URL` | Fallback API base URL (used if `UID_CLIENT_BASE_URL` not set) | Same as above | +| `UID_CSTG_SERVER_PUBLIC_KEY` | Your server public key for client-side token generation for the UID2/EUID service specified in UID_BASE_URL. | Your assigned server public key | +| `UID_CSTG_SUBSCRIPTION_ID` | Your subscription ID for client-side token generation for the UID2/EUID service specified in UID_BASE_URL. | Your assigned subscription ID | +| `UID_JS_SDK_URL` | URL to the JavaScript SDK | UID2: `https://cdn.integ.uidapi.com/uid2-sdk-4.0.1.js`
EUID: `https://cdn.integ.euid.eu/euid-sdk-4.0.1.js` | +| `UID_JS_SDK_NAME` | Global variable name for the SDK | UID2: `__uid2`
EUID: `__euid` | +| `UID_SECURE_SIGNALS_SDK_URL` | URL to the Secure Signals SDK | UID2: `https://cdn.integ.uidapi.com/uid2SecureSignal.js`
EUID: `https://cdn.integ.euid.eu/euidSecureSignal.js` | +| `UID_SECURE_SIGNALS_STORAGE_KEY` | Local storage key for Secure Signals | UID2: `_GESPSK-uidapi.com`
EUID: `_GESPSK-euid.eu` | +| `IDENTITY_NAME` | Identity name for UI display | UID2: `UID2`
EUID: `EUID` | +| `DOCS_BASE_URL` | Documentation base URL | UID2: `https://unifiedid.com/docs`
EUID: `https://euid.eu/docs` | If needed, to close the application, terminate the docker container or use the `Ctrl+C` keyboard shortcut. ## Test the Example Application -The example application illustrates the steps documented in the [Google Ad Manager Secure Signals Integration Guide](https://unifiedid.com/docs/guides/integration-google-ss). For an overview of the high-level workflow for establishing UID2 identity, API reference, and explanation of the UID2 cookie format, see [UID2 SDK for JavaScript](https://unifiedid.com/docs/sdks/sdk-ref-javascript). +The example application illustrates the steps documented in the Google Ad Manager Secure Signals Integration guides: +- UID2: [Google Ad Manager Secure Signals Integration Guide](https://unifiedid.com/docs/guides/integration-google-ss), [UID2 SDK for JavaScript](https://unifiedid.com/docs/sdks/sdk-ref-javascript) +- EUID: [EUID Google Ad Manager Secure Signals Integration Guide](https://euid.eu/docs/guides/integration-google-ss), [EUID SDK for JavaScript](https://euid.eu/docs/sdks/sdk-ref-javascript) + +**Note:** For API endpoint documentation, see the UID2 or EUID docs based on your configuration. The following table outlines and annotates the steps you may take to test and explore the example application. | Step | Description | Comments | | :--: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 1 | In your browser, navigate to the application main page at `http://localhost:3000`. | The displayed main [page](views/index.html) of the example application provides a login form for the user to complete the UID2 login process.
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](views/index.html) 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](views/index.html) 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. | +| 1 | In your browser, navigate to the application main page at `http://localhost:3042`. | The displayed main [page](views/index.html) of the example application provides a login form for the user to complete the UID2/EUID login process.
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** or **Generate EUID**. Note: The button label depends on your environment configuration; 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 JavaScript SDK. For details, see [Configuring the SDK for Javascript](https://unifiedid.com/docs/guides/integration-javascript-client-side#configure-the-sdk-for-javascript) (UID2) or [Configuring the SDK for Javascript](https://euid.eu/docs/guides/integration-javascript-client-side#configure-the-sdk-for-javascript) (EUID). | +| 3 | A confirmation message appears with the established identity information. | The displayed identity information is the `body` property of the JSON response payload from the `client-generate` response (see [Decrypted JSON Response Format](https://unifiedid.com/docs/endpoints/post-token-generate#decrypted-json-response-format) for UID2 or [Decrypted JSON Response Format](https://euid.eu/docs/endpoints/post-token-generate#decrypted-json-response-format) for EUID). Next, the identity information is passed to the 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 cookie 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 **Advertising Token** value and a video player. While the [page](views/index.html) is loading, [GPT](https://developers.google.com/publisher-tag/reference#googletag) auto-loads the Secure Signal 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](views/index.html) calls the SDK [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. | | 5 | Click **Play**. | This triggers AdsManager to insert the ad returned from the ad request, for display. The ad tag used in this example contains a 10-second pre-roll ad. | -| 6 | (Optional) Right-click the main page to inspect the source code. | When the UID2 SDK initialization is complete, the SDK invokes the passed [callback function](https://unifiedid.com/docs/sdks/client-side-identity#callback-function) (`onUid2IdentityUpdated()` in this example).
IMPORTANT: The callback updates the page elements with the state of UID2 identity: this is the place where you should define your logic for initiating targeted advertising. | -| 7 | Keep the application main page open or refresh it after awhile and note the UID2 identity state, updated counter, and login information values. | In the background, the UID2 SDK continuously validates whether the advertising token is up-to-date and refreshes it automatically when needed. If the refresh succeeds, the user opts out, or the refresh token expires, the callback function is invoked and the UI elements are updated with the current state of the UID2 identity. For details, see [Workflow States and Transitions](https://unifiedid.com/docs/sdks/client-side-identity#workflow-states-and-transitions) and [Background Token Auto-Refresh](https://unifiedid.com/docs/sdks/client-side-identity#background-token-auto-refresh). | -| 8 | To exit the application, click **Clear UID2**. | This event calls the UID2 SDK [`disconnect()`](https://unifiedid.com/docs/sdks/sdk-ref-javascript#disconnect-void) function, which clears the UID2 session and the first-party cookie or local storage and calls the Secure Signal [`clearAllCache()`](https://developers.google.com/publisher-tag/reference#googletag.secureSignals.SecureSignalProvidersArray_clearAllCache) function to clear all cached signals. This call also makes the UID2 SDK [`isLoginRequired()`](https://unifiedid.com/docs/sdks/sdk-ref-javascript#isloginrequired-boolean) function return `true`, which presents the user with the login form again.
NOTE: The page displays the **Clear UID2** button as long as the user identity is valid and refreshable within the integration test environment. | +| 6 | (Optional) Right-click the main page to inspect the source code. | When the SDK initialization is complete, the SDK invokes the passed callback function (`onIdentityUpdated()` in this example). For details, see [Callback Function](https://unifiedid.com/docs/sdks/client-side-identity#callback-function) (UID2) or [Callback Function](https://euid.eu/docs/sdks/client-side-identity#callback-function) (EUID).
IMPORTANT: The callback updates the page elements with the state of the identity: this is the place where you should define your logic for initiating targeted advertising. | +| 7 | Keep the application main page open or refresh it after awhile and note the identity state, updated counter, and login information values. | In the background, the SDK continuously validates whether the advertising token is up-to-date and refreshes it automatically when needed. If the refresh succeeds, the user opts out, or the refresh token expires, the callback function is invoked and the UI elements are updated with the current state of the identity. For details, see [Workflow States and Transitions](https://unifiedid.com/docs/sdks/client-side-identity#workflow-states-and-transitions) (UID2) or [Workflow States and Transitions](https://euid.eu/docs/sdks/client-side-identity#workflow-states-and-transitions) (EUID), and [Background Token Auto-Refresh](https://unifiedid.com/docs/sdks/client-side-identity#background-token-auto-refresh). | +| 8 | To exit the application, click **Clear UID2** or **Clear EUID**. | This event calls the SDK [`disconnect()`](https://unifiedid.com/docs/sdks/sdk-ref-javascript#disconnect-void) function, which clears the session and the first-party cookie or local storage and calls the Secure Signal [`clearAllCache()`](https://developers.google.com/publisher-tag/reference#googletag.secureSignals.SecureSignalProvidersArray_clearAllCache) function to clear all cached signals. This call also makes the SDK [`isLoginRequired()`](https://unifiedid.com/docs/sdks/sdk-ref-javascript#isloginrequired-boolean) function return `true`, which presents the user with the login form again.
NOTE: The page displays the **Clear** button as long as the user identity is valid and refreshable within the integration test environment. | diff --git a/web-integrations/google-secure-signals/client-side/entrypoint.sh b/web-integrations/google-secure-signals/client-side/entrypoint.sh index 581d5983..786ecdc6 100644 --- a/web-integrations/google-secure-signals/client-side/entrypoint.sh +++ b/web-integrations/google-secure-signals/client-side/entrypoint.sh @@ -1,11 +1,16 @@ #!/bin/sh # Set default values if not provided -export UID_JS_SDK_URL=${UID2_JS_SDK_URL:-"https://cdn.integ.uidapi.com/uid2-sdk-4.0.1.js"} -export UID_JS_SDK_NAME=${UID2_JS_SDK_NAME:-"__uid2"} -export UID_BASE_URL=${UID2_BASE_URL:-"https://operator-integ.uidapi.com"} -export SERVER_PUBLIC_KEY=${UID2_CSTG_SERVER_PUBLIC_KEY:-"UID2-X-I-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEo+jcPlk8GWn3iG0R5Il2cbFQI9hR3TvHxaBUKHl5Vh+ugr+9uLMiXihka8To07ETFGghEifY96Hrpe5RnYko7Q=="} -export SUBSCRIPTION_ID=${UID2_CSTG_SUBSCRIPTION_ID:-"DMr7uHxqLU"} +export UID_JS_SDK_URL=${UID_JS_SDK_URL:-"https://cdn.integ.uidapi.com/uid2-sdk-4.0.1.js"} +export UID_JS_SDK_NAME=${UID_JS_SDK_NAME:-"__uid2"} +# Use CLIENT_BASE_URL for browser calls, fallback to BASE_URL if not set +export UID_BASE_URL=${UID_CLIENT_BASE_URL:-${UID_BASE_URL:-"https://operator-integ.uidapi.com"}} +export SERVER_PUBLIC_KEY=${UID_CSTG_SERVER_PUBLIC_KEY:-"UID2-X-I-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEo+jcPlk8GWn3iG0R5Il2cbFQI9hR3TvHxaBUKHl5Vh+ugr+9uLMiXihka8To07ETFGghEifY96Hrpe5RnYko7Q=="} +export SUBSCRIPTION_ID=${UID_CSTG_SUBSCRIPTION_ID:-"DMr7uHxqLU"} +export UID_SECURE_SIGNALS_SDK_URL=${UID_SECURE_SIGNALS_SDK_URL:-"https://cdn.integ.uidapi.com/uid2SecureSignal.js"} +export UID_SECURE_SIGNALS_STORAGE_KEY=${UID_SECURE_SIGNALS_STORAGE_KEY:-"_GESPSK-uidapi.com"} +export IDENTITY_NAME=${IDENTITY_NAME:-"UID2"} +export DOCS_BASE_URL=${DOCS_BASE_URL:-"https://unifiedid.com/docs"} # Process index.html template with environment variables envsubst < /usr/share/nginx/html/index.html > /usr/share/nginx/html/index.temp.html diff --git a/web-integrations/google-secure-signals/client-side/html/index.html b/web-integrations/google-secure-signals/client-side/html/index.html index 0556cd74..249a3b4c 100644 --- a/web-integrations/google-secure-signals/client-side/html/index.html +++ b/web-integrations/google-secure-signals/client-side/html/index.html @@ -2,7 +2,7 @@ - Client-Side UID2 SDK Integration Example with Google Secure Signals + Client-Side ${IDENTITY_NAME} SDK Integration Example with Google Secure Signals @@ -12,10 +12,10 @@ -

Client-Side UID2 SDK Integration Example with Google Secure Signals

+

Client-Side ${IDENTITY_NAME} SDK Integration Example with Google Secure Signals

This example demonstrates how a content publisher can follow the - Client-Side Integration Guide for JavaScript to implement UID2 integration and generate UID2 tokens. + Client-Side Integration Guide for JavaScript to implement ${IDENTITY_NAME} integration and generate ${IDENTITY_NAME} tokens. Secure Signals is updated when the page is reloaded. Reload the page in order to update Secure Signals in local storage. Note: This is a test-only integration environment—not for production use. @@ -39,15 +39,15 @@

Client-Side UID2 SDK Integration Example with Google Secure Signals


         
         
-          UID2 Advertising Token:
+          ${IDENTITY_NAME} Advertising Token:
           

         
         
-          Is UID2 Login Required?
+          Is ${IDENTITY_NAME} Login Required?
           

         
         
-          UID2 Identity Callback State:
+          ${IDENTITY_NAME} Identity Callback State:
           

         
         
@@ -61,7 +61,7 @@ 

Client-Side UID2 SDK Integration Example with Google Secure Signals

-
+
- + diff --git a/web-integrations/google-secure-signals/client-side/html/scripts/scripts.js b/web-integrations/google-secure-signals/client-side/html/scripts/scripts.js index 767f5b95..ddf98828 100644 --- a/web-integrations/google-secure-signals/client-side/html/scripts/scripts.js +++ b/web-integrations/google-secure-signals/client-side/html/scripts/scripts.js @@ -1,3 +1,7 @@ +const sdkName = '${UID_JS_SDK_NAME}'; +let sdk = window[sdkName]; +sdk = sdk || { callbacks: [] }; + const clientSideIdentityOptions = { subscriptionId: '${SUBSCRIPTION_ID}', serverPublicKey: '${SERVER_PUBLIC_KEY}', @@ -7,15 +11,15 @@ const clientSideIdentityOptions = { let loginAttempted = false; function updateGuiElements(state) { - $('#targeted_advertising_ready').text(__uid2.getAdvertisingToken() ? 'yes' : 'no'); - const token = __uid2.getAdvertisingToken(); + $('#targeted_advertising_ready').text(sdk.getAdvertisingToken() ? 'yes' : 'no'); + const token = sdk.getAdvertisingToken(); $('#advertising_token').text(String(token)); $('#login_required').text( - __uid2.isLoginRequired() || __uid2.isLoginRequired() === undefined ? 'yes' : 'no' + sdk.isLoginRequired() || sdk.isLoginRequired() === undefined ? 'yes' : 'no' ); $('#identity_state').text(String(JSON.stringify(state, null, 2))); - const uid2LoginRequired = __uid2.isLoginRequired(); + const loginRequired = sdk.isLoginRequired(); // Check for opt-out: only if user attempted login, and we got identity null with no token const isOptedOut = loginAttempted && !token && state?.identity === null; @@ -25,7 +29,7 @@ function updateGuiElements(state) { $('#logout_form').hide(); $('#optout_message').show(); $('#optout_banner').show(); - } else if (uid2LoginRequired) { + } else if (loginRequired) { $('#login_form').show(); $('#logout_form').hide(); $('#optout_message').hide(); @@ -37,7 +41,8 @@ function updateGuiElements(state) { $('#optout_banner').hide(); } - const secureSignalsStorage = localStorage['_GESPSK-uidapi.com']; + const secureSignalsStorageKey = '${UID_SECURE_SIGNALS_STORAGE_KEY}'; + const secureSignalsStorage = localStorage[secureSignalsStorageKey]; if (token && !secureSignalsStorage) { //Token is valid but Secure Signals has not been refreshed. Reload the page. location.reload(); @@ -52,8 +57,8 @@ function updateGuiElements(state) { } } -function onUid2IdentityUpdated(eventType, payload) { - console.log('UID2 Callback', payload); +function onIdentityUpdated(eventType, payload) { + console.log('Identity Callback', payload); // allow secure signals time to load setTimeout(() => updateGuiElements(payload), 1000); } @@ -61,7 +66,7 @@ function onUid2IdentityUpdated(eventType, payload) { function onDocumentReady() { $('#logout').click(() => { window.googletag.secureSignalProviders.clearAllCache(); - __uid2.disconnect(); + sdk.disconnect(); loginAttempted = false; // Reset flag }); @@ -71,7 +76,7 @@ function onDocumentReady() { loginAttempted = true; // Mark that user attempted to generate a token try { - await __uid2.setIdentityFromEmail(email, clientSideIdentityOptions); + await sdk.setIdentityFromEmail(email, clientSideIdentityOptions); } catch (e) { console.error('setIdentityFromEmail failed', e); } @@ -79,28 +84,26 @@ function onDocumentReady() { $('#try_another').click(() => { window.googletag.secureSignalProviders.clearAllCache(); - __uid2.disconnect(); + sdk.disconnect(); $('#email').val(''); loginAttempted = false; // Reset flag }); } -window.__uid2 = window.__uid2 || {}; -window.__uid2.callbacks = window.__uid2.callbacks || []; - -window.__uid2.callbacks.push(onUid2IdentityUpdated); -window.__uid2.callbacks.push((eventType, payload) => { +sdk.callbacks.push(onIdentityUpdated); +sdk.callbacks.push((eventType, payload) => { if (eventType === 'SdkLoaded') { - window.__uid2.init({ + sdk.init({ baseUrl: '${UID_BASE_URL}', }); $(document).ready(() => { // Clear any existing identity on page load for clean state - __uid2.disconnect(); + sdk.disconnect(); loginAttempted = false; onDocumentReady(); - // Always show login form on initial page load + + // Set initial UI state - updateGuiElements will adjust based on actual identity state $('#login_form').show(); $('#logout_form').hide(); $('#optout_message').hide(); diff --git a/web-integrations/google-secure-signals/react-client-side/README.md b/web-integrations/google-secure-signals/react-client-side/README.md index 026e4eec..1b2014c4 100644 --- a/web-integrations/google-secure-signals/react-client-side/README.md +++ b/web-integrations/google-secure-signals/react-client-side/README.md @@ -1,6 +1,11 @@ -# React Client-Side UID2 SDK Integration Example with Google Secure Signals +# React Client-Side UID2 or EUID SDK Integration Example with Google Secure Signals -This example demonstrates how a content publisher who is working with [Google Interactive Media Ads(IMA) SDKs](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side) can use [Google Secure Signal](https://support.google.com/admanager/answer/10488752) and the [UID2 SDK for JavaScript](https://unifiedid.com/docs/sdks/sdk-ref-javascript) to share UID2 directly with bidders, in an implementation that uses this JS SDK on the client side in a React App. +This example demonstrates how a content publisher who is working with [Google Interactive Media Ads(IMA) SDKs](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side) can use [Google Secure Signal](https://support.google.com/admanager/answer/10488752) and either the UID2 or EUID SDK for JavaScript to share tokens directly with bidders, in a client-side React implementation that uses this SDK. + +- For UID2: [UID2 SDK for JavaScript](https://unifiedid.com/docs/sdks/sdk-ref-javascript), [Google Ad Manager Secure Signals Integration Guide](https://unifiedid.com/docs/guides/integration-google-ss) +- For EUID: [EUID SDK for JavaScript](https://euid.eu/docs/sdks/sdk-ref-javascript), [EUID Google Ad Manager Secure Signals Integration Guide](https://euid.eu/docs/guides/integration-google-ss) + +This example can be configured for either UID2 or EUID — the behavior is determined by your environment variable configuration. You cannot use both simultaneously. ## Build and Run the Example Application @@ -34,28 +39,56 @@ The example app will be up and running at `http://localhost:3044` Alternatively, you can build and run the example using Docker (note: this may take several minutes): +#### Using Docker Compose (Recommended) + +From the repository root directory: + +```bash +# Start the service +docker compose up google-secure-signals-react-client-side ``` -docker build . -t uid2-secure-signals-react -docker run -it --rm -p 3044:3044 uid2-secure-signals-react + +The application will be available at http://localhost:3044 + +To view logs or stop the service: + +```bash +# View logs (in another terminal) +docker compose logs google-secure-signals-react-client-side + +# Stop the service +docker compose stop google-secure-signals-react-client-side ``` -The example app will be up and running at localhost:3044 +#### Using Docker Build + +```bash +# Build the image +docker build -f web-integrations/google-secure-signals/react-client-side/Dockerfile -t google-secure-signals-react-client-side . + +# Run the container +docker run -it --rm -p 3044:3044 --env-file .env google-secure-signals-react-client-side +``` If needed, to close the application, terminate the docker container or use the `Ctrl+C` keyboard shortcut. ## Test the Example Application -The example application illustrates the steps documented in the [Google Ad Manager Secure Signals Integration Guide](https://unifiedid.com/docs/guides/integration-google-ss). For an overview of the high-level workflow for establishing UID2 identity, API reference, and explanation of the UID2 cookie format, see [UID2 SDK for JavaScript](https://unifiedid.com/docs/sdks/client-side-identity). +The example application illustrates the steps documented in the Google Ad Manager Secure Signals Integration guides: +- UID2: [Google Ad Manager Secure Signals Integration Guide](https://unifiedid.com/docs/guides/integration-google-ss), [UID2 SDK for JavaScript](https://unifiedid.com/docs/sdks/client-side-identity) +- EUID: [EUID Google Ad Manager Secure Signals Integration Guide](https://euid.eu/docs/guides/integration-google-ss), [EUID SDK for JavaScript](https://euid.eu/docs/sdks/client-side-identity) + +**Note:** For API endpoint documentation, see the UID2 or EUID docs based on your configuration. The following table outlines and annotates the steps you may take to test and explore the example application. | Step | Description | Comments | | :--: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 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.
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. | +| 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/EUID login process.
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** or **Generate EUID**. Note: The button label depends on your environment configuration; 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 JavaScript SDK. | +| 3 | A confirmation message appears with the established identity information. | The displayed identity information is the `body` property of the JSON response payload from the `client-generate` response. Next, the identity information is passed to the SDK `setIdentity()` function. If the identity is valid, the SDK stores it either in local storage or a first-party cookie 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 **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 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() function again, but this time without passing an explicit identity. Instead, the identity is loaded from the first-party cookie or local storage. | | 5 | Click **Play**. | This triggers AdsManager to insert the ad returned from the ad request, for display. The ad tag used in this example contains a 10-second pre-roll ad. | -| 6 | (Optional) Right-click the main page to inspect the source code. | When the UID2 SDK initialization is complete, the SDK invokes the passed [callback function](https://unifiedid.com/docs/sdks/client-side-identity#callback-function) (`onUid2IdentityUpdated()` in this example).
IMPORTANT: The callback updates the page elements with the state of UID2 identity: this is the place where you should define your logic for initiating targeted advertising. | -| 7 | Keep the application main page open or refresh it after awhile and note the UID2 identity state, updated counter, and login information values. | In the background, the UID2 SDK continuously validates whether the advertising token is up-to-date and refreshes it automatically when needed. If the refresh succeeds, the user opts out, or the refresh token expires, the callback function is invoked and the UI elements are updated with the current state of the UID2 identity. For details, see [Workflow States and Transitions](https://unifiedid.com/docs/sdks/client-side-identity#workflow-states-and-transitions) and [Background Token Auto-Refresh](https://unifiedid.com/docs/sdks/client-side-identity#background-token-auto-refresh). | -| 8 | To exit the application, click **Clear UID2**. | This event calls the UID2 SDK [`disconnect()`](https://unifiedid.com/docs/sdks/sdk-ref-javascript#disconnect-void) function, which clears the UID2 session and the first-party cookie or local storage and calls the Secure Signal [`clearAllCache()`](https://developers.google.com/publisher-tag/reference#googletag.secureSignals.SecureSignalProvidersArray_clearAllCache) function to clear all cached signals. This call also makes the UID2 SDK [`isLoginRequired()`](https://unifiedid.com/docs/sdks/sdk-ref-javascript#isloginrequired-boolean) function return `true`, which presents the user with the login form again.
NOTE: The page displays the **Clear UID2** button as long as the user identity is valid and refreshable within the integration test environment. | +| 6 | (Optional) Right-click the main page to inspect the source code. | When the SDK initialization is complete, the SDK invokes the passed callback function.
IMPORTANT: The callback updates the page elements with the state of the identity: this is the place where you should define your logic for initiating targeted advertising. | +| 7 | Keep the application main page open or refresh it after awhile and note the identity state, updated counter, and login information values. | In the background, the SDK continuously validates whether the advertising token is up-to-date and refreshes it automatically when needed. If the refresh succeeds, the user opts out, or the refresh token expires, the callback function is invoked and the UI elements are updated with the current state of the identity. | +| 8 | To exit the application, click **Clear UID2** or **Clear EUID**. | This event calls the SDK `disconnect()` function, which clears the session and the first-party cookie or local storage and calls the Secure Signal [`clearAllCache()`](https://developers.google.com/publisher-tag/reference#googletag.secureSignals.SecureSignalProvidersArray_clearAllCache) function to clear all cached signals. This call also makes the SDK `isLoginRequired()` function return `true`, which presents the user with the login form again.
NOTE: The page displays the **Clear** button as long as the user identity is valid and refreshable within the integration test environment. | diff --git a/web-integrations/google-secure-signals/react-client-side/server.js b/web-integrations/google-secure-signals/react-client-side/server.js index 9de006b4..30181fd9 100644 --- a/web-integrations/google-secure-signals/react-client-side/server.js +++ b/web-integrations/google-secure-signals/react-client-side/server.js @@ -16,11 +16,7 @@ app.set('view engine', 'html'); app.use(express.static('public', { type: 'application/javascript' })); app.get('/', (req, res) => { - res.render('index', { - uid2SubscriptionId: process.env.UID2_CSTG_SUBSCRIPTION_ID, - uid2ServerPublicKey: process.env.UID2_CSTG_SERVER_PUBLIC_KEY, - uid2BaseUrl: process.env.UID2_BASE_URL, - }); + res.render('index', {}); }); app.listen(port, () => { diff --git a/web-integrations/google-secure-signals/react-client-side/src/SecureSignalsApp.tsx b/web-integrations/google-secure-signals/react-client-side/src/SecureSignalsApp.tsx index f59caa52..f7b962fe 100644 --- a/web-integrations/google-secure-signals/react-client-side/src/SecureSignalsApp.tsx +++ b/web-integrations/google-secure-signals/react-client-side/src/SecureSignalsApp.tsx @@ -3,7 +3,7 @@ import './styles/app.css'; import './styles/ads.css'; declare global { interface Window { - __uid2: any; + [key: string]: any; getAdvertisingToken: any; google: any; googletag: any; @@ -13,9 +13,17 @@ declare global { // Declare global variables declare const google: any; +// Set default to uid2 configuration +const UID_JS_SDK_NAME = process.env.REACT_APP_UID_JS_SDK_NAME || '__uid2'; +const UID_BASE_URL = process.env.REACT_APP_UID_CLIENT_BASE_URL || 'https://operator-integ.uidapi.com'; +const SECURE_SIGNALS_SDK_URL = process.env.REACT_APP_UID_SECURE_SIGNALS_SDK_URL || 'https://cdn.integ.uidapi.com/uid2SecureSignal.js'; +const SECURE_SIGNALS_STORAGE_KEY = process.env.REACT_APP_UID_SECURE_SIGNALS_STORAGE_KEY || '_GESPSK-uidapi.com'; +const IDENTITY_NAME = process.env.REACT_APP_IDENTITY_NAME; +const DOCS_BASE_URL = process.env.REACT_APP_DOCS_BASE_URL; + const clientSideIdentityOptions = { - subscriptionId: process.env.REACT_APP_UID2_CSTG_SUBSCRIPTION_ID || 'toPh8vgJgt', - serverPublicKey: process.env.REACT_APP_UID2_CSTG_SERVER_PUBLIC_KEY || + subscriptionId: process.env.REACT_APP_UID_CSTG_SUBSCRIPTION_ID || 'toPh8vgJgt', + serverPublicKey: process.env.REACT_APP_UID_CSTG_SERVER_PUBLIC_KEY || 'UID2-X-I-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKAbPfOz7u25g1fL6riU7p2eeqhjmpALPeYoyjvZmZ1xM2NM8UeOmDZmCIBnKyRZ97pz5bMCjrs38WM22O7LJuw==', }; @@ -29,7 +37,6 @@ const SecureSignalsApp = () => { const [identityState, setIdentityState] = useState(''); const [email, setEmail] = useState(''); const [identity, setIdentity] = useState(null); - const [isUid2Enabled, setIsUid2Enabled] = useState(true); const [adsLoaded, setAdsLoaded] = useState(false); const [isOptedOut, setIsOptedOut] = useState(false); @@ -42,21 +49,25 @@ const SecureSignalsApp = () => { // Track whether user has attempted to generate a token const loginAttemptedRef = useRef(false); + // Helper function to get SDK instance + const getSDK = () => window[UID_JS_SDK_NAME]; + const updateElements = useCallback((status) => { - const token = window.__uid2.getAdvertisingToken(); + const sdk = getSDK(); + const token = sdk.getAdvertisingToken(); // Check for opt-out: only if user attempted login, and we got identity null with no token const optedOut = loginAttemptedRef.current && !token && status?.identity === null; setIsOptedOut(optedOut); - if (window.__uid2.getAdvertisingToken()) { + if (sdk.getAdvertisingToken()) { setTargetedAdvertisingReady(true); } else { setTargetedAdvertisingReady(false); } - setAdvertisingToken(String(window.__uid2.getAdvertisingToken())); + setAdvertisingToken(String(sdk.getAdvertisingToken())); - if (window.__uid2.isLoginRequired() === true) { + if (sdk.isLoginRequired() === true) { setLoginRequired(true); setIsLoggedIn(false); } else { @@ -70,16 +81,9 @@ const SecureSignalsApp = () => { setTimeout(updateSecureSignals, 500); }, []); - const isEnabled = (product: string): boolean => { - if (product === 'uid2') { - return isUid2Enabled; - } - return false; - }; - - const onUid2IdentityUpdated = useCallback( + const onIdentityUpdated = useCallback( (eventType, payload) => { - console.log('UID2 Callback', payload); + console.log(`${IDENTITY_NAME} Callback`, payload); updateElements(payload); }, [updateElements] @@ -173,23 +177,24 @@ const SecureSignalsApp = () => { ); useEffect(() => { - // Add callbacks for UID2 JS SDK - window.__uid2.callbacks.push(onUid2IdentityUpdated); - window.__uid2.callbacks.push((eventType, payload) => { - let __uid2 = window.__uid2; + // Add callbacks for UID2/EUID JS SDK + let sdk = getSDK(); + sdk = sdk || { callbacks: [] }; + sdk.callbacks.push(onIdentityUpdated); + sdk.callbacks.push((eventType, payload) => { if (eventType === 'SdkLoaded') { - __uid2.init({ - baseUrl: process.env.REACT_APP_UID2_BASE_URL ||'https://operator-integ.uidapi.com', + sdk.init({ + baseUrl: UID_BASE_URL, }); } if (eventType === 'InitCompleted') { - if (__uid2.isLoginRequired()) { - __uid2.setIdentity(identity); + if (sdk.isLoginRequired()) { + sdk.setIdentity(identity); setIdentity(identity); } } }); - }, [identity, onUid2IdentityUpdated]); + }, [identity, onIdentityUpdated]); useEffect(() => { // initialize ads manager @@ -243,7 +248,7 @@ const SecureSignalsApp = () => { const loadSecureSignals = () => { const script2 = document.createElement('script'); - script2.src = 'https://cdn.integ.uidapi.com/uid2SecureSignal.js'; + script2.src = SECURE_SIGNALS_SDK_URL; script2.async = true; script2.onload = () => { console.log('secure signals script loaded'); @@ -256,10 +261,9 @@ const SecureSignalsApp = () => { loginAttemptedRef.current = true; // Mark that user attempted to generate a token try { - if (isEnabled('uid2')) { - await window.__uid2.setIdentityFromEmail(email, clientSideIdentityOptions); - loadSecureSignals(); - } + const sdk = getSDK(); + await sdk.setIdentityFromEmail(email, clientSideIdentityOptions); + loadSecureSignals(); } catch (e) { console.error('setIdentityFromEmail failed', e); } @@ -267,18 +271,16 @@ const SecureSignalsApp = () => { const handleLogout = () => { window.googletag.secureSignalProviders.clearAllCache(); - if (isEnabled('uid2')) { - window.__uid2.disconnect(); - } + const sdk = getSDK(); + sdk.disconnect(); loginAttemptedRef.current = false; // Reset flag setIsOptedOut(false); }; const handleTryAnother = () => { window.googletag.secureSignalProviders.clearAllCache(); - if (isEnabled('uid2')) { - window.__uid2.disconnect(); - } + const sdk = getSDK(); + sdk.disconnect(); setEmail(''); loginAttemptedRef.current = false; // Reset flag setIsOptedOut(false); @@ -294,7 +296,7 @@ const SecureSignalsApp = () => { }; const updateSecureSignals = () => { - const secureSignalsStorage = localStorage['_GESPSK-uidapi.com']; + const secureSignalsStorage = localStorage[SECURE_SIGNALS_STORAGE_KEY]; const secureSignalsStorageJson = secureSignalsStorage && JSON.parse(secureSignalsStorage); if (secureSignalsStorageJson && secureSignalsStorageJson[1]) { setSecureSignalsLoaded(true); @@ -305,21 +307,17 @@ const SecureSignalsApp = () => { } }; - const handleCheckboxChange = (e: any) => { - setIsUid2Enabled(e.target.checked); - }; - return (

- React Client-Side UID2 SDK Integration Example with Google Secure Signals + React Client-Side {IDENTITY_NAME} SDK Integration Example with Google Secure Signals

This example demonstrates how a content publisher can follow the{' '} - + Client-Side Integration Guide for JavaScript {' '} - to implement UID2 integration and generate UID2 tokens. Secure Signals is updated when the + to implement {IDENTITY_NAME} integration and generate {IDENTITY_NAME} tokens. Secure Signals is updated when the page is reloaded. Reload the page in order to update Secure Signals in local storage.

@@ -340,15 +338,7 @@ const SecureSignalsApp = () => { - + @@ -359,19 +349,19 @@ const SecureSignalsApp = () => { - + - + - + @@ -395,7 +385,7 @@ const SecureSignalsApp = () => { {isOptedOut ? ( <>
-

The email address you entered has opted out of UID2.

+

The email address you entered has opted out of {IDENTITY_NAME}.

@@ -426,7 +416,7 @@ const SecureSignalsApp = () => {
diff --git a/web-integrations/google-secure-signals/server-side/README.md b/web-integrations/google-secure-signals/server-side/README.md index 5d6bf86b..9625113f 100644 --- a/web-integrations/google-secure-signals/server-side/README.md +++ b/web-integrations/google-secure-signals/server-side/README.md @@ -1,35 +1,78 @@ -# Server-Side UID2 Integration Example with Google Secure Signals +# Server-Side UID2 or EUID Integration Example with Google Secure Signals -This example demonstrates how a content publisher who is working with [Google Interactive Media Ads(IMA) SDKs](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side) can use [Google Secure Signal](https://support.google.com/admanager/answer/10488752) to share UID2 directly with bidders, in a server-side implementation of UID2. +This example demonstrates how a content publisher who is working with [Google Interactive Media Ads(IMA) SDKs](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side) can use [Google Secure Signal](https://support.google.com/admanager/answer/10488752) with either UID2 or EUID to share tokens directly with bidders, in a server-side implementation without using an SDK. -For an example application using the [UID2 SDK for JavaScript](https://unifiedid.com/docs/sdks/sdk-ref-javascript), see [Client-Server UID2 SDK Integration Example with Google Secure Signals](../client-server/README.md) or [Client-Side UID2 SDK Integration Example with Google Secure Signals](../client-side/README.md). +- For UID2: [Google Ad Manager Secure Signals Integration Guide](https://unifiedid.com/docs/guides/integration-google-ss#server-side-integration) +- For EUID: [EUID Google Ad Manager Secure Signals Integration Guide](https://euid.eu/docs/guides/integration-google-ss#server-side-integration) + +This example can be configured for either UID2 or EUID — the behavior is determined by your environment variable configuration. You cannot use both simultaneously. + +For an example application using the SDK, see [Client-Server UID2 or EUID SDK Integration Example with Google Secure Signals](../client-server/README.md) or [Client-Side UID2 or EUID SDK Integration Example with Google Secure Signals](../client-side/README.md). > NOTE: Although the server side of the example application is implemented in JavaScript using node.js, it is not a requirement. You can use any technology of your choice and refer to the example application for an illustration of the functionality that needs to be implemented. ## Build and Run the Example Application -The easiest way to try the example is to use the following Docker Build command: +### Environment Configuration + +Copy the appropriate sample environment file: + +```bash +# For UID2 +cp .env.sample.uid2 .env + +# For EUID +cp .env.sample.euid .env +``` + +Then update the `.env` file with your credentials. + +### Running with Docker + +#### Using Docker Compose (Recommended) + +From the repository root directory: +```bash +# Start the service +docker compose up google-secure-signals-server-side ``` -docker build . -t uid2-secure-signals-server -docker run -it --rm -p 3000:3000 \ - -e UID2_BASE_URL="https://operator-integ.uidapi.com" \ - -e UID2_API_KEY="" \ - -e UID2_CLIENT_SECRET="" \ - -e SESSION_KEY="" \ - -e AD_TAG_URL="" \ - uid2-secure-signals-server + +The application will be available at http://localhost:3043 + +To view logs or stop the service: + +```bash +# View logs (in another terminal) +docker compose logs google-secure-signals-server-side + +# Stop the service +docker compose stop google-secure-signals-server-side +``` + +#### Using Docker Build + +```bash +# Build the image +docker build -f web-integrations/google-secure-signals/server-side/Dockerfile -t google-secure-signals-server-side . + +# Run the container +docker run -it --rm -p 3043:3043 --env-file .env google-secure-signals-server-side ``` -The following table lists the environment variables that you must specify to start the application. +### Environment Variables -| Parameter | Data Type | Description | -| :------------------- | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `UID2_BASE_URL` | string | The base URL of the UID2 service. For example:
Testing environment: `https://integ.uidapi.com`
Production environment: `https://prod.uidapi.com` | -| `UID2_API_KEY` | string | Your UID2 authentication key for the UID2 service specified in `UID2_BASE_URL`. | -| `UID2_CLIENT_SECRET` | string | Your UID2 client secret for the UID2 service specified in `UID2_BASE_URL`. | -| `SESSION_KEY` | string | The key to the encryption session data stored in the application's session cookie. | -| `AD_TAG_URL` | string | The ad tag URL to test ad requests. | +| Variable | Description | Example Values | +|:---------|:------------|:---------------| +| `UID_SERVER_BASE_URL` | The base URL of the UID2/EUID service for server-side API calls | UID2: `https://operator-integ.uidapi.com`
EUID: `https://integ.euid.eu` | +| `UID_API_KEY` | Your UID2/EUID authentication key for the UID2/EUID service specified in UID_SERVER_BASE_URL. | Your assigned API key | +| `UID_CLIENT_SECRET` | Your UID2/EUID client secret for the UID2/EUID service specified in UID_SERVER_BASE_URL. | Your assigned client secret | +| `SESSION_KEY` | The key to the encryption session data stored in the application's session cookie | Any secure random string | +| `UID_SECURE_SIGNALS_SDK_URL` | URL to the Secure Signals SDK | UID2: `https://cdn.integ.uidapi.com/uid2SecureSignal.js`
EUID: `https://cdn.integ.euid.eu/euidSecureSignal.js` | +| `IDENTITY_NAME` | Identity name for UI display | UID2: `UID2`
EUID: `EUID` | +| `DOCS_BASE_URL` | Documentation base URL | UID2: `https://unifiedid.com/docs`
EUID: `https://euid.eu/docs` | + +**Note:** The example uses a Google IMA sample ad tag URL in `public/ads.js`. To test with your own ad tag, edit line 56 in `public/ads.js` to use your ad tag URL. Output similar to the following indicates that the example application is up and running. @@ -37,7 +80,7 @@ Output similar to the following indicates that the example application is up and > uid2-publisher@1.0.0 start /usr/src/app > node server.js -Example app listening at http://localhost:3000 +Example app listening at http://localhost:3043 ``` If needed, to close the application, terminate the Docker container or use the `Ctrl+C` keyboard shortcut. @@ -54,14 +97,16 @@ Access to these pages is possible only after the user completes the login proces Submitting the login form simulates logging in to a publisher's application in the real world. Normally, the login would require checking the user's secure credentials (for example, a password). In this example, for demonstration purposes, this -step is omitted, and the login process focuses on integration with the UID2 services instead. +step is omitted, and the login process focuses on integration with the UID2/EUID services instead. + +**Note:** For API endpoint documentation, see the UID2 or EUID docs based on your configuration. The following table outlines and annotates the steps you can take to test and explore the example application. | Step | Description | Comments | | :--: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| 1 | In your browser, navigate to the application main page at `http://localhost:3000`. | The displayed main (index) page of the example application provides a [login form](views/login.html) for the user to complete the UID2 login process.
IMPORTANT: A real-life application must also display a form for the user to consent to targeted advertising. | -| 2 | Enter the 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, and then calls the `/login` endpoint ([server.js](server.js)). The login initiated on the server side then calls the [POST /token/generate](https://unifiedid.com/docs/endpoints/post-token-generate) endpoint and processes the received response. | -| | The main page updates to display the established UID2 identity information and a video player. | 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 successful `POST /token/generate` response. If the response is successful, the returned identity is saved to a session cookie (a real-world application would use a different way to store session data) and the protected index page is rendered. While the main page is loading, [Google Publisher Tag (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. The [Interactive Media Ads (IMA) SDK](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side) then makes an ad request, and transmits the encoded signal in the request. | -| 4 | Click **Play**. | This triggers AdsManager to insert the ad returned from the ad request, for display. The ad tag used in this example contains a 10-second pre-roll.ad. | -| 5 | To exit the application, click **Clear UID2**. | This event calls the Secure Signal [`clearAllCache()`](https://developers.google.com/publisher-tag/reference#googletag.secureSignals.SecureSignalProvidersArray_clearAllCache) function, to clear all cached signals, and then calls the `/logout` endpoint on the server ([server.js](server.js)), which clears the UID2 session and the first-party cookie and presents the user with the login form again.
NOTE: The page displays the **Clear UID2** button as long as the user identity is valid and refreshable within the integration test environment. | +| 1 | In your browser, navigate to the application main page at `http://localhost:3043`. | The displayed main (index) page of the example application provides a [login form](views/login.html) for the user to complete the UID2/EUID login process.
IMPORTANT: A real-life application must also display a form for the user to consent to targeted advertising. | +| 2 | Enter the email address that you want to use for testing and click **Generate UID2** or **Generate EUID**. Note: The button label depends on your environment configuration; 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, and then calls the `/login` endpoint ([server.js](server.js)). The login initiated on the server side then calls the POST /token/generate endpoint and processes the received response. | +| | The main page updates to display the established identity information and a video player. | The displayed identity information is the `body` property of the JSON response payload from the successful POST /token/generate response. If the response is successful, the returned identity is saved to a session cookie (a real-world application would use a different way to store session data) and the protected index page is rendered. While the main page is loading, [Google Publisher Tag (GPT)](https://developers.google.com/publisher-tag/reference#googletag) auto-loads the Secure Signal script which pushes the advertising token to GPT local storage. The [Interactive Media Ads (IMA) SDK](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side) then makes an ad request, and transmits the encoded signal in the request. | +| 4 | Click **Play**. | This triggers AdsManager to insert the ad returned from the ad request, for display. The ad tag used in this example contains a 10-second pre-roll ad. | +| 5 | To exit the application, click **Clear UID2** or **Clear EUID**. | This event calls the Secure Signal [`clearAllCache()`](https://developers.google.com/publisher-tag/reference#googletag.secureSignals.SecureSignalProvidersArray_clearAllCache) function, to clear all cached signals, and then calls the `/logout` endpoint on the server ([server.js](server.js)), which clears the session and the first-party cookie and presents the user with the login form again.
NOTE: The page displays the **Clear** button as long as the user identity is valid and refreshable within the integration test environment. | diff --git a/web-integrations/google-secure-signals/server-side/public/ads.js b/web-integrations/google-secure-signals/server-side/public/ads.js index b575cf95..ce1d698d 100644 --- a/web-integrations/google-secure-signals/server-side/public/ads.js +++ b/web-integrations/google-secure-signals/server-side/public/ads.js @@ -52,7 +52,8 @@ function setUpIMA() { // Request video ads. const adsRequest = new google.ima.AdsRequest(); - adsRequest.adTagUrl = '${AD_TAG_URL}'; + // Using Google IMA sample ad tag - replace with your own ad tag URL for production + adsRequest.adTagUrl = 'https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_ad_samples&sz=640x480&cust_params=sample_ct%3Dlinear&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator='; // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. diff --git a/web-integrations/google-secure-signals/server-side/server.js b/web-integrations/google-secure-signals/server-side/server.js index 3894407d..7106fff2 100644 --- a/web-integrations/google-secure-signals/server-side/server.js +++ b/web-integrations/google-secure-signals/server-side/server.js @@ -10,9 +10,16 @@ const crypto = require('crypto'); const app = express(); const port = process.env.PORT || 3043; -const uid2BaseUrl = process.env.UID2_BASE_URL; -const uid2ApiKey = process.env.UID2_API_KEY; -const uid2ClientSecret = process.env.UID2_CLIENT_SECRET; +const uidBaseUrl = process.env.UID_SERVER_BASE_URL; +const uidApiKey = process.env.UID_API_KEY; +const uidClientSecret = process.env.UID_CLIENT_SECRET; + +// Secure Signals configuration +const secureSignalsSdkUrl = process.env.UID_SECURE_SIGNALS_SDK_URL || 'https://cdn.integ.uidapi.com/uid2SecureSignal.js'; + +// UI/Display configuration +const identityName = process.env.IDENTITY_NAME; +const docsBaseUrl = process.env.DOCS_BASE_URL; const ivLength = 12; const nonceLength = 8; @@ -84,7 +91,7 @@ function createEnvelope(payload) { const payloadEncoded = new TextEncoder().encode(payload); const body = Buffer.concat([Buffer.from(new Uint8Array(bufferMillisec)), nonce, payloadEncoded]); - const { ciphertext, iv } = encryptRequest(body, uid2ClientSecret); + const { ciphertext, iv } = encryptRequest(body, uidClientSecret); const envelopeVersion = Buffer.alloc(1, 1); const envelope = bufferToBase64( @@ -120,12 +127,12 @@ function isRefreshableIdentity(identity) { async function refreshIdentity(identity) { const headers = { - headers: { Authorization: 'Bearer ' + uid2ApiKey }, + headers: { Authorization: 'Bearer ' + uidApiKey }, }; try { const encryptedResponse = await axios.post( - uid2BaseUrl + '/v2/token/refresh', + uidBaseUrl + '/v2/token/refresh', identity.refresh_token, headers ); //if HTTP response code is not 200, this throws and is caught in the catch handler below. @@ -178,7 +185,12 @@ async function protect(req, res, next) { } app.get('/', protect, (req, res) => { - res.render('index', { identity: req.session.identity }); + res.render('index', { + identity: req.session.identity, + secureSignalsSdkUrl, + identityName, + docsBaseUrl + }); }); app.get('/getFreshToken', protect, async (req, res) => { @@ -197,27 +209,41 @@ app.get('/login', async (req, res) => { res.redirect('/'); } else { req.session = null; - res.render('login'); + res.render('login', { + secureSignalsSdkUrl, + identityName, + docsBaseUrl + }); } }); function _GenerateTokenV1(req, res) { axios - .get(uid2BaseUrl + '/v1/token/generate?email=' + encodeURIComponent(req.body.email), { - headers: { Authorization: 'Bearer ' + uid2ApiKey }, + .get(uidBaseUrl + '/v1/token/generate?email=' + encodeURIComponent(req.body.email), { + headers: { Authorization: 'Bearer ' + uidApiKey }, }) .then((response) => { if (response.data.status === 'optout') { - res.render('optout'); + res.render('optout', { + secureSignalsSdkUrl, + identityName, + docsBaseUrl + }); } else if (response.data.status !== 'success') { res.render('error', { error: 'Got unexpected token generate status: ' + response.data.status, - response: response, + response, + secureSignalsSdkUrl, + identityName, + docsBaseUrl }); } else if (typeof response.data.body !== 'object') { res.render('error', { error: 'Unexpected token generate response format: ' + response.data, - response: response, + response, + secureSignalsSdkUrl, + identityName, + docsBaseUrl }); } else { req.session.identity = response.data.body; @@ -225,7 +251,13 @@ function _GenerateTokenV1(req, res) { } }) .catch((error) => { - res.render('error', { error: error, response: error.response }); + res.render('error', { + error, + response: error.response, + secureSignalsSdkUrl, + identityName, + docsBaseUrl + }); }); } @@ -237,35 +269,51 @@ app.post('/login', async (req, res) => { const { envelope, nonce } = createEnvelope(jsonEmail); const headers = { - headers: { Authorization: 'Bearer ' + uid2ApiKey }, + headers: { Authorization: 'Bearer ' + uidApiKey }, }; try { const encryptedResponse = await axios.post( - uid2BaseUrl + '/v2/token/generate', + uidBaseUrl + '/v2/token/generate', envelope, headers ); //if HTTP response code is not 200, this throws and is caught in the catch handler below. - const response = decrypt(encryptedResponse.data, uid2ClientSecret, false, nonce); + const response = decrypt(encryptedResponse.data, uidClientSecret, false, nonce); if (response.status === 'optout') { - res.render('optout'); + res.render('optout', { + secureSignalsSdkUrl, + identityName, + docsBaseUrl + }); } else if (response.status !== 'success') { res.render('error', { error: 'Got unexpected token generate status in decrypted response: ' + response.status, - response: response, + response, + secureSignalsSdkUrl, + identityName, + docsBaseUrl }); } else if (typeof response.body !== 'object') { res.render('error', { error: 'Unexpected token generate response format in decrypted response: ' + response, - response: response, + response, + secureSignalsSdkUrl, + identityName, + docsBaseUrl }); } else { req.session.identity = response.body; res.redirect('/'); } } catch (error) { - res.render('error', { error: error, response: error.response }); + res.render('error', { + error, + response: error.response, + secureSignalsSdkUrl, + identityName, + docsBaseUrl + }); } }); diff --git a/web-integrations/google-secure-signals/server-side/views/error.html b/web-integrations/google-secure-signals/server-side/views/error.html index 25ddea9d..f8b33c1d 100644 --- a/web-integrations/google-secure-signals/server-side/views/error.html +++ b/web-integrations/google-secure-signals/server-side/views/error.html @@ -1,7 +1,7 @@ <%- include('header.html'); -%>

Something went wrong:

<%= error %>
-

Response from the UID2 operator:

+

Response from the <%- identityName %> operator:

<%= response ? JSON.stringify(response.data) : '' %>

HTTP error:

<%= response ? (response.status + ' ' + response.statusText) : '' %>
diff --git a/web-integrations/google-secure-signals/server-side/views/header.html b/web-integrations/google-secure-signals/server-side/views/header.html index 1dc6273d..e6b4b7c2 100644 --- a/web-integrations/google-secure-signals/server-side/views/header.html +++ b/web-integrations/google-secure-signals/server-side/views/header.html @@ -2,42 +2,43 @@ - Server-Side UID2 Integration Example with Google Secure Signals + Server-Side <%- identityName %> Integration Example with Google Secure Signals - + -

Server-Side UID2 Integration Example with Google Secure Signals

+

Server-Side <%- identityName %> Integration Example with Google Secure Signals

- This example demonstrates how a content publisher can use the UID2 services to implement the - server-side UID2 integration workflow with Secure Signals. [ services to implement the + server-side <%- identityName %> integration workflow with Secure Signals. [Source Code]

This assumes that the publisher has implemented - UID2 Server-Side integration - on the backend and is able to pass the resulting UID2 identity response to the front end. + <%- identityName %> Server-Side integration + on the backend and is able to pass the resulting <%- identityName %> identity response to the front end.

diff --git a/web-integrations/google-secure-signals/server-side/views/identity.html b/web-integrations/google-secure-signals/server-side/views/identity.html index 30d6b92a..dfeca933 100644 --- a/web-integrations/google-secure-signals/server-side/views/identity.html +++ b/web-integrations/google-secure-signals/server-side/views/identity.html @@ -5,6 +5,6 @@ onsubmit="return window.googletag.secureSignalProviders.clearAllCache()" >
- + diff --git a/web-integrations/google-secure-signals/server-side/views/login.html b/web-integrations/google-secure-signals/server-side/views/login.html index 9ed293ae..49d729e0 100644 --- a/web-integrations/google-secure-signals/server-side/views/login.html +++ b/web-integrations/google-secure-signals/server-side/views/login.html @@ -9,6 +9,6 @@ style="border-style: none" /> -
+
<%- include('footer.html'); -%> diff --git a/web-integrations/google-secure-signals/server-side/views/optout.html b/web-integrations/google-secure-signals/server-side/views/optout.html index 051d9a20..a635c6c0 100644 --- a/web-integrations/google-secure-signals/server-side/views/optout.html +++ b/web-integrations/google-secure-signals/server-side/views/optout.html @@ -3,7 +3,7 @@

This email has opted out

- The email address you entered has opted out of UID2. No UID2 token can be generated for this + The email address you entered has opted out of <%- identityName %>. No <%- identityName %> token can be generated for this email.

diff --git a/web-integrations/javascript-sdk/client-server/README.md b/web-integrations/javascript-sdk/client-server/README.md index 00dc535e..248d0f7f 100644 --- a/web-integrations/javascript-sdk/client-server/README.md +++ b/web-integrations/javascript-sdk/client-server/README.md @@ -1,63 +1,86 @@ -# Client-Server UID2 Integration Example using JavaScript SDK +# Client-Server UID2 or EUID Integration Example using JavaScript SDK -[This example](https://example-jssdk-integ.uidapi.com/) demonstrates how a content publisher can use the [UID2 services](https://unifiedid.com/docs/intro) and the [UID2 SDK for JavaScript](https://unifiedid.com/docs/sdks/sdk-ref-javascript) to implement the [client-server UID2 integration workflow](https://unifiedid.com/docs/guides/integration-javascript-client-server). +[This example](https://example-jssdk-integ.uidapi.com/) demonstrates how a content publisher can use either the UID2 or EUID services and the corresponding SDK for JavaScript to implement the client-server integration workflow. -For an example application without using the UID2 SDK, see [Server-Side UID2 Integration Example](../../server-side/README.md). +- For UID2: [UID2 services](https://unifiedid.com/docs/intro), [UID2 SDK for JavaScript](https://unifiedid.com/docs/sdks/sdk-ref-javascript), [client-server UID2 integration workflow](https://unifiedid.com/docs/guides/integration-javascript-client-server) +- For EUID: [EUID services](https://euid.eu/docs/intro), [EUID SDK for JavaScript](https://euid.eu/docs/sdks/sdk-ref-javascript), [client-server EUID integration workflow](https://euid.eu/docs/guides/integration-javascript-client-server) + +This example can be configured for either UID2 or EUID — the behavior is determined by your environment variable configuration. You cannot use both simultaneously. + +For an example application without using the SDK, see [Server-Side UID2 or EUID Integration Example](../../server-side/README.md). > NOTE: While the server side of the example application is implemented in JavaScript using node.js, it is not > a requirement. You can use any technology of your choice and refer to the example application for illustration of the functionality that needs to be implemented. ## Build and Run the Example Application -The easiest way to try the example is to use the following docker build command: +### Using Docker Compose (Recommended) +From the repository root directory: + +```bash +# Start the service +docker compose up javascript-sdk-client-server ``` -docker build . -t uid2-publisher-standard -docker run -it --rm -p 3000:3000 \ - -e UID2_BASE_URL="https://operator-integ.uidapi.com" \ - -e UID2_API_KEY="{INTEG_API_KEY}" \ - -e UID2_CLIENT_SECRET="{CLIENT_SECRET}" \ - uid2-publisher-standard -``` -If this command does not work in Powershell because of the `-e` variable, try running in Command Prompt with quotes around each variable like so: +The application will be available at http://localhost:3032 + +To view logs or stop the service: + +```bash +# View logs (in another terminal) +docker compose logs javascript-sdk-client-server +# Stop the service +docker compose stop javascript-sdk-client-server ``` -docker build . -t uid2-publisher-server -docker run -it --rm -p 3000:3000 -e "UID2_BASE_URL=https://operator-integ.uidapi.com" -e "UID2_API_KEY={INTEG_API_KEY}" -e "UID2_CLIENT_SECRET={CLIENT_SECRET}" uid2-publisher-server + +### Using Docker Build + +```bash +# Build the image +docker build -f web-integrations/javascript-sdk/client-server/Dockerfile -t javascript-sdk-client-server . + +# Run the container +docker run -it --rm -p 3032:3032 --env-file .env javascript-sdk-client-server ``` The following table lists the environment variables that you must specify to start the application. -| Parameter | Data Type | Description | -| :------------------- | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `UID2_BASE_URL` | string | The base URL of the UID2 service. For example:
Testing environment: `https://operator-integ.uidapi.com`
For details, see [Environments](https://unifiedid.com/docs/getting-started/gs-environments). | -| `UID2_API_KEY` | string | Your UID2 authentication key for the UID2 service specified in `UID2_BASE_URL`. | -| `UID2_CLIENT_SECRET` | string | Your UID2 client secret for the UID2 service specified in `UID2_BASE_URL`. | +### Core Configuration -After you see output similar to the following, the example application is up and running. +| Variable | Description | Example Values | +|:---------|:------------|:---------------| +| `UID_SERVER_BASE_URL` | The base URL of the UID2/EUID service. For details, see [Environments](https://unifiedid.com/docs/getting-started/gs-environments) (UID2) or [Environments](https://euid.eu/docs/getting-started/gs-environments) (EUID). | UID2: `https://operator-integ.uidapi.com`
EUID: `https://integ.euid.eu/v2` | +| `UID_API_KEY` | Your UID2/EUID authentication key for the UID2/EUID service specified in UID_SERVER_BASE_URL. | Your assigned API key | +| `UID_CLIENT_SECRET` | Your UID2/EUID client secret for the UID2/EUID service specified in UID_SERVER_BASE_URL. | Your assigned client secret | +| `UID_JS_SDK_URL` | URL to the JavaScript SDK | UID2: `https://cdn.integ.uidapi.com/uid2-sdk-4.0.1.js`
EUID: `https://cdn.integ.euid.eu/euid-sdk-4.0.1.js` | +| `UID_JS_SDK_NAME` | Global variable name for the SDK | UID2: `__uid2`
EUID: `__euid` | -``` -> uid2-publisher@1.0.0 start /usr/src/app -> node server.js +### Display/UI Configuration -Example app listening at http://localhost:3000 -``` +| Variable | Description | Example Values | +|:---------|:------------|:---------------| +| `IDENTITY_NAME` | Identity name for UI display | UID2: `UID2`
EUID: `EUID` | +| `DOCS_BASE_URL` | Documentation base URL | UID2: `https://unifiedid.com/docs`
EUID: `https://euid.eu/docs` | -If needed, to close the application, terminate the docker container or use the `Ctrl+C` keyboard shortcut. ## Test the Example Application -The example application illustrates the steps documented in the [UID2 SDK Integration Guide](https://unifiedid.com/docs/guides/publisher-client-side). For an overview of the high-level workflow for establishing UID2 identity, API reference, and explanation of the UID2 cookie format, see [UID2 SDK for JavaScript](https://unifiedid.com/docs/sdks/client-side-identity). +The example application illustrates the steps documented in the integration guides. For an overview of the high-level workflow for establishing UID2/EUID identity, API reference, and cookie format details, see: +- UID2: [UID2 SDK Integration Guide](https://unifiedid.com/docs/guides/publisher-client-side), [UID2 SDK for JavaScript](https://unifiedid.com/docs/sdks/client-side-identity) +- EUID: [EUID SDK Integration Guide](https://euid.eu/docs/guides/publisher-client-side), [EUID SDK for JavaScript](https://euid.eu/docs/sdks/client-side-identity) + +**Note:** For API endpoint documentation, see the UID2 or EUID docs based on your configuration. The following table outlines and annotates the steps you may take to test and explore the example application. | Step | Description | Comments | | :--: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 1 | In your browser, navigate to the application main page at `http://localhost:3000`. | The displayed main ([index](views/index.html)) page of the example application provides a login form for the user to complete the UID2 login process.
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. | This is a call to the `/login` endpoint ([server.js](server.js)). The login initiated on the server side then calls the [POST /token/generate](https://unifiedid.com/docs/endpoints/post-token-generate) endpoint and processes the received response. | -| | 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 `POST /token/generate` response. It has been passed to the `login` [view](views/login.html) for rendering client-side JavaScript. Next, the identity information is passed to the [UID2 SDK `init()` function](https://unifiedid.com/docs/sdks/client-side-identity#initopts-object-void). If the identity is valid, the SDK stores it in a [first-party UID2 cookie](https://unifiedid.com/docs/sdks/client-side-identity#uid2-cookie-format) for use on subsequent page loads. | -| 3 | Click the **Back to the main page** link. | On the updated application main page, note the newly populated **UID2 Advertising Token** value. The [page view](views/index.html) calls the [init() function](https://unifiedid.com/docs/sdks/client-side-identity#initopts-object-void) again, but this time without passing an explicit identity. Instead, the identity is loaded from the first-party cookie. | -| 4 | (Optional) Right-click the main page to inspect the source code. | When the UID2 SDK initialization is complete, the SDK invokes the passed [callback function](https://unifiedid.com/docs/sdks/client-side-identity#callback-function) (`onUid2IdentityUpdated()` in this example).
IMPORTANT: The callback updates the page elements with the state of UID2 identity: this is the place where you should define your logic for initiating targeted advertising. | -| 5 | Keep the application main page open or refresh it after awhile and note the UID2 identity state, updated counter, and login information values. | In the background, the UID2 SDK continuously validates whether the advertising token is up-to-date and refreshes it automatically when needed. If the refresh succeeds, the user opts out, or the refresh token expires, the callback function is invoked and the UI elements are updated with the current state of the UID2 identity. For details, see [Workflow States and Transitions](https://unifiedid.com/docs/sdks/client-side-identity#workflow-states-and-transitions) and [Background Token Auto-Refresh](https://unifiedid.com/docs/sdks/client-side-identity#background-token-auto-refresh). | -| 6 | To exit the application, click **Clear UID2**. | This event calls the [UID2 SDK `disconnect()` function](https://unifiedid.com/docs/sdks/client-side-identity#disconnect-void), which clears the UID2 session and the first-party cookie. This call also makes the [UID2 SDK `isLoginRequired()` function](https://unifiedid.com/docs/sdks/client-side-identity#isloginrequired-boolean) return `true`, which presents the user with the login form again.
NOTE: The page displays the **Clear UID2** button as long as the user identity is valid and refreshable within the integration test environment. | \ No newline at end of file +| 1 | In your browser, navigate to the application main page at `http://localhost:3032`. | The displayed main ([index](views/index.html)) page of the example application provides a login form for the user to complete the UID2/EUID login process.
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** or **Generate EUID**. Note: The button label depends on your environment configuration; in a real production environment, labels may differ. | This is a call to the `/login` endpoint ([server.js](server.js)). The login initiated on the server side then calls the POST /token/generate endpoint and processes the received response. | +| | A confirmation message appears with the established identity information. | The displayed identity information is the `body` property of the JSON response payload from the POST /token/generate response. It has been passed to the `login` [view](views/login.html) for rendering client-side JavaScript. Next, the identity information is passed to the SDK `init()` function. If the identity is valid, the SDK stores it in a first-party cookie for use on subsequent page loads. | +| 3 | Click the **Back to the main page** link. | On the updated application main page, note the newly populated **Advertising Token** value. The [page view](views/index.html) calls the init() function again, but this time without passing an explicit identity. Instead, the identity is loaded from the first-party cookie. | +| 4 | (Optional) Right-click the main page to inspect the source code. | When the SDK initialization is complete, the SDK invokes the passed callback function.
IMPORTANT: The callback updates the page elements with the state of the identity: this is the place where you should define your logic for initiating targeted advertising. | +| 5 | Keep the application main page open or refresh it after awhile and note the identity state, updated counter, and login information values. | In the background, the SDK continuously validates whether the advertising token is up-to-date and refreshes it automatically when needed. If the refresh succeeds, the user opts out, or the refresh token expires, the callback function is invoked and the UI elements are updated with the current state of the identity. | +| 6 | To exit the application, click **Clear UID2** or **Clear EUID**. | This event calls the SDK `disconnect()` function, which clears the session and the first-party cookie. This call also makes the SDK `isLoginRequired()` function return `true`, which presents the user with the login form again.
NOTE: The page displays the **Clear** button as long as the user identity is valid and refreshable within the integration test environment. | \ No newline at end of file diff --git a/web-integrations/javascript-sdk/client-server/server.js b/web-integrations/javascript-sdk/client-server/server.js index 55485971..1ceb7b7d 100644 --- a/web-integrations/javascript-sdk/client-server/server.js +++ b/web-integrations/javascript-sdk/client-server/server.js @@ -9,9 +9,15 @@ const crypto = require('crypto'); const app = express(); const port = process.env.PORT || 3032; -const uid2BaseUrl = process.env.UID2_BASE_URL; -const uid2ApiKey = process.env.UID2_API_KEY; -const uid2ClientSecret = process.env.UID2_CLIENT_SECRET; +const uidBaseUrl = process.env.UID_SERVER_BASE_URL; +const uidApiKey = process.env.UID_API_KEY; +const uidClientSecret = process.env.UID_CLIENT_SECRET; + +// UI/Display configuration +const identityName = process.env.IDENTITY_NAME; +const docsBaseUrl = process.env.DOCS_BASE_URL; +const uidJsSdkUrl = process.env.UID_JS_SDK_URL || 'https://cdn.integ.uidapi.com/uid2-sdk-4.0.1.js'; +const uidJsSdkName = process.env.UID_JS_SDK_NAME || '__uid2'; const ivLength = 12; const nonceLength = 8; @@ -25,7 +31,13 @@ app.engine('.html', ejs.__express); app.set('view engine', 'html'); app.get('/', (req, res) => { - res.render('index', { uid2BaseUrl: uid2BaseUrl }); + res.render('index', { + uidBaseUrl, + identityName, + docsBaseUrl, + uidJsSdkUrl, + uidJsSdkName + }); }); function bufferToBase64(arrayBuffer) { @@ -86,7 +98,7 @@ function createEnvelope(payload) { const payloadEncoded = new TextEncoder().encode(payload); const body = Buffer.concat([Buffer.from(new Uint8Array(bufferMillisec)), nonce, payloadEncoded]); - const { ciphertext, iv } = encryptRequest(body, uid2ClientSecret); + const { ciphertext, iv } = encryptRequest(body, uidClientSecret); const envelopeVersion = Buffer.alloc(1, 1); const envelope = bufferToBase64(Buffer.concat([envelopeVersion, iv, Buffer.from( new Uint8Array(ciphertext))])); @@ -98,22 +110,44 @@ app.post('/login', async (req, res) => { const { envelope, nonce } = createEnvelope(jsonEmail); const headers = { - headers: { 'Authorization': 'Bearer ' + uid2ApiKey } + headers: { 'Authorization': 'Bearer ' + uidApiKey } }; try { - const encryptedResponse = await axios.post(uid2BaseUrl + '/v2/token/generate', envelope, headers); //if HTTP response code is not 200, this throws and is caught in the catch handler below. - const response = decrypt(encryptedResponse.data, uid2ClientSecret, nonce); + const encryptedResponse = await axios.post(uidBaseUrl + '/v2/token/generate', envelope, headers); //if HTTP response code is not 200, this throws and is caught in the catch handler below. + const response = decrypt(encryptedResponse.data, uidClientSecret, nonce); if (response.status !== 'success') { - res.render('error', { error: 'Got unexpected token generate status in decrypted response: ' + response.status, response: response }); + res.render('error', { + error: 'Got unexpected token generate status in decrypted response: ' + response.status, + response, + identityName, + docsBaseUrl + }); } else if (typeof response.body !== 'object') { - res.render('error', { error: 'Unexpected token generate response format in decrypted response: ' + response, response: response }); + res.render('error', { + error: 'Unexpected token generate response format in decrypted response: ' + response, + response, + identityName, + docsBaseUrl + }); } else { - res.render('login', { identity: response.body, uid2BaseUrl: uid2BaseUrl }); + res.render('login', { + identity: response.body, + uidBaseUrl, + identityName, + docsBaseUrl, + uidJsSdkUrl, + uidJsSdkName + }); } } catch (error) { - res.render('error', { error: error, response: error.response }); + res.render('error', { + error, + response: error.response, + identityName, + docsBaseUrl + }); } }); diff --git a/web-integrations/javascript-sdk/client-server/views/error.html b/web-integrations/javascript-sdk/client-server/views/error.html index 5e216e61..450b4bb5 100644 --- a/web-integrations/javascript-sdk/client-server/views/error.html +++ b/web-integrations/javascript-sdk/client-server/views/error.html @@ -2,7 +2,7 @@ - Error - Client-Server UID2 Integration Example using JavaScript SDK + Error - Client-Server <%- identityName %> Integration Example using JavaScript SDK @@ -10,7 +10,7 @@ <%- include('intro.html'); -%>

Something went wrong:

<%= error %>
-

Response from the UID2 operator:

+

Response from the <%- identityName %> operator:

<%= response ? JSON.stringify(response.data) : '' %>

HTTP error:

<%= response ? (response.status + ' ' + response.statusText) : '' %>
diff --git a/web-integrations/javascript-sdk/client-server/views/index.html b/web-integrations/javascript-sdk/client-server/views/index.html index d4b9b34c..d1d6cafd 100644 --- a/web-integrations/javascript-sdk/client-server/views/index.html +++ b/web-integrations/javascript-sdk/client-server/views/index.html @@ -2,23 +2,25 @@ - Client-Server UID2 Integration Example using JavaScript SDK + Client-Server <%- identityName %> Integration Example using JavaScript SDK - + @@ -60,19 +62,19 @@
- + - + - + - +
- UID2 Enabled{' '} - - {IDENTITY_NAME} Status
UID2 Advertising Token:{IDENTITY_NAME} Advertising Token:
{advertisingToken}
Is UID2 Login Required?Is {IDENTITY_NAME} Login Required?
{loginRequired ? 'yes' : 'no'}
UID2 Identity Callback State:{IDENTITY_NAME} Identity Callback State:
{identityState}
UID2 Advertising Token:<%- identityName %> Advertising Token:
Is UID2 Login Required?Is <%- identityName %> Login Required?
UID2 Identity Updated Counter:<%- identityName %> Identity Updated Counter:
UID2 Identity Callback State:<%- identityName %> Identity Callback State:
@@ -87,12 +89,12 @@ style="border-style: none" />
-
+
diff --git a/web-integrations/javascript-sdk/client-server/views/intro.html b/web-integrations/javascript-sdk/client-server/views/intro.html index 989db663..064d476f 100644 --- a/web-integrations/javascript-sdk/client-server/views/intro.html +++ b/web-integrations/javascript-sdk/client-server/views/intro.html @@ -1,12 +1,12 @@ -

Client-Server UID2 Integration Example using JavaScript SDK

+

Client-Server <%- identityName %> Integration Example using JavaScript SDK

- This example demonstrates how a content publisher can use the UID2 services and the - UID2 SDK for JavaScript services and the + <%- identityName %> SDK for JavaScript - (UID2 SDK) to implement the - client-server UID2 integration workflow SDK) to implement the + client-server <%- identityName %> integration workflow. [Source Code] diff --git a/web-integrations/javascript-sdk/client-server/views/login.html b/web-integrations/javascript-sdk/client-server/views/login.html index c3dc3cac..e3c502f8 100644 --- a/web-integrations/javascript-sdk/client-server/views/login.html +++ b/web-integrations/javascript-sdk/client-server/views/login.html @@ -2,30 +2,32 @@ - Login - Client-Server UID2 Integration Example using JavaScript SDK + Login - Client-Server <%- identityName %> Integration Example using JavaScript SDK - + <%- include('intro.html'); -%> -

Generate UID2 completed

-

UID2 identity:

+

Generate <%- identityName %> completed

+

<%- identityName %> identity:

<%- JSON.stringify(identity, null, 2) %>

Back to the main page

- Normally user would be redirected automatically, but this example demonstrates one way UID2 + Normally user would be redirected automatically, but this example demonstrates one way <%- identityName %> generation could be handled.

diff --git a/web-integrations/javascript-sdk/client-side/README.md b/web-integrations/javascript-sdk/client-side/README.md index dc6c211f..5319c837 100644 --- a/web-integrations/javascript-sdk/client-side/README.md +++ b/web-integrations/javascript-sdk/client-side/README.md @@ -1,45 +1,66 @@ -# Client-Side UID2 Integration Example using JavaScript SDK +# Client-Side UID2 or EUID Integration Example using JavaScript SDK -This example demonstrates how a content publisher can follow the [Client-Side Integration Guide for JavaScript](https://unifiedid.com/docs/guides/integration-javascript-client-side) to implement UID2 integration and generate UID2 tokens. +This example demonstrates how a content publisher can follow the Client-Side Integration Guide for JavaScript to implement either a UID2 or EUID integration and generate tokens on the client side. + +- For UID2: [Client-Side Integration Guide for JavaScript](https://unifiedid.com/docs/guides/integration-javascript-client-side), [UID2 SDK for JavaScript](https://unifiedid.com/docs/sdks/sdk-ref-javascript) +- For EUID: [EUID Client-Side Integration Guide for JavaScript](https://euid.eu/docs/guides/integration-javascript-client-side), [EUID SDK for JavaScript](https://euid.eu/docs/sdks/sdk-ref-javascript) + +This example can be configured for either UID2 or EUID — the behavior is determined by your environment variable configuration. You cannot use both simultaneously. ## Running with Docker ### Using Docker Compose (Recommended) -From the base directory: +From the repository root directory: ```bash # Start the service -docker-compose up -d javascript-sdk-client-side +docker compose up javascript-sdk-client-side +``` + +The application will be available at http://localhost:3031 + +To view logs or stop the service: -# View logs -docker-compose logs javascript-sdk-client-side +```bash +# View logs (in another terminal) +docker compose logs javascript-sdk-client-side # Stop the service -docker-compose down javascript-sdk-client-side +docker compose stop javascript-sdk-client-side ``` -### Using Docker directly - -From the base directory: +### Using Docker Build ```bash # Build the image docker build -f web-integrations/javascript-sdk/client-side/Dockerfile -t javascript-sdk-client-side . # Run the container -docker run -p 3032:3032 --env-file .env javascript-sdk-client-side +docker run -it --rm -p 3031:3031 --env-file .env javascript-sdk-client-side ``` ## Environment Variables The application uses environment variables from the `.env` file in the base directory: -- `UID_JS_SDK_URL` - URL to the UID2 JavaScript SDK (default: https://cdn.uidapi.com/sdk/uid2-sdk-3.3.0.js) -- `UID_JS_SDK_NAME` - Global variable name for the SDK (default: __uid2) -- `UID_BASE_URL` - UID2 base URL (default: https://operator-integ.uidapi.com) -- `SERVER_PUBLIC_KEY` - Server public key for UID2 -- `SUBSCRIPTION_ID` - UID2 subscription ID +### Core Configuration + +| Variable | Description | Example Values | +|:---------|:------------|:---------------| +| `UID_JS_SDK_URL` | URL to the UID2/EUID JavaScript SDK | UID2: `https://cdn.integ.uidapi.com/uid2-sdk-4.0.1.js`
EUID: `https://cdn.integ.euid.eu/euid-sdk-4.0.1.js` | +| `UID_JS_SDK_NAME` | Global variable name for the SDK | UID2: `__uid2`
EUID: `__euid` | +| `UID_CLIENT_BASE_URL` | API base URL for client-side/browser calls | UID2: `https://operator-integ.uidapi.com` or `http://localhost:8080`
EUID: `https://integ.euid.eu/v2` | +| `UID_BASE_URL` | Fallback API base URL (used if `UID_CLIENT_BASE_URL` not set) | Same as above | +| `UID_CSTG_SERVER_PUBLIC_KEY` | Your server public key for client-side token generation for the UID2/EUID service specified in UID_BASE_URL. | Your assigned server public key | +| `UID_CSTG_SUBSCRIPTION_ID` | Your subscription ID for client-side token generation for the UID2/EUID service specified in UID_BASE_URL. | Your assigned subscription ID | + +### Display/UI Configuration + +| Variable | Description | Example Values | +|:---------|:------------|:---------------| +| `IDENTITY_NAME` | Identity name for UI display | UID2: `UID2`
EUID: `EUID` | +| `DOCS_BASE_URL` | Documentation base URL | UID2: `https://unifiedid.com/docs`
EUID: `https://euid.eu/docs` | ## Accessing the Application @@ -47,8 +68,9 @@ Once running, access the application at: http://localhost:3032 ## Features -- **Client-side UID2 integration** using the UID2 JavaScript SDK -- **Environment variable substitution** for configuration +- **Client-side UID2/EUID integration** using the UID2/EUID JavaScript SDK +- **Dynamic product configuration** - supports both UID2 and EUID via environment variables +- **Environment variable substitution** for all configuration and UI text - **Nginx-based static file serving** - **Docker containerization** for easy deployment diff --git a/web-integrations/javascript-sdk/client-side/entrypoint.sh b/web-integrations/javascript-sdk/client-side/entrypoint.sh index ac366bd2..ab859464 100644 --- a/web-integrations/javascript-sdk/client-side/entrypoint.sh +++ b/web-integrations/javascript-sdk/client-side/entrypoint.sh @@ -1,15 +1,22 @@ #!/bin/sh # Set default values if not provided -export UID_JS_SDK_URL=${UID2_JS_SDK_URL:-"https://cdn.integ.uidapi.com/uid2-sdk-4.0.1.js"} -export UID_JS_SDK_NAME=${UID2_JS_SDK_NAME:-"__uid2"} -export UID_BASE_URL=${UID2_BASE_URL:-"https://operator-integ.uidapi.com"} -export SERVER_PUBLIC_KEY=${UID2_CSTG_SERVER_PUBLIC_KEY:-"UID2-X-I-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEo+jcPlk8GWn3iG0R5Il2cbFQI9hR3TvHxaBUKHl5Vh+ugr+9uLMiXihka8To07ETFGghEifY96Hrpe5RnYko7Q=="} -export SUBSCRIPTION_ID=${UID2_CSTG_SUBSCRIPTION_ID:-"DMr7uHxqLU"} +export UID_JS_SDK_URL=${UID_JS_SDK_URL:-"https://cdn.integ.uidapi.com/uid2-sdk-4.0.1.js"} +export UID_JS_SDK_NAME=${UID_JS_SDK_NAME:-"__uid2"} +# Use CLIENT_BASE_URL for browser calls, fallback to BASE_URL if not set +export UID_BASE_URL=${UID_CLIENT_BASE_URL:-${UID_BASE_URL:-"https://operator-integ.uidapi.com"}} +export SERVER_PUBLIC_KEY=${UID_CSTG_SERVER_PUBLIC_KEY:-"UID2-X-I-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEo+jcPlk8GWn3iG0R5Il2cbFQI9hR3TvHxaBUKHl5Vh+ugr+9uLMiXihka8To07ETFGghEifY96Hrpe5RnYko7Q=="} +export SUBSCRIPTION_ID=${UID_CSTG_SUBSCRIPTION_ID:-"DMr7uHxqLU"} +export IDENTITY_NAME=${IDENTITY_NAME:-"UID2"} +export DOCS_BASE_URL=${DOCS_BASE_URL:-"https://unifiedid.com/docs"} # Process index.html template with environment variables envsubst < /usr/share/nginx/html/index.html > /usr/share/nginx/html/index.temp.html mv /usr/share/nginx/html/index.temp.html /usr/share/nginx/html/index.html +# Process iframe.html template with environment variables +envsubst < /usr/share/nginx/html/iframe.html > /usr/share/nginx/html/iframe.temp.html +mv /usr/share/nginx/html/iframe.temp.html /usr/share/nginx/html/iframe.html + # Start nginx exec nginx -g "daemon off;" diff --git a/web-integrations/javascript-sdk/client-side/html/iframe.html b/web-integrations/javascript-sdk/client-side/html/iframe.html index e34c8a07..fab1c21a 100644 --- a/web-integrations/javascript-sdk/client-side/html/iframe.html +++ b/web-integrations/javascript-sdk/client-side/html/iframe.html @@ -2,7 +2,7 @@ - Client-Side UID2 Integration Example using JavaScript SDK + Client-Side ${IDENTITY_NAME} Integration Example using JavaScript SDK diff --git a/web-integrations/javascript-sdk/client-side/html/index.html b/web-integrations/javascript-sdk/client-side/html/index.html index 3d91542f..8ad76e04 100644 --- a/web-integrations/javascript-sdk/client-side/html/index.html +++ b/web-integrations/javascript-sdk/client-side/html/index.html @@ -2,7 +2,7 @@ - Client-Side UID2 Integration Example using JavaScript SDK + Client-Side ${IDENTITY_NAME} Integration Example using JavaScript SDK @@ -89,13 +89,13 @@ -

Client-Side UID2 Integration Example using JavaScript SDK

+

Client-Side ${IDENTITY_NAME} Integration Example using JavaScript SDK

This example demonstrates how a content publisher can follow the - Client-Side Integration Guide for JavaScript - to implement UID2 integration and generate UID2 tokens. + to implement ${IDENTITY_NAME} integration and generate ${IDENTITY_NAME} tokens. Note: This is a test-only integration environment—not for production use. It does not perform real user authentication or generate production-level tokens. Do not use real user data on this page. @@ -136,11 +136,11 @@

Client-Side UID2 Integration Example using JavaScript SDK

style="border-style: none" /> -
>
+
>
diff --git a/web-integrations/server-side/README.md b/web-integrations/server-side/README.md index 24d59072..ad22406d 100644 --- a/web-integrations/server-side/README.md +++ b/web-integrations/server-side/README.md @@ -1,8 +1,13 @@ -# Server-Side UID2 Integration Example +# Server-Side UID2 or EUID Integration Example -[This example](https://example-srvonly-integ.uidapi.com/) demonstrates how a content publisher can use the [UID2 services](https://unifiedid.com/docs/intro) to implement the [server-side UID2 integration workflow](https://unifiedid.com/docs/guides/integration-publisher-server-side). +[This example](https://example-srvonly-integ.uidapi.com/) demonstrates how a content publisher can use either the UID2 or EUID services to implement the server-side integration workflow without using an SDK. -For an example application using the [UID2 SDK for JavaScript](https://unifiedid.com/docs/sdks/sdk-ref-javascript), see [Client-Server UID2 Integration Example using JavaScript SDK](../javascript-sdk/client-server/README.md) or [Client-Side UID2 Integration Example using JavaScript SDK](../javascript-sdk/client-side/README.md). +- For UID2: [UID2 services](https://unifiedid.com/docs/intro), [server-side UID2 integration workflow](https://unifiedid.com/docs/guides/integration-publisher-server-side) +- For EUID: [EUID services](https://euid.eu/docs/intro), [server-side EUID integration workflow](https://euid.eu/docs/guides/integration-publisher-server-side) + +This example can be configured for either UID2 or EUID — the behavior is determined by your environment variable configuration. You cannot use both simultaneously. + +For an example application using the SDK, see [Client-Server UID2 or EUID Integration Example using JavaScript SDK](../javascript-sdk/client-server/README.md) or [Client-Side UID2 or EUID Integration Example using JavaScript SDK](../javascript-sdk/client-side/README.md). >NOTE: While the server side of the example application is implemented in JavaScript using node.js, it is not a requirement. You can use any technology of your choice and refer to the example application for illustration of the functionality that needs to be implemented. @@ -10,44 +15,52 @@ For an example application using the [UID2 SDK for JavaScript](https://unifiedid ### Using Docker Compose (Recommended) -From the base directory: +From the repository root directory: ```bash # Start the service -docker-compose up -d server-side +docker compose up server-side +``` -# View logs -docker-compose logs server-side +The application will be available at http://localhost:3033 + +To view logs or stop the service: + +```bash +# View logs (in another terminal) +docker compose logs server-side # Stop the service -docker-compose down server-side +docker compose stop server-side ``` -### Using Docker directly - -From the base directory: +### Using Docker Build ```bash # Build the image docker build -f web-integrations/server-side/Dockerfile -t server-side . # Run the container -docker run -it --rm -p 3033:3033 \ - -e UID2_BASE_URL="https://operator-integ.uidapi.com" \ - -e UID2_API_KEY="{INTEG_API_KEY}" \ - -e UID2_CLIENT_SECRET="{CLIENT_KEY}" \ - -e SESSION_KEY="{SESSION_KEY}" \ - server-side +docker run -it --rm -p 3033:3033 --env-file .env server-side ``` The following table lists the environment variables that you must specify to start the application. -| Parameter | Data Type | Description | -|:---------------------|:----------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `UID2_BASE_URL` | string | The base URL of the UID2 service. For example:
Testing environment: `https://operator-integ.uidapi.com`
For details, see [Environments](https://unifiedid.com/docs/getting-started/gs-environments). | -| `UID2_API_KEY` | string | Your UID2 authentication key for the UID2 service specified in `UID2_BASE_URL`. | | -| `UID2_CLIENT_SECRET` | string | Your UID2 client secret for the UID2 service specified in `UID2_BASE_URL`. | | -| `SESSION_KEY` | string | The key to the encryption session data stored in the application session cookie. This can be any arbitrary string. | | +### Core Configuration + +| Variable | Description | Example Values | +|:---------|:------------|:---------------| +| `UID_SERVER_BASE_URL` | The base URL of the UID2/EUID service. For details, see [Environments](https://unifiedid.com/docs/getting-started/gs-environments) (UID2) or [Environments](https://euid.eu/docs/getting-started/gs-environments) (EUID). | UID2: `https://operator-integ.uidapi.com`
EUID: `https://integ.euid.eu/v2` | +| `UID_API_KEY` | Your UID2/EUID authentication key for the UID2/EUID service specified in UID_SERVER_BASE_URL. | Your assigned API key | +| `UID_CLIENT_SECRET` | Your UID2/EUID client secret for the UID2/EUID service specified in UID_SERVER_BASE_URL. | Your assigned client secret | +| `SESSION_KEY` | The key to the encryption session data stored in the application session cookie. This can be any arbitrary string. | Any secure random string | + +### Display/UI Configuration + +| Variable | Description | Example Values | +|:---------|:------------|:---------------| +| `IDENTITY_NAME` | Identity name for UI display | UID2: `UID2`
EUID: `EUID` | +| `DOCS_BASE_URL` | Documentation base URL | UID2: `https://unifiedid.com/docs`
EUID: `https://euid.eu/docs` | After you see output similar to the following, the example application is up and running. @@ -62,21 +75,25 @@ If needed, to close the application, terminate the docker container or use the ` ## Test the Example Application -The example application illustrates the steps documented in the [Server-Only UID2 Integration Guide](https://unifiedid.com/docs/guides/custom-publisher-integration). +The example application illustrates the steps documented in the server-side integration guides: +- UID2: [Server-Side Integration Guide](https://unifiedid.com/docs/guides/integration-publisher-server-side) +- EUID: [Server-Side Integration Guide](https://euid.eu/docs/guides/integration-publisher-server-side) + +**Note:** For API endpoint documentation, see the UID2 or EUID docs based on your configuration. The application provides three main pages: index (main), example content 1, and example content 2. Access to these pages is possible only after the user completes the login process. If the user is not logged in, they will be redirected to the login page. Submitting the login form simulates logging in to a publisher's application in the real world. Normally the login would require checking the user's secure credentials (for example, a password), but for demonstration purposes this -step is omitted, and the login process focuses on integration with the UID2 services instead. +step is omitted, and the login process focuses on integration with the UID2/EUID services instead. The following table outlines and annotates the steps you may take to test and explore the example application. | Step | Description | Comments | |:----:|:------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 1 | In your browser, navigate to the application main page at `http://localhost:3033`. | The displayed main (index) page of the example application provides a [login form](views/login.html) for the user to complete the UID2 login process.
IMPORTANT: A real-life application must also display a form for the user to express their consent to targeted advertising. | -| 2 | Enter the user email address that you want to use for testing and click **Log In**. | This is a call to the `/login` endpoint ([server.js](server.js)). The login initiated on the server side then calls the [POST /token/generate](https://unifiedid.com/docs/endpoints/post-token-generate) endpoint and processes the received response. | -| | The main page is updated to display links to the two pages with protected content and 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 successful `POST /token/generate` response. If the response is successful, the returned identity is saved to a session cookie (a real-world application would use a different way to store session data) and the protected index page is rendered. | -| 3 | Click either of the two sample content pages. | When the user requests the index or content pages, the server reads the user session and extracts the current UID2 identity ([server.js](server.js)). The `advertising_token` on the identity can be used for targeted advertising. | -| 4 | Click the **Back to the main page** link. | Note that the identity contains several timestamps that determine when the advertising token becomes invalid (`identity_expires`) and when the server should attempt to refresh it (`refresh_from`). Every time a protected page is requested, the `verifyIdentity` function ([server.js](server.js)) calls [POST /token/refresh](https://unifiedid.com/docs/endpoints/post-token-refresh) as needed.
The user is automatically logged out in the following cases:
- If the identity expires without being refreshed and refresh attempt fails.
- If the refresh token expires.
- If the refresh attempt indicates that the user has opted out. | -| 5 | To exit the application, click **Log Out**. | This calls the `/logout` endpoint on the server ([server.js](server.js)), which clears the UID2 session and the first-party cookie and presents the user with the login form again.
NOTE: The page displays the **Log Out** button as long as the user is logged it. | +| 1 | In your browser, navigate to the application main page at `http://localhost:3033`. | The displayed main (index) page of the example application provides a [login form](views/login.html) for the user to complete the UID2/EUID login process.
IMPORTANT: A real-life application must also display a form for the user to express their consent to targeted advertising. | +| 2 | Enter the user email address that you want to use for testing and click **Log In**. | This is a call to the `/login` endpoint ([server.js](server.js)). The login initiated on the server side then calls the POST /token/generate endpoint and processes the received response. | +| | The main page is updated to display links to the two pages with protected content and the established identity information. | The displayed identity information is the `body` property of the JSON response payload from the successful POST /token/generate response. If the response is successful, the returned identity is saved to a session cookie (a real-world application would use a different way to store session data) and the protected index page is rendered. | +| 3 | Click either of the two sample content pages. | When the user requests the index or content pages, the server reads the user session and extracts the current identity ([server.js](server.js)). The `advertising_token` on the identity can be used for targeted advertising. | +| 4 | Click the **Back to the main page** link. | Note that the identity contains several timestamps that determine when the advertising token becomes invalid (`identity_expires`) and when the server should attempt to refresh it (`refresh_from`). Every time a protected page is requested, the `verifyIdentity` function ([server.js](server.js)) calls POST /token/refresh as needed.
The user is automatically logged out in the following cases:
- If the identity expires without being refreshed and refresh attempt fails.
- If the refresh token expires.
- If the refresh attempt indicates that the user has opted out. | +| 5 | To exit the application, click **Log Out**. | This calls the `/logout` endpoint on the server ([server.js](server.js)), which clears the session and the first-party cookie and presents the user with the login form again.
NOTE: The page displays the **Log Out** button as long as the user is logged in. | diff --git a/web-integrations/server-side/server.js b/web-integrations/server-side/server.js index faedcda1..291f9f03 100644 --- a/web-integrations/server-side/server.js +++ b/web-integrations/server-side/server.js @@ -10,9 +10,13 @@ const crypto = require('crypto'); const app = express(); const port = process.env.PORT || 3033; -const uid2BaseUrl = process.env.UID2_BASE_URL; -const uid2ApiKey = process.env.UID2_API_KEY; -const uid2ClientSecret = process.env.UID2_CLIENT_SECRET; +const uidBaseUrl = process.env.UID_SERVER_BASE_URL; +const uidApiKey = process.env.UID_API_KEY; +const uidClientSecret = process.env.UID_CLIENT_SECRET; + +// UI/Display configuration +const identityName = process.env.IDENTITY_NAME; +const docsBaseUrl = process.env.DOCS_BASE_URL; const ivLength = 12; const nonceLength = 8; @@ -83,7 +87,7 @@ function createEnvelope(payload) { const payloadEncoded = new TextEncoder().encode(payload); const body = Buffer.concat([Buffer.from(new Uint8Array(bufferMillisec)), nonce, payloadEncoded]); - const { ciphertext, iv } = encryptRequest(body, uid2ClientSecret); + const { ciphertext, iv } = encryptRequest(body, uidClientSecret); const envelopeVersion = Buffer.alloc(1, 1); const envelope = bufferToBase64(Buffer.concat([envelopeVersion, iv, Buffer.from( new Uint8Array(ciphertext))])); @@ -116,11 +120,11 @@ function isRefreshableIdentity(identity){ async function refreshIdentity(identity) { const headers = { - headers: { 'Authorization': 'Bearer ' + uid2ApiKey } + headers: { 'Authorization': 'Bearer ' + uidApiKey } }; try { - const encryptedResponse = await axios.post(uid2BaseUrl + '/v2/token/refresh', identity.refresh_token, headers); //if HTTP response code is not 200, this throws and is caught in the catch handler below. + const encryptedResponse = await axios.post(uidBaseUrl + '/v2/token/refresh', identity.refresh_token, headers); //if HTTP response code is not 200, this throws and is caught in the catch handler below. let response; if (identity.refresh_response_key) { @@ -163,38 +167,70 @@ async function protect(req, res, next){ } app.get('/', protect, (req, res) => { - res.render('index', { identity: req.session.identity }); + res.render('index', { + identity: req.session.identity, + identityName, + docsBaseUrl + }); }); app.get('/content1', protect, (req, res) => { - res.render('content', { identity: req.session.identity, content: 'First Sample Content' }); + res.render('content', { + identity: req.session.identity, + content: 'First Sample Content', + identityName, + docsBaseUrl + }); }); app.get('/content2', protect, (req, res) => { - res.render('content', { identity: req.session.identity, content: 'Second Sample Content' }); + res.render('content', { + identity: req.session.identity, + content: 'Second Sample Content', + identityName, + docsBaseUrl + }); }); app.get('/login', async (req, res) => { if (await verifyIdentity(req)) { res.redirect('/'); } else { req.session = null; - res.render('login'); + res.render('login', { + identityName, + docsBaseUrl + }); } }); function _GenerateTokenV1(req, res) { - axios.get(uid2BaseUrl + '/v1/token/generate?email=' + encodeURIComponent(req.body.email), { headers: { 'Authorization': 'Bearer ' + uid2ApiKey } }) + axios.get(uidBaseUrl + '/v1/token/generate?email=' + encodeURIComponent(req.body.email), { headers: { 'Authorization': 'Bearer ' + uidApiKey } }) .then((response) => { if (response.data.status !== 'success') { - res.render('error', { error: 'Got unexpected token generate status: ' + response.data.status, response: response }); + res.render('error', { + error: 'Got unexpected token generate status: ' + response.data.status, + response, + identityName, + docsBaseUrl + }); } else if (typeof response.data.body !== 'object') { - res.render('error', { error: 'Unexpected token generate response format: ' + response.data, response: response }); + res.render('error', { + error: 'Unexpected token generate response format: ' + response.data, + response, + identityName, + docsBaseUrl + }); } else { req.session.identity = response.data.body; res.redirect('/'); } }) .catch((error) => { - res.render('error', { error: error, response: error.response }); + res.render('error', { + error, + response: error.response, + identityName, + docsBaseUrl + }); }); } @@ -206,23 +242,38 @@ app.post('/login', async (req, res) => { const { envelope, nonce } = createEnvelope(jsonEmail); const headers = { - headers: { 'Authorization': 'Bearer ' + uid2ApiKey } + headers: { 'Authorization': 'Bearer ' + uidApiKey } }; try { - const encryptedResponse = await axios.post(uid2BaseUrl + '/v2/token/generate', envelope, headers); //if HTTP response code is not 200, this throws and is caught in the catch handler below. - const response = decrypt(encryptedResponse.data, uid2ClientSecret, false, nonce); - - if (response.status !== 'success') { - res.render('error', { error: 'Got unexpected token generate status in decrypted response: ' + response.status, response: response }); + const encryptedResponse = await axios.post(uidBaseUrl + '/v2/token/generate', envelope, headers); //if HTTP response code is not 200, this throws and is caught in the catch handler below. + const response = decrypt(encryptedResponse.data, uidClientSecret, false, nonce); + + if (response.status !== 'success') { + res.render('error', { + error: 'Got unexpected token generate status in decrypted response: ' + response.status, + response, + identityName, + docsBaseUrl + }); } else if (typeof response.body !== 'object') { - res.render('error', { error: 'Unexpected token generate response format in decrypted response: ' + response, response: response }); + res.render('error', { + error: 'Unexpected token generate response format in decrypted response: ' + response, + response, + identityName, + docsBaseUrl + }); } else { req.session.identity = response.body; res.redirect('/'); } } catch (error) { - res.render('error', { error: error, response: error.response }); + res.render('error', { + error, + response: error.response, + identityName, + docsBaseUrl + }); } }); diff --git a/web-integrations/server-side/views/content.html b/web-integrations/server-side/views/content.html index 4f86f4d1..710c7e02 100644 --- a/web-integrations/server-side/views/content.html +++ b/web-integrations/server-side/views/content.html @@ -1,5 +1,5 @@ <%- include('header.html'); -%> -

Protected Content — accessible only with a valid UID2 identity:

+

Protected Content — accessible only with a valid <%- identityName %> identity:

<%= content %>

Back to the main page

<%- include('identity.html'); -%> diff --git a/web-integrations/server-side/views/error.html b/web-integrations/server-side/views/error.html index 25ddea9d..f8b33c1d 100644 --- a/web-integrations/server-side/views/error.html +++ b/web-integrations/server-side/views/error.html @@ -1,7 +1,7 @@ <%- include('header.html'); -%>

Something went wrong:

<%= error %>
-

Response from the UID2 operator:

+

Response from the <%- identityName %> operator:

<%= response ? JSON.stringify(response.data) : '' %>

HTTP error:

<%= response ? (response.status + ' ' + response.statusText) : '' %>
diff --git a/web-integrations/server-side/views/header.html b/web-integrations/server-side/views/header.html index 9d882bbe..f436e9a0 100644 --- a/web-integrations/server-side/views/header.html +++ b/web-integrations/server-side/views/header.html @@ -2,12 +2,12 @@ - Server-Side UID2 Integration Example + Server-Side <%- identityName %> Integration Example -

Server-Side UID2 Integration Example

-

This example demonstrates how a content publisher can use UID2 services to implement the - server-side UID2 integration workflow. +

Server-Side <%- identityName %> Integration Example

+

This example demonstrates how a content publisher can use <%- identityName %> services to implement the + server-side <%- identityName %> integration workflow. [Source Code]

diff --git a/web-integrations/server-side/views/index.html b/web-integrations/server-side/views/index.html index 8d45f73f..2b2b47b7 100644 --- a/web-integrations/server-side/views/index.html +++ b/web-integrations/server-side/views/index.html @@ -1,9 +1,9 @@ <%- include('header.html'); -%> -

Protected Content — accessible only with a valid UID2 identity:

+

Protected Content — accessible only with a valid <%- identityName %> identity:

-

Current UID2 Identity:

+

Current <%- identityName %> Identity:

<%- include('identity.html'); -%> <%- include('footer.html'); -%>