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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tools/reverse-proxy/default.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ server {
location / {
add_header Content-Type text/html;
# Use protocol-relative URLs (//) so they work with both http and https
return 200 "<!DOCTYPE html><html><head><title>UID2 Sample Pages</title><style>body{font-family:Arial,sans-serif;max-width:800px;margin:50px auto;padding:20px;background:#f5f5f5}h1{color:#333}a{display:block;padding:10px;margin:5px 0;background:white;border-left:4px solid #007bff;text-decoration:none;color:#007bff;border-radius:4px}a:hover{background:#e7f3ff;border-left-color:#0056b3}.info{margin-top:30px;padding:15px;background:#fff3cd;border-left:4px solid #ffc107;border-radius:4px}</style></head><body><h1>UID2 Sample Pages</h1><p>Access services using the following subdomains:</p><a href=\"//js-client-side.${DOMAIN}\">js-client-side.${DOMAIN}</a><a href=\"//js-client-server.${DOMAIN}\">js-client-server.${DOMAIN}</a><a href=\"//js-react.${DOMAIN}\">js-react.${DOMAIN}</a><a href=\"//server-side.${DOMAIN}\">server-side.${DOMAIN}</a><a href=\"//secure-signals-client-server.${DOMAIN}\">secure-signals-client-server.${DOMAIN}</a><a href=\"//secure-signals-client-side.${DOMAIN}\">secure-signals-client-side.${DOMAIN}</a><a href=\"//secure-signals-server-side.${DOMAIN}\">secure-signals-server-side.${DOMAIN}</a><a href=\"//secure-signals-react.${DOMAIN}\">secure-signals-react.${DOMAIN}</a><a href=\"//prebid-client.${DOMAIN}\">prebid-client.${DOMAIN}</a><a href=\"//prebid-client-server.${DOMAIN}\">prebid-client-server.${DOMAIN}</a><a href=\"//prebid-deferred.${DOMAIN}\">prebid-deferred.${DOMAIN} (mergeConfig example)</a><a href=\"//prebid-secure-signals.${DOMAIN}\">prebid-secure-signals.${DOMAIN}</a><div class=\"info\"><strong>Note:</strong> For local development, add ${DOMAIN} and all subdomains to your hosts file (127.0.0.1) to use them. Example: <code>127.0.0.1 ${DOMAIN} js-client-side.${DOMAIN} ...</code></div></body></html>";
return 200 "<!DOCTYPE html><html><head><title>UID2 Sample Pages</title><style>body{font-family:Arial,sans-serif;max-width:800px;margin:50px auto;padding:20px;background:#f5f5f5}h1{color:#333}a{display:block;padding:10px;margin:5px 0;background:white;border-left:4px solid #007bff;text-decoration:none;color:#007bff;border-radius:4px}a:hover{background:#e7f3ff;border-left-color:#0056b3}.info{margin-top:30px;padding:15px;background:#fff3cd;border-left:4px solid #ffc107;border-radius:4px}</style></head><body><h1>UID2 Sample Pages</h1><p>Access services using the following subdomains:</p><a href=\"//js-client-side.${DOMAIN}\" target=\"_blank\">js-client-side.${DOMAIN}</a><a href=\"//js-client-server.${DOMAIN}\" target=\"_blank\">js-client-server.${DOMAIN}</a><a href=\"//js-react.${DOMAIN}\" target=\"_blank\">js-react.${DOMAIN}</a><a href=\"//server-side.${DOMAIN}\" target=\"_blank\">server-side.${DOMAIN}</a><a href=\"//secure-signals-client-server.${DOMAIN}\" target=\"_blank\">secure-signals-client-server.${DOMAIN}</a><a href=\"//secure-signals-client-side.${DOMAIN}\" target=\"_blank\">secure-signals-client-side.${DOMAIN}</a><a href=\"//secure-signals-server-side.${DOMAIN}\" target=\"_blank\">secure-signals-server-side.${DOMAIN}</a><a href=\"//secure-signals-react.${DOMAIN}\" target=\"_blank\">secure-signals-react.${DOMAIN}</a><a href=\"//prebid-client.${DOMAIN}\" target=\"_blank\">prebid-client.${DOMAIN}</a><a href=\"//prebid-client-server.${DOMAIN}\" target=\"_blank\">prebid-client-server.${DOMAIN}</a><a href=\"//prebid-deferred.${DOMAIN}\" target=\"_blank\">prebid-deferred.${DOMAIN}</a><a href=\"//prebid-secure-signals.${DOMAIN}\" target=\"_blank\">prebid-secure-signals.${DOMAIN}</a><div class=\"info\"><strong>Note:</strong> For local development, add ${DOMAIN} and all subdomains to your hosts file (127.0.0.1) to use them. Example: <code>127.0.0.1 ${DOMAIN} js-client-side.${DOMAIN} ...</code></div></body></html>";
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,6 @@
// Read from localStorage
const secureSignalsStorageKey = '<%- secureSignalsStorageKey %>';
const secureSignalsStorage = localStorage[secureSignalsStorageKey];
const token = sdk.getAdvertisingToken();

// Safety net: If token exists but Secure Signals haven't loaded yet, reload the page
if (token && !secureSignalsStorage && !<%= isOptout %>) {
console.log("Token exists but Secure Signals not loaded yet, reloading page...");
location.reload();
return;
}
Copy link
Contributor Author

@eiman-eltigani-ttd eiman-eltigani-ttd Dec 12, 2025

Choose a reason for hiding this comment

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

Removed the infinite reload loop in secure signals client server (bug fix)


const secureSignalsStorageJson = secureSignalsStorage && JSON.parse(secureSignalsStorage);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM nginx:alpine

# Install gettext for envsubst
RUN apk add --no-cache gettext

# Copy static files from client-side-deferred directory
COPY client-side-deferred/app.css /usr/share/nginx/html/
COPY prebid.js /usr/share/nginx/html/

# Copy config and HTML
COPY client-side-deferred/default.conf /etc/nginx/conf.d/default.conf
COPY client-side-deferred/index.html /usr/share/nginx/html/index.template.html
COPY client-side-deferred/entrypoint.sh /entrypoint.sh

RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]

123 changes: 123 additions & 0 deletions web-integrations/prebid-integrations/client-side-deferred/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Deferred UID2/EUID Integration with Prebid.js (using mergeConfig)

This example demonstrates how to integrate UID2 or EUID with Prebid.js using **deferred configuration**. Unlike the standard integration where UID2/EUID is configured on page load, this pattern uses `mergeConfig()` and `refreshUserIds()` to add the identity module *after* the page has already loaded.

## Use Cases

This pattern is useful for:

- **Async Login**: User logs in after the page has loaded
- **Delayed Consent**: Consent is given asynchronously (e.g., via a consent management platform)
- **Single Page Applications (SPAs)**: Dynamic login/logout without full page reloads
- **Lazy Loading**: Only load UID2/EUID when actually needed
- **User State Changes**: Handle logout and re-login scenarios

## How It Works

### Standard Flow (for comparison)
```javascript
// Page load: UID2 configured immediately
pbjs.setConfig({
userSync: {
userIds: [{ name: 'uid2', params: {...} }]
}
});
```

### Deferred Flow (this example)
```javascript
// Step 1: Page load - Prebid configured WITHOUT UID2
pbjs.setConfig({
userSync: {
syncDelay: 5000,
auctionDelay: 1000,
// Note: NO userIds configured here!
}
});

// Step 2: Later (after login, consent, etc.) - Add UID2 via mergeConfig
pbjs.mergeConfig({
userSync: {
userIds: [{
name: 'uid2',
params: {
uid2ApiBase: 'https://operator-integ.uidapi.com',
email: '[email protected]',
subscriptionId: 'your-subscription-id',
serverPublicKey: 'your-server-public-key'
}
}]
}
});

// Step 3: Trigger user ID refresh to generate the token
await pbjs.refreshUserIds();
```

## Key Prebid.js APIs

| API | Purpose |
|-----|---------|
| `pbjs.setConfig()` | Initial configuration (without UID2) |
| `pbjs.mergeConfig()` | Add/update configuration without replacing existing config |
| `pbjs.refreshUserIds()` | Trigger user ID module to fetch/generate new IDs |
| `pbjs.getUserIds()` | Get current user IDs (check if token was generated) |

## Live Examples

- **UID2**: [https://unifiedid.com/examples/cstg-prebid-deferred-example/](https://unifiedid.com/examples/cstg-prebid-deferred-example/)
- **EUID**: [https://euid.eu/examples/cstg-prebid-deferred-example/](https://euid.eu/examples/cstg-prebid-deferred-example/)
Copy link
Contributor

Choose a reason for hiding this comment

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

i dont think these URLs would be where the examples will live


## Running Locally

### Using Docker Compose (recommended)

From the repository root:

```bash
docker compose up prebid-client-side-deferred
```

Access at: http://localhost:3053

### Using the Reverse Proxy

```bash
docker compose up
```

Access at: http://prebid-deferred.sample-dev.com (requires hosts file configuration)

## Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `UID_CLIENT_BASE_URL` | API base URL for client-side calls | `https://operator-integ.uidapi.com` |
| `UID_CSTG_SUBSCRIPTION_ID` | Your CSTG subscription ID | Test value provided |
| `UID_CSTG_SERVER_PUBLIC_KEY` | Your CSTG server public key | Test value provided |
| `UID_STORAGE_KEY` | localStorage key for token storage | `__uid2_advertising_token` |
| `IDENTITY_NAME` | Display name (UID2 or EUID) | `UID2` |
| `DOCS_BASE_URL` | Base URL for documentation links | `https://unifiedid.com/docs` |

## Testing Flow

1. **Page loads** - Observe that Prebid is loaded but UID2 shows "Not yet configured (deferred)"
2. **Enter email** - Type an email address in the input field
3. **Click "Configure UID2 with mergeConfig()"** - This triggers:
- `pbjs.mergeConfig()` to add UID2 configuration
- `pbjs.refreshUserIds()` to generate the token
4. **Observe results** - Token appears in the status tables
5. **Test opt-out** - Use `[email protected]` to see opt-out behavior

## Documentation

- [UID2 Client-Side Integration Guide for Prebid.js](https://unifiedid.com/docs/guides/integration-prebid-client-side)
- [EUID Client-Side Integration Guide for Prebid.js](https://euid.eu/docs/guides/integration-prebid-client-side)
- [Prebid.js User ID Module](https://docs.prebid.org/dev-docs/modules/userId.html)
- [Prebid.js setConfig/mergeConfig](https://docs.prebid.org/dev-docs/publisher-api-reference/setConfig.html)
Copy link
Contributor

Choose a reason for hiding this comment

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

setConfig and mergeConfig have different prebid docs references, merge config would be here https://docs.prebid.org/dev-docs/publisher-api-reference/mergeConfig.html


## Related Examples

- [client-side](../client-side/) - Standard Prebid + UID2 (configured on page load)
- [client-server](../client-server/) - Server-side token generation with Prebid

Loading