prebid.js 7.52.0 → 7.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/1plusXRtdProvider.js +1 -1
- package/dist/33acrossBidAdapter.js +1 -1
- package/dist/33acrossIdSystem.js +1 -1
- package/dist/adagioBidAdapter.js +1 -1
- package/dist/adbookpspBidAdapter.js +1 -1
- package/dist/adgenerationBidAdapter.js +1 -1
- package/dist/adkernelBidAdapter.js +1 -1
- package/dist/adqueryBidAdapter.js +1 -1
- package/dist/adrelevantisBidAdapter.js +1 -1
- package/dist/adtrgtmeBidAdapter.js +1 -1
- package/dist/adxcgBidAdapter.js +1 -1
- package/dist/adyoulikeBidAdapter.js +1 -1
- package/dist/airgridRtdProvider.js +1 -1
- package/dist/ajaBidAdapter.js +1 -1
- package/dist/amxBidAdapter.js +1 -1
- package/dist/amxIdSystem.js +1 -1
- package/dist/appierAnalyticsAdapter.js +1 -1
- package/dist/appnexusBidAdapter.js +1 -1
- package/dist/asoBidAdapter.js +1 -1
- package/dist/axonixBidAdapter.js +1 -1
- package/dist/beopBidAdapter.js +1 -1
- package/dist/bidglassBidAdapter.js +1 -1
- package/dist/big-richmediaBidAdapter.js +1 -1
- package/dist/bridgewellBidAdapter.js +1 -1
- package/dist/brightMountainMediaBidAdapter.js +1 -1
- package/dist/carodaBidAdapter.js +1 -1
- package/dist/chtnwBidAdapter.js +1 -1
- package/dist/conceptxBidAdapter.js +1 -0
- package/dist/concertBidAdapter.js +1 -1
- package/dist/connectadBidAdapter.js +1 -1
- package/dist/consumableBidAdapter.js +1 -1
- package/dist/conversantAnalyticsAdapter.js +1 -1
- package/dist/conversantBidAdapter.js +1 -1
- package/dist/craftBidAdapter.js +1 -1
- package/dist/criteoBidAdapter.js +1 -1
- package/dist/cwireBidAdapter.js +1 -1
- package/dist/dspxBidAdapter.js +1 -1
- package/dist/eplanningBidAdapter.js +1 -1
- package/dist/eskimiBidAdapter.js +1 -1
- package/dist/euidIdSystem.js +1 -0
- package/dist/feedadBidAdapter.js +1 -1
- package/dist/finativeBidAdapter.js +1 -1
- package/dist/freepassIdSystem.js +1 -0
- package/dist/freewheel-sspBidAdapter.js +1 -1
- package/dist/glimpseBidAdapter.js +1 -1
- package/dist/gmosspBidAdapter.js +1 -1
- package/dist/goldbachBidAdapter.js +1 -1
- package/dist/greenbidsAnalyticsAdapter.js +1 -1
- package/dist/greenbidsRtdProvider.js +1 -1
- package/dist/gridBidAdapter.js +1 -1
- package/dist/gumgumBidAdapter.js +1 -1
- package/dist/h12mediaBidAdapter.js +1 -1
- package/dist/id5IdSystem.js +1 -1
- package/dist/improvedigitalBidAdapter.js +1 -1
- package/dist/inmarBidAdapter.js +1 -1
- package/dist/insticatorBidAdapter.js +1 -1
- package/dist/ixBidAdapter.js +1 -1
- package/dist/justpremiumBidAdapter.js +1 -1
- package/dist/kargoBidAdapter.js +1 -1
- package/dist/konduitAnalyticsAdapter.js +1 -1
- package/dist/kueezBidAdapter.js +1 -1
- package/dist/kueezRtbBidAdapter.js +1 -1
- package/dist/kulturemediaBidAdapter.js +1 -1
- package/dist/lassoBidAdapter.js +1 -1
- package/dist/lifestreetBidAdapter.js +1 -1
- package/dist/limelightDigitalBidAdapter.js +1 -1
- package/dist/liveyieldAnalyticsAdapter.js +1 -1
- package/dist/logicadBidAdapter.js +1 -1
- package/dist/loglyliftBidAdapter.js +1 -1
- package/dist/magniteAnalyticsAdapter.js +1 -1
- package/dist/malltvAnalyticsAdapter.js +1 -1
- package/dist/marsmediaBidAdapter.js +1 -1
- package/dist/mediafuseBidAdapter.js +1 -1
- package/dist/mediasquareBidAdapter.js +1 -1
- package/dist/mgidBidAdapter.js +1 -1
- package/dist/minutemediaBidAdapter.js +1 -1
- package/dist/minutemediaplusBidAdapter.js +1 -1
- package/dist/nexx360BidAdapter.js +1 -1
- package/dist/not-for-prod/prebid.js +146 -142
- package/dist/oguryBidAdapter.js +1 -1
- package/dist/onetagBidAdapter.js +1 -1
- package/dist/ooloAnalyticsAdapter.js +1 -1
- package/dist/optidigitalBidAdapter.js +1 -1
- package/dist/outbrainBidAdapter.js +1 -1
- package/dist/pairIdSystem.js +1 -1
- package/dist/parrableIdSystem.js +1 -1
- package/dist/pixfutureBidAdapter.js +1 -1
- package/dist/prebid-core.js +1 -1
- package/dist/proxistoreBidAdapter.js +1 -1
- package/dist/publinkIdSystem.js +1 -1
- package/dist/pubmaticBidAdapter.js +1 -1
- package/dist/pubwiseAnalyticsAdapter.js +1 -1
- package/dist/pxyzBidAdapter.js +1 -1
- package/dist/quantcastBidAdapter.js +1 -1
- package/dist/readpeakBidAdapter.js +1 -1
- package/dist/relaidoBidAdapter.js +1 -1
- package/dist/retailspotBidAdapter.js +1 -1
- package/dist/rhythmoneBidAdapter.js +1 -1
- package/dist/richaudienceBidAdapter.js +1 -1
- package/dist/riseBidAdapter.js +1 -1
- package/dist/rubiconAnalyticsAdapter.js +1 -1
- package/dist/rubiconBidAdapter.js +1 -1
- package/dist/schain.js +1 -1
- package/dist/seedingAllianceBidAdapter.js +1 -1
- package/dist/seedtagBidAdapter.js +1 -1
- package/dist/sharethroughAnalyticsAdapter.js +1 -1
- package/dist/sharethroughBidAdapter.js +1 -1
- package/dist/shinezBidAdapter.js +1 -1
- package/dist/sirdataRtdProvider.js +1 -1
- package/dist/smaatoBidAdapter.js +1 -1
- package/dist/smartadserverBidAdapter.js +1 -1
- package/dist/smartxBidAdapter.js +1 -1
- package/dist/smilewantedBidAdapter.js +1 -1
- package/dist/sonobiBidAdapter.js +1 -1
- package/dist/sovrnAnalyticsAdapter.js +1 -1
- package/dist/sovrnBidAdapter.js +1 -1
- package/dist/sspBCBidAdapter.js +1 -1
- package/dist/stroeerCoreBidAdapter.js +1 -1
- package/dist/stvBidAdapter.js +1 -1
- package/dist/sublimeBidAdapter.js +1 -1
- package/dist/synacormediaBidAdapter.js +1 -1
- package/dist/targetVideoBidAdapter.js +1 -1
- package/dist/teadsBidAdapter.js +1 -1
- package/dist/trionBidAdapter.js +1 -1
- package/dist/tripleliftBidAdapter.js +1 -1
- package/dist/ttdBidAdapter.js +1 -1
- package/dist/ucfunnelAnalyticsAdapter.js +1 -1
- package/dist/uid2IdSystem.js +1 -1
- package/dist/uid2IdSystem_shared.js +1 -0
- package/dist/underdogmediaBidAdapter.js +1 -1
- package/dist/undertoneBidAdapter.js +1 -1
- package/dist/userId.js +1 -1
- package/dist/vidazooBidAdapter.js +1 -1
- package/dist/videobyteBidAdapter.js +1 -1
- package/dist/viouslyBidAdapter.js +1 -1
- package/dist/visxBidAdapter.js +1 -1
- package/dist/vuukleBidAdapter.js +1 -1
- package/dist/weboramaRtdProvider.js +1 -1
- package/dist/widespaceBidAdapter.js +1 -1
- package/dist/winrBidAdapter.js +1 -1
- package/dist/yahoosspBidAdapter.js +1 -1
- package/dist/yieldlabBidAdapter.js +1 -1
- package/dist/yieldmoBidAdapter.js +1 -1
- package/dist/yieldoneAnalyticsAdapter.js +1 -1
- package/dist/zeta_global_sspBidAdapter.js +1 -1
- package/integrationExamples/gpt/userId_example.html +20 -6
- package/modules/.submodules.json +3 -1
- package/modules/1plusXRtdProvider.js +31 -60
- package/modules/adagioBidAdapter.js +86 -24
- package/modules/adkernelBidAdapter.js +2 -2
- package/modules/airgridRtdProvider.js +11 -12
- package/modules/asoBidAdapter.js +2 -1
- package/modules/beopBidAdapter.js +6 -0
- package/modules/conceptxBidAdapter.js +70 -0
- package/modules/conceptxBidAdapter.md +36 -0
- package/modules/criteoBidAdapter.js +9 -2
- package/modules/eskimiBidAdapter.js +171 -41
- package/modules/eskimiBidAdapter.md +35 -16
- package/modules/euidIdSystem.js +121 -0
- package/modules/euidIdSystem.md +131 -0
- package/modules/freepassIdSystem.js +61 -0
- package/modules/freepassIdSystem.md +47 -0
- package/modules/greenbidsAnalyticsAdapter.js +1 -1
- package/modules/id5IdSystem.js +3 -5
- package/modules/ixBidAdapter.js +12 -1
- package/modules/limelightDigitalBidAdapter.js +1 -1
- package/modules/logicadBidAdapter.js +14 -1
- package/modules/mediasquareBidAdapter.js +13 -5
- package/modules/nexx360BidAdapter.js +1 -0
- package/modules/pairIdSystem.js +10 -5
- package/modules/proxistoreBidAdapter.js +11 -14
- package/modules/richaudienceBidAdapter.js +10 -1
- package/modules/riseBidAdapter.js +1 -1
- package/modules/schain.js +2 -2
- package/modules/sirdataRtdProvider.js +73 -146
- package/modules/sovrnBidAdapter.js +4 -1
- package/modules/stroeerCoreBidAdapter.js +55 -6
- package/modules/uid2IdSystem.js +27 -210
- package/modules/uid2IdSystem.md +104 -23
- package/modules/uid2IdSystem_shared.js +232 -0
- package/modules/userId/eids.js +8 -0
- package/modules/userId/userId.md +2 -1
- package/modules/viouslyBidAdapter.js +2 -2
- package/modules/weboramaRtdProvider.js +25 -95
- package/modules/weboramaRtdProvider.md +4 -4
- package/modules/yieldlabBidAdapter.js +23 -14
- package/modules/zeta_global_sspBidAdapter.js +27 -22
- package/package.json +1 -1
- package/src/adloader.js +1 -0
- package/test/spec/modules/1plusXRtdProvider_spec.js +98 -149
- package/test/spec/modules/adagioBidAdapter_spec.js +46 -17
- package/test/spec/modules/airgridRtdProvider_spec.js +2 -0
- package/test/spec/modules/beopBidAdapter_spec.js +24 -0
- package/test/spec/modules/conceptxBidAdapter_spec.js +136 -0
- package/test/spec/modules/criteoBidAdapter_spec.js +1 -1
- package/test/spec/modules/eids_spec.js +15 -0
- package/test/spec/modules/eskimiBidAdapter_spec.js +264 -112
- package/test/spec/modules/euidIdSystem_spec.js +130 -0
- package/test/spec/modules/freepassIdSystem_spec.js +186 -0
- package/test/spec/modules/id5IdSystem_spec.js +10 -3
- package/test/spec/modules/ixBidAdapter_spec.js +30 -0
- package/test/spec/modules/logicadBidAdapter_spec.js +122 -2
- package/test/spec/modules/mediasquareBidAdapter_spec.js +4 -0
- package/test/spec/modules/richaudienceBidAdapter_spec.js +44 -0
- package/test/spec/modules/schain_spec.js +9 -0
- package/test/spec/modules/sirdataRtdProvider_spec.js +110 -17
- package/test/spec/modules/sovrnBidAdapter_spec.js +13 -0
- package/test/spec/modules/stroeerCoreBidAdapter_spec.js +151 -6
- package/test/spec/modules/uid2IdSystem_helpers.js +70 -0
- package/test/spec/modules/uid2IdSystem_spec.js +131 -86
- package/test/spec/modules/userId_spec.js +16 -12
- package/test/spec/modules/weboramaRtdProvider_spec.js +331 -205
- package/test/spec/modules/yieldlabBidAdapter_spec.js +42 -2
- package/test/spec/modules/zeta_global_sspBidAdapter_spec.js +200 -4
package/modules/uid2IdSystem.js
CHANGED
|
@@ -6,16 +6,19 @@
|
|
|
6
6
|
* @requires module:modules/userId
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { logInfo } from '../src/utils.js';
|
|
9
|
+
import { logInfo, logWarn } from '../src/utils.js';
|
|
10
10
|
import {submodule} from '../src/hook.js';
|
|
11
11
|
import {getStorageManager} from '../src/storageManager.js';
|
|
12
12
|
import {MODULE_TYPE_UID} from '../src/activities/modules.js';
|
|
13
13
|
|
|
14
|
+
// RE below lint exception: UID2 and EUID are separate modules, but the protocol is the same and shared code makes sense here.
|
|
15
|
+
// eslint-disable-next-line prebid/validate-imports
|
|
16
|
+
import { Uid2GetId, Uid2CodeVersion } from './uid2IdSystem_shared.js';
|
|
17
|
+
|
|
14
18
|
const MODULE_NAME = 'uid2';
|
|
15
|
-
const MODULE_REVISION =
|
|
19
|
+
const MODULE_REVISION = Uid2CodeVersion;
|
|
16
20
|
const PREBID_VERSION = '$prebid.version$';
|
|
17
21
|
const UID2_CLIENT_ID = `PrebidJS-${PREBID_VERSION}-UID2Module-${MODULE_REVISION}`;
|
|
18
|
-
const GVLID = 887;
|
|
19
22
|
const LOG_PRE_FIX = 'UID2: ';
|
|
20
23
|
const ADVERTISING_COOKIE = '__uid2_advertising_token';
|
|
21
24
|
|
|
@@ -24,131 +27,15 @@ const UID2_TEST_URL = 'https://operator-integ.uidapi.com';
|
|
|
24
27
|
const UID2_PROD_URL = 'https://prod.uidapi.com';
|
|
25
28
|
const UID2_BASE_URL = UID2_PROD_URL;
|
|
26
29
|
|
|
27
|
-
function
|
|
28
|
-
return getStorageManager({moduleType: MODULE_TYPE_UID, moduleName: MODULE_NAME});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function createLogInfo(prefix) {
|
|
30
|
+
function createLogger(logger, prefix) {
|
|
32
31
|
return function (...strings) {
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
export const storage = getStorage();
|
|
37
|
-
const _logInfo = createLogInfo(LOG_PRE_FIX);
|
|
38
|
-
|
|
39
|
-
function readFromLocalStorage() {
|
|
40
|
-
return storage.localStorageIsEnabled() ? storage.getDataFromLocalStorage(ADVERTISING_COOKIE) : null;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function readModuleCookie() {
|
|
44
|
-
const cookie = readCookie(ADVERTISING_COOKIE);
|
|
45
|
-
if (cookie && cookie.includes('{')) {
|
|
46
|
-
return JSON.parse(cookie);
|
|
32
|
+
logger(prefix + ' ', ...strings);
|
|
47
33
|
}
|
|
48
|
-
return cookie;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function readJsonCookie(cookieName) {
|
|
52
|
-
return JSON.parse(readCookie(cookieName));
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function readCookie(cookieName) {
|
|
56
|
-
const cookie = storage.cookiesAreEnabled() ? storage.getCookie(cookieName) : null;
|
|
57
|
-
if (!cookie) {
|
|
58
|
-
_logInfo(`Attempted to read UID2 from cookie '${cookieName}' but it was empty`);
|
|
59
|
-
return null;
|
|
60
|
-
};
|
|
61
|
-
_logInfo(`Read UID2 from cookie '${cookieName}'`);
|
|
62
|
-
return cookie;
|
|
63
34
|
}
|
|
35
|
+
const _logInfo = createLogger(logInfo, LOG_PRE_FIX);
|
|
36
|
+
const _logWarn = createLogger(logWarn, LOG_PRE_FIX);
|
|
64
37
|
|
|
65
|
-
|
|
66
|
-
if (storage.cookiesAreEnabled()) {
|
|
67
|
-
storage.setCookie(ADVERTISING_COOKIE, JSON.stringify(value), Date.now() + 60 * 60 * 24 * 1000);
|
|
68
|
-
} else if (storage.localStorageIsEnabled()) {
|
|
69
|
-
storage.setLocalStorage(ADVERTISING_COOKIE, value);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function isValidIdentity(identity) {
|
|
74
|
-
return !!(typeof identity === 'object' && identity !== null && identity.advertising_token && identity.identity_expires && identity.refresh_from && identity.refresh_token && identity.refresh_expires);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// This is extracted from an in-progress API client. Once it's available via NPM, this class should be replaced with the NPM package.
|
|
78
|
-
class Uid2ApiClient {
|
|
79
|
-
constructor(opts) {
|
|
80
|
-
this._baseUrl = opts.baseUrl ? opts.baseUrl : UID2_BASE_URL;
|
|
81
|
-
this._clientVersion = UID2_CLIENT_ID;
|
|
82
|
-
}
|
|
83
|
-
createArrayBuffer(text) {
|
|
84
|
-
const arrayBuffer = new Uint8Array(text.length);
|
|
85
|
-
for (let i = 0; i < text.length; i++) {
|
|
86
|
-
arrayBuffer[i] = text.charCodeAt(i);
|
|
87
|
-
}
|
|
88
|
-
return arrayBuffer;
|
|
89
|
-
}
|
|
90
|
-
hasStatusResponse(response) {
|
|
91
|
-
return typeof (response) === 'object' && response && response.status;
|
|
92
|
-
}
|
|
93
|
-
isValidRefreshResponse(response) {
|
|
94
|
-
return this.hasStatusResponse(response) && (
|
|
95
|
-
response.status === 'optout' || response.status === 'expired_token' || (response.status === 'success' && response.body && isValidIdentity(response.body))
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
ResponseToRefreshResult(response) {
|
|
99
|
-
if (this.isValidRefreshResponse(response)) {
|
|
100
|
-
if (response.status === 'success') { return { status: response.status, identity: response.body }; }
|
|
101
|
-
return response;
|
|
102
|
-
} else { return "Response didn't contain a valid status"; }
|
|
103
|
-
}
|
|
104
|
-
callRefreshApi(refreshDetails) {
|
|
105
|
-
const url = this._baseUrl + '/v2/token/refresh';
|
|
106
|
-
const req = new XMLHttpRequest();
|
|
107
|
-
req.overrideMimeType('text/plain');
|
|
108
|
-
req.open('POST', url, true);
|
|
109
|
-
req.setRequestHeader('X-UID2-Client-Version', this._clientVersion);
|
|
110
|
-
let resolvePromise;
|
|
111
|
-
let rejectPromise;
|
|
112
|
-
const promise = new Promise((resolve, reject) => {
|
|
113
|
-
resolvePromise = resolve;
|
|
114
|
-
rejectPromise = reject;
|
|
115
|
-
});
|
|
116
|
-
req.onreadystatechange = () => {
|
|
117
|
-
if (req.readyState !== req.DONE) { return; }
|
|
118
|
-
try {
|
|
119
|
-
if (!refreshDetails.refresh_response_key || req.status !== 200) {
|
|
120
|
-
_logInfo('Error status OR no response decryption key available, assuming unencrypted JSON');
|
|
121
|
-
const response = JSON.parse(req.responseText);
|
|
122
|
-
const result = this.ResponseToRefreshResult(response);
|
|
123
|
-
if (typeof result === 'string') { rejectPromise(result); } else { resolvePromise(result); }
|
|
124
|
-
} else {
|
|
125
|
-
_logInfo('Decrypting refresh API response');
|
|
126
|
-
const encodeResp = this.createArrayBuffer(atob(req.responseText));
|
|
127
|
-
window.crypto.subtle.importKey('raw', this.createArrayBuffer(atob(refreshDetails.refresh_response_key)), { name: 'AES-GCM' }, false, ['decrypt']).then((key) => {
|
|
128
|
-
_logInfo('Imported decryption key')
|
|
129
|
-
// returns the symmetric key
|
|
130
|
-
window.crypto.subtle.decrypt({
|
|
131
|
-
name: 'AES-GCM',
|
|
132
|
-
iv: encodeResp.slice(0, 12),
|
|
133
|
-
tagLength: 128, // The tagLength you used to encrypt (if any)
|
|
134
|
-
}, key, encodeResp.slice(12)).then((decrypted) => {
|
|
135
|
-
const decryptedResponse = String.fromCharCode(...new Uint8Array(decrypted));
|
|
136
|
-
_logInfo('Decrypted to:', decryptedResponse);
|
|
137
|
-
const response = JSON.parse(decryptedResponse);
|
|
138
|
-
const result = this.ResponseToRefreshResult(response);
|
|
139
|
-
if (typeof result === 'string') { rejectPromise(result); } else { resolvePromise(result); }
|
|
140
|
-
}, (reason) => console.warn(`Call to UID2 API failed`, reason));
|
|
141
|
-
}, (reason) => console.warn(`Call to UID2 API failed`, reason));
|
|
142
|
-
}
|
|
143
|
-
} catch (err) {
|
|
144
|
-
rejectPromise(err);
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
_logInfo('Sending refresh request', req);
|
|
148
|
-
req.send(refreshDetails.refresh_token);
|
|
149
|
-
return promise;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
38
|
+
export const storage = getStorageManager({moduleType: MODULE_TYPE_UID, moduleName: MODULE_NAME});
|
|
152
39
|
|
|
153
40
|
/** @type {Submodule} */
|
|
154
41
|
export const uid2IdSubmodule = {
|
|
@@ -158,11 +45,6 @@ export const uid2IdSubmodule = {
|
|
|
158
45
|
*/
|
|
159
46
|
name: MODULE_NAME,
|
|
160
47
|
|
|
161
|
-
/**
|
|
162
|
-
* Vendor id of Prebid
|
|
163
|
-
* @type {Number}
|
|
164
|
-
*/
|
|
165
|
-
gvlid: GVLID,
|
|
166
48
|
/**
|
|
167
49
|
* decode the stored id value for passing to bid requests
|
|
168
50
|
* @function
|
|
@@ -183,29 +65,29 @@ export const uid2IdSubmodule = {
|
|
|
183
65
|
* @returns {uid2Id}
|
|
184
66
|
*/
|
|
185
67
|
getId(config, consentData) {
|
|
186
|
-
|
|
68
|
+
if (consentData?.gdprApplies === true) {
|
|
69
|
+
_logWarn('UID2 is not intended for use where GDPR applies. The UID2 module will not run.');
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const mappedConfig = {
|
|
74
|
+
apiBaseUrl: config?.params?.uid2ApiBase ?? UID2_BASE_URL,
|
|
75
|
+
paramToken: config?.params?.uid2Token,
|
|
76
|
+
serverCookieName: config?.params?.uid2Cookie ?? config?.params?.uid2ServerCookie,
|
|
77
|
+
storage: config?.params?.storage ?? 'localStorage',
|
|
78
|
+
clientId: UID2_CLIENT_ID,
|
|
79
|
+
internalStorage: ADVERTISING_COOKIE
|
|
80
|
+
}
|
|
81
|
+
_logInfo(`UID2 configuration loaded and mapped.`, mappedConfig);
|
|
82
|
+
const result = Uid2GetId(mappedConfig, storage, _logInfo, _logWarn);
|
|
187
83
|
_logInfo(`UID2 getId returned`, result);
|
|
188
84
|
return result;
|
|
189
85
|
},
|
|
190
86
|
};
|
|
191
87
|
|
|
192
|
-
function refreshTokenAndStore(baseUrl, token) {
|
|
193
|
-
_logInfo('UID2 base url provided: ', baseUrl);
|
|
194
|
-
const client = new Uid2ApiClient({baseUrl});
|
|
195
|
-
return client.callRefreshApi(token).then((response) => {
|
|
196
|
-
_logInfo('Refresh endpoint responded with:', response);
|
|
197
|
-
const tokens = {
|
|
198
|
-
originalToken: token,
|
|
199
|
-
latestToken: response.identity,
|
|
200
|
-
};
|
|
201
|
-
storeValue(tokens);
|
|
202
|
-
return tokens;
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
|
|
206
88
|
function decodeImpl(value) {
|
|
207
89
|
if (typeof value === 'string') {
|
|
208
|
-
_logInfo('Found
|
|
90
|
+
_logInfo('Found server-only token. Refresh is unavailable for this token.');
|
|
209
91
|
const result = { uid2: { id: value } };
|
|
210
92
|
return result;
|
|
211
93
|
}
|
|
@@ -215,70 +97,5 @@ function decodeImpl(value) {
|
|
|
215
97
|
return null;
|
|
216
98
|
}
|
|
217
99
|
|
|
218
|
-
function getIdImpl(config, consentData) {
|
|
219
|
-
let suppliedToken = null;
|
|
220
|
-
const uid2BaseUrl = config?.params?.uid2ApiBase ?? UID2_BASE_URL;
|
|
221
|
-
if (config && config.params) {
|
|
222
|
-
if (config.params.uid2Token) {
|
|
223
|
-
suppliedToken = config.params.uid2Token;
|
|
224
|
-
_logInfo('Read token from params', suppliedToken);
|
|
225
|
-
} else if (config.params.uid2ServerCookie) {
|
|
226
|
-
suppliedToken = readJsonCookie(config.params.uid2ServerCookie);
|
|
227
|
-
_logInfo('Read token from server-supplied cookie', suppliedToken);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
let storedTokens = readModuleCookie() || readFromLocalStorage();
|
|
231
|
-
_logInfo('Loaded module-stored tokens:', storedTokens);
|
|
232
|
-
|
|
233
|
-
if (storedTokens && typeof storedTokens === 'string') {
|
|
234
|
-
// Legacy value stored, this must be from an old integration. If no token supplied, just use the legacy value.
|
|
235
|
-
|
|
236
|
-
if (!suppliedToken) {
|
|
237
|
-
_logInfo('Returning legacy cookie value.');
|
|
238
|
-
return { id: storedTokens };
|
|
239
|
-
}
|
|
240
|
-
// Otherwise, ignore the legacy value - it should get over-written later anyway.
|
|
241
|
-
_logInfo('Discarding superseded legacy cookie.');
|
|
242
|
-
storedTokens = null;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
if (suppliedToken && storedTokens) {
|
|
246
|
-
if (storedTokens.originalToken?.advertising_token !== suppliedToken.advertising_token) {
|
|
247
|
-
_logInfo('Server supplied new token - ignoring stored value.', storedTokens.originalToken?.advertising_token, suppliedToken.advertising_token);
|
|
248
|
-
// Stored token wasn't originally sourced from the provided token - ignore the stored value. A new user has logged in?
|
|
249
|
-
storedTokens = null;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
// At this point, any legacy values or superseded stored tokens have been nulled out.
|
|
253
|
-
const useSuppliedToken = !(storedTokens?.latestToken) || (suppliedToken && suppliedToken.identity_expires > storedTokens.latestToken.identity_expires);
|
|
254
|
-
const newestAvailableToken = useSuppliedToken ? suppliedToken : storedTokens.latestToken;
|
|
255
|
-
_logInfo('UID2 module selected latest token', useSuppliedToken, newestAvailableToken);
|
|
256
|
-
if (!newestAvailableToken || Date.now() > newestAvailableToken.refresh_expires) {
|
|
257
|
-
_logInfo('Newest available token is expired and not refreshable.');
|
|
258
|
-
return { id: null };
|
|
259
|
-
}
|
|
260
|
-
if (Date.now() > newestAvailableToken.identity_expires) {
|
|
261
|
-
const promise = refreshTokenAndStore(uid2BaseUrl, newestAvailableToken);
|
|
262
|
-
_logInfo('Token is expired but can be refreshed, attempting refresh.');
|
|
263
|
-
return { callback: (cb) => {
|
|
264
|
-
promise.then((result) => {
|
|
265
|
-
_logInfo('Refresh reponded, passing the updated token on.', result);
|
|
266
|
-
cb(result);
|
|
267
|
-
});
|
|
268
|
-
} };
|
|
269
|
-
}
|
|
270
|
-
// If should refresh (but don't need to), refresh in the background.
|
|
271
|
-
if (Date.now() > newestAvailableToken.refresh_from) {
|
|
272
|
-
_logInfo(`Refreshing token in background with low priority.`);
|
|
273
|
-
refreshTokenAndStore(uid2BaseUrl, newestAvailableToken);
|
|
274
|
-
}
|
|
275
|
-
const tokens = {
|
|
276
|
-
originalToken: suppliedToken ?? storedTokens?.originalToken,
|
|
277
|
-
latestToken: newestAvailableToken,
|
|
278
|
-
};
|
|
279
|
-
storeValue(tokens);
|
|
280
|
-
return { id: tokens };
|
|
281
|
-
}
|
|
282
|
-
|
|
283
100
|
// Register submodule for userId
|
|
284
101
|
submodule('userId', uid2IdSubmodule);
|
package/modules/uid2IdSystem.md
CHANGED
|
@@ -1,25 +1,56 @@
|
|
|
1
|
-
##
|
|
1
|
+
## UID2 User ID Submodule
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
UID2 requires initial tokens to be generated server-side. The UID2 module handles storing, providing, and optionally refreshing them. The module can operate in one of two different modes: *Client Refresh* mode or *Server Only* mode.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
*Server Only* mode was originally referred to as *legacy mode*, but it is a popular mode for new integrations where publishers prefer to handle token refresh server-side.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**Important information:** UID2 is not designed to be used where GDPR applies. The module checks the passed-in consent data and will not operate if the `gdprApplies` flag is true.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Client Refresh mode
|
|
10
10
|
|
|
11
|
+
This is the recommended mode for most scenarios. In this mode, the full response body from the UID2 Token Generate or Token Refresh endpoint must be provided to the module. As long as the refresh token remains valid, the module will refresh the advertising token as needed.
|
|
12
|
+
|
|
13
|
+
To configure the module to use this mode, you must **either**:
|
|
14
|
+
1. Set `params.uid2Cookie` to the name of the cookie which contains the response body as a JSON string, **or**
|
|
15
|
+
2. Set `params.uid2Token` to the response body as a JavaScript object.
|
|
16
|
+
|
|
17
|
+
The `uid2Cookie` param was originally `uid2ServerCookie`. The old name can still be used, however the inclusion of the word 'server' was causing some confusion. If both values are provided, `uid2ServerCookie` will be ignored.
|
|
18
|
+
|
|
19
|
+
### Client refresh cookie example
|
|
20
|
+
|
|
21
|
+
In this example, the cookie is called `uid2_pub_cookie`.
|
|
22
|
+
|
|
23
|
+
Cookie:
|
|
24
|
+
```
|
|
25
|
+
uid2_pub_cookie={"advertising_token":"...advertising token...","refresh_token":"...refresh token...","identity_expires":1684741472161,"refresh_from":1684741425653,"refresh_expires":1684784643668,"refresh_response_key":"...response key..."}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Configuration:
|
|
29
|
+
```
|
|
30
|
+
pbjs.setConfig({
|
|
31
|
+
userSync: {
|
|
32
|
+
userIds: [{
|
|
33
|
+
name: 'uid2',
|
|
34
|
+
params: {
|
|
35
|
+
uid2Cookie: 'uid2_pub_cookie'
|
|
36
|
+
}
|
|
37
|
+
}]
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Client refresh uid2Token example
|
|
43
|
+
|
|
44
|
+
Configuration:
|
|
11
45
|
```
|
|
12
46
|
pbjs.setConfig({
|
|
13
47
|
userSync: {
|
|
14
48
|
userIds: [{
|
|
15
49
|
name: 'uid2',
|
|
16
50
|
params: {
|
|
17
|
-
// Either:
|
|
18
|
-
uid2ServerCookie: 'your_UID2_server_set_cookie_name'
|
|
19
|
-
// Or:
|
|
20
51
|
uid2Token: {
|
|
21
|
-
'advertising_token': '...',
|
|
22
|
-
'refresh_token': '...',
|
|
52
|
+
'advertising_token': '...advertising token...',
|
|
53
|
+
'refresh_token': '...refresh token...',
|
|
23
54
|
// etc. - see the Sample Token below for contents of this object
|
|
24
55
|
}
|
|
25
56
|
}
|
|
@@ -27,28 +58,78 @@ pbjs.setConfig({
|
|
|
27
58
|
}
|
|
28
59
|
});
|
|
29
60
|
```
|
|
30
|
-
## Parameter Descriptions for the `usersync` Configuration Section
|
|
31
|
-
The below parameters apply only to the UID 2.0 User ID Module integration.
|
|
32
61
|
|
|
33
|
-
|
|
62
|
+
## Server-Only Mode
|
|
34
63
|
|
|
35
|
-
|
|
64
|
+
In this mode, only the advertising token is provided to the module. The module will not be able to refresh the token. The publisher is responsible for implementing some other way to refresh the token.
|
|
36
65
|
|
|
37
|
-
|
|
66
|
+
To configure the module to use this mode, you must **either**:
|
|
67
|
+
1. Set a cookie named `__uid2_advertising_token` to the advertising token, **or**
|
|
68
|
+
2. Set `value` to an ID block containing the advertising token (see "Server only value" example below).
|
|
38
69
|
|
|
39
|
-
|
|
70
|
+
### Server only cookie example
|
|
40
71
|
|
|
41
|
-
|
|
72
|
+
Cookie:
|
|
73
|
+
```
|
|
74
|
+
__uid2_advertising_token=...advertising token...
|
|
75
|
+
```
|
|
42
76
|
|
|
43
|
-
|
|
77
|
+
Configuration:
|
|
78
|
+
```
|
|
79
|
+
pbjs.setConfig({
|
|
80
|
+
userSync: {
|
|
81
|
+
userIds: [{
|
|
82
|
+
name: 'uid2'
|
|
83
|
+
}]
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Server only value example
|
|
89
|
+
|
|
90
|
+
Configuration:
|
|
91
|
+
```
|
|
92
|
+
pbjs.setConfig({
|
|
93
|
+
userSync: {
|
|
94
|
+
userIds: [{
|
|
95
|
+
name: 'uid2'
|
|
96
|
+
value: {
|
|
97
|
+
'uid2': {
|
|
98
|
+
'id': '...advertising token...'
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}]
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Storage
|
|
44
107
|
|
|
45
|
-
|
|
108
|
+
The module stores a number of internal values. By default, all values are stored in HTML5 local storage. You can switch to cookie storage by setting `params.storage` to `cookie`. The cookie size can be significant and this is not recommended, but is provided as an option if local storage is not an option.
|
|
109
|
+
|
|
110
|
+
## Sample token
|
|
46
111
|
|
|
47
112
|
`{`<br /> `"advertising_token": "...",`<br /> `"refresh_token": "...",`<br /> `"identity_expires": 1633643601000,`<br /> `"refresh_from": 1633643001000,`<br /> `"refresh_expires": 1636322000000,`<br /> `"refresh_response_key": "wR5t6HKMfJ2r4J7fEGX9Gw=="`<br />`}`
|
|
48
113
|
|
|
114
|
+
### Notes
|
|
115
|
+
|
|
116
|
+
If you are trying to limit the size of cookies, provide the token in configuration and use the default option of local storage.
|
|
117
|
+
|
|
118
|
+
If you provide an expired identity and the module has a valid identity which was refreshed from the identity you provide, it will use the refreshed identity. The module stores the original token used for refreshing the token, and it will use the refreshed tokens as long as the original token matches the one supplied.
|
|
119
|
+
|
|
120
|
+
If a new token is supplied which does not match the original token used to generate any refreshed tokens, all stored tokens will be discarded and the new token used instead (refreshed if necessary).
|
|
121
|
+
|
|
122
|
+
You can set `params.uid2ApiBase` to `"https://operator-integ.uidapi.com"` during integration testing. Be aware that you must use the same environment (production or integration) here as you use for generating tokens.
|
|
123
|
+
|
|
124
|
+
## Parameter Descriptions for the `usersync` Configuration Section
|
|
125
|
+
|
|
126
|
+
The below parameters apply only to the UID2 User ID Module integration.
|
|
127
|
+
|
|
49
128
|
| Param under userSync.userIds[] | Scope | Type | Description | Example |
|
|
50
129
|
| --- | --- | --- | --- | --- |
|
|
51
|
-
| name | Required | String | ID value for the
|
|
52
|
-
|
|
|
53
|
-
| params.
|
|
54
|
-
| params.
|
|
130
|
+
| name | Required | String | ID value for the UID2 module - `"uid2"` | `"uid2"` |
|
|
131
|
+
| value | Optional, Server only | Object | An object containing the value for the advertising token. | See the example above. |
|
|
132
|
+
| params.uid2Token | Optional, Client refresh | Object | The initial UID2 token. This should be `body` element of the decrypted response from a call to the `/token/generate` or `/token/refresh` endpoint. | See the sample token above. |
|
|
133
|
+
| params.uid2Cookie | Optional, Client refresh | String | The name of a cookie which holds the initial UID2 token, set by the server. The cookie should contain JSON in the same format as the uid2Token param. **If uid2Token is supplied, this param is ignored.** | See the sample token above. |
|
|
134
|
+
| params.uid2ApiBase | Optional, Client refresh | String | Overrides the default UID2 API endpoint. | `"https://prod.uidapi.com"` _(default)_|
|
|
135
|
+
| params.storage | Optional, Client refresh | String | Specify whether to use `cookie` or `localStorage` for module-internal storage. It is recommended to not provide this and allow the module to use the default. | `localStorage` _(default)_ |
|