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.
Files changed (214) hide show
  1. package/dist/1plusXRtdProvider.js +1 -1
  2. package/dist/33acrossBidAdapter.js +1 -1
  3. package/dist/33acrossIdSystem.js +1 -1
  4. package/dist/adagioBidAdapter.js +1 -1
  5. package/dist/adbookpspBidAdapter.js +1 -1
  6. package/dist/adgenerationBidAdapter.js +1 -1
  7. package/dist/adkernelBidAdapter.js +1 -1
  8. package/dist/adqueryBidAdapter.js +1 -1
  9. package/dist/adrelevantisBidAdapter.js +1 -1
  10. package/dist/adtrgtmeBidAdapter.js +1 -1
  11. package/dist/adxcgBidAdapter.js +1 -1
  12. package/dist/adyoulikeBidAdapter.js +1 -1
  13. package/dist/airgridRtdProvider.js +1 -1
  14. package/dist/ajaBidAdapter.js +1 -1
  15. package/dist/amxBidAdapter.js +1 -1
  16. package/dist/amxIdSystem.js +1 -1
  17. package/dist/appierAnalyticsAdapter.js +1 -1
  18. package/dist/appnexusBidAdapter.js +1 -1
  19. package/dist/asoBidAdapter.js +1 -1
  20. package/dist/axonixBidAdapter.js +1 -1
  21. package/dist/beopBidAdapter.js +1 -1
  22. package/dist/bidglassBidAdapter.js +1 -1
  23. package/dist/big-richmediaBidAdapter.js +1 -1
  24. package/dist/bridgewellBidAdapter.js +1 -1
  25. package/dist/brightMountainMediaBidAdapter.js +1 -1
  26. package/dist/carodaBidAdapter.js +1 -1
  27. package/dist/chtnwBidAdapter.js +1 -1
  28. package/dist/conceptxBidAdapter.js +1 -0
  29. package/dist/concertBidAdapter.js +1 -1
  30. package/dist/connectadBidAdapter.js +1 -1
  31. package/dist/consumableBidAdapter.js +1 -1
  32. package/dist/conversantAnalyticsAdapter.js +1 -1
  33. package/dist/conversantBidAdapter.js +1 -1
  34. package/dist/craftBidAdapter.js +1 -1
  35. package/dist/criteoBidAdapter.js +1 -1
  36. package/dist/cwireBidAdapter.js +1 -1
  37. package/dist/dspxBidAdapter.js +1 -1
  38. package/dist/eplanningBidAdapter.js +1 -1
  39. package/dist/eskimiBidAdapter.js +1 -1
  40. package/dist/euidIdSystem.js +1 -0
  41. package/dist/feedadBidAdapter.js +1 -1
  42. package/dist/finativeBidAdapter.js +1 -1
  43. package/dist/freepassIdSystem.js +1 -0
  44. package/dist/freewheel-sspBidAdapter.js +1 -1
  45. package/dist/glimpseBidAdapter.js +1 -1
  46. package/dist/gmosspBidAdapter.js +1 -1
  47. package/dist/goldbachBidAdapter.js +1 -1
  48. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  49. package/dist/greenbidsRtdProvider.js +1 -1
  50. package/dist/gridBidAdapter.js +1 -1
  51. package/dist/gumgumBidAdapter.js +1 -1
  52. package/dist/h12mediaBidAdapter.js +1 -1
  53. package/dist/id5IdSystem.js +1 -1
  54. package/dist/improvedigitalBidAdapter.js +1 -1
  55. package/dist/inmarBidAdapter.js +1 -1
  56. package/dist/insticatorBidAdapter.js +1 -1
  57. package/dist/ixBidAdapter.js +1 -1
  58. package/dist/justpremiumBidAdapter.js +1 -1
  59. package/dist/kargoBidAdapter.js +1 -1
  60. package/dist/konduitAnalyticsAdapter.js +1 -1
  61. package/dist/kueezBidAdapter.js +1 -1
  62. package/dist/kueezRtbBidAdapter.js +1 -1
  63. package/dist/kulturemediaBidAdapter.js +1 -1
  64. package/dist/lassoBidAdapter.js +1 -1
  65. package/dist/lifestreetBidAdapter.js +1 -1
  66. package/dist/limelightDigitalBidAdapter.js +1 -1
  67. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  68. package/dist/logicadBidAdapter.js +1 -1
  69. package/dist/loglyliftBidAdapter.js +1 -1
  70. package/dist/magniteAnalyticsAdapter.js +1 -1
  71. package/dist/malltvAnalyticsAdapter.js +1 -1
  72. package/dist/marsmediaBidAdapter.js +1 -1
  73. package/dist/mediafuseBidAdapter.js +1 -1
  74. package/dist/mediasquareBidAdapter.js +1 -1
  75. package/dist/mgidBidAdapter.js +1 -1
  76. package/dist/minutemediaBidAdapter.js +1 -1
  77. package/dist/minutemediaplusBidAdapter.js +1 -1
  78. package/dist/nexx360BidAdapter.js +1 -1
  79. package/dist/not-for-prod/prebid.js +146 -142
  80. package/dist/oguryBidAdapter.js +1 -1
  81. package/dist/onetagBidAdapter.js +1 -1
  82. package/dist/ooloAnalyticsAdapter.js +1 -1
  83. package/dist/optidigitalBidAdapter.js +1 -1
  84. package/dist/outbrainBidAdapter.js +1 -1
  85. package/dist/pairIdSystem.js +1 -1
  86. package/dist/parrableIdSystem.js +1 -1
  87. package/dist/pixfutureBidAdapter.js +1 -1
  88. package/dist/prebid-core.js +1 -1
  89. package/dist/proxistoreBidAdapter.js +1 -1
  90. package/dist/publinkIdSystem.js +1 -1
  91. package/dist/pubmaticBidAdapter.js +1 -1
  92. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  93. package/dist/pxyzBidAdapter.js +1 -1
  94. package/dist/quantcastBidAdapter.js +1 -1
  95. package/dist/readpeakBidAdapter.js +1 -1
  96. package/dist/relaidoBidAdapter.js +1 -1
  97. package/dist/retailspotBidAdapter.js +1 -1
  98. package/dist/rhythmoneBidAdapter.js +1 -1
  99. package/dist/richaudienceBidAdapter.js +1 -1
  100. package/dist/riseBidAdapter.js +1 -1
  101. package/dist/rubiconAnalyticsAdapter.js +1 -1
  102. package/dist/rubiconBidAdapter.js +1 -1
  103. package/dist/schain.js +1 -1
  104. package/dist/seedingAllianceBidAdapter.js +1 -1
  105. package/dist/seedtagBidAdapter.js +1 -1
  106. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  107. package/dist/sharethroughBidAdapter.js +1 -1
  108. package/dist/shinezBidAdapter.js +1 -1
  109. package/dist/sirdataRtdProvider.js +1 -1
  110. package/dist/smaatoBidAdapter.js +1 -1
  111. package/dist/smartadserverBidAdapter.js +1 -1
  112. package/dist/smartxBidAdapter.js +1 -1
  113. package/dist/smilewantedBidAdapter.js +1 -1
  114. package/dist/sonobiBidAdapter.js +1 -1
  115. package/dist/sovrnAnalyticsAdapter.js +1 -1
  116. package/dist/sovrnBidAdapter.js +1 -1
  117. package/dist/sspBCBidAdapter.js +1 -1
  118. package/dist/stroeerCoreBidAdapter.js +1 -1
  119. package/dist/stvBidAdapter.js +1 -1
  120. package/dist/sublimeBidAdapter.js +1 -1
  121. package/dist/synacormediaBidAdapter.js +1 -1
  122. package/dist/targetVideoBidAdapter.js +1 -1
  123. package/dist/teadsBidAdapter.js +1 -1
  124. package/dist/trionBidAdapter.js +1 -1
  125. package/dist/tripleliftBidAdapter.js +1 -1
  126. package/dist/ttdBidAdapter.js +1 -1
  127. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  128. package/dist/uid2IdSystem.js +1 -1
  129. package/dist/uid2IdSystem_shared.js +1 -0
  130. package/dist/underdogmediaBidAdapter.js +1 -1
  131. package/dist/undertoneBidAdapter.js +1 -1
  132. package/dist/userId.js +1 -1
  133. package/dist/vidazooBidAdapter.js +1 -1
  134. package/dist/videobyteBidAdapter.js +1 -1
  135. package/dist/viouslyBidAdapter.js +1 -1
  136. package/dist/visxBidAdapter.js +1 -1
  137. package/dist/vuukleBidAdapter.js +1 -1
  138. package/dist/weboramaRtdProvider.js +1 -1
  139. package/dist/widespaceBidAdapter.js +1 -1
  140. package/dist/winrBidAdapter.js +1 -1
  141. package/dist/yahoosspBidAdapter.js +1 -1
  142. package/dist/yieldlabBidAdapter.js +1 -1
  143. package/dist/yieldmoBidAdapter.js +1 -1
  144. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  145. package/dist/zeta_global_sspBidAdapter.js +1 -1
  146. package/integrationExamples/gpt/userId_example.html +20 -6
  147. package/modules/.submodules.json +3 -1
  148. package/modules/1plusXRtdProvider.js +31 -60
  149. package/modules/adagioBidAdapter.js +86 -24
  150. package/modules/adkernelBidAdapter.js +2 -2
  151. package/modules/airgridRtdProvider.js +11 -12
  152. package/modules/asoBidAdapter.js +2 -1
  153. package/modules/beopBidAdapter.js +6 -0
  154. package/modules/conceptxBidAdapter.js +70 -0
  155. package/modules/conceptxBidAdapter.md +36 -0
  156. package/modules/criteoBidAdapter.js +9 -2
  157. package/modules/eskimiBidAdapter.js +171 -41
  158. package/modules/eskimiBidAdapter.md +35 -16
  159. package/modules/euidIdSystem.js +121 -0
  160. package/modules/euidIdSystem.md +131 -0
  161. package/modules/freepassIdSystem.js +61 -0
  162. package/modules/freepassIdSystem.md +47 -0
  163. package/modules/greenbidsAnalyticsAdapter.js +1 -1
  164. package/modules/id5IdSystem.js +3 -5
  165. package/modules/ixBidAdapter.js +12 -1
  166. package/modules/limelightDigitalBidAdapter.js +1 -1
  167. package/modules/logicadBidAdapter.js +14 -1
  168. package/modules/mediasquareBidAdapter.js +13 -5
  169. package/modules/nexx360BidAdapter.js +1 -0
  170. package/modules/pairIdSystem.js +10 -5
  171. package/modules/proxistoreBidAdapter.js +11 -14
  172. package/modules/richaudienceBidAdapter.js +10 -1
  173. package/modules/riseBidAdapter.js +1 -1
  174. package/modules/schain.js +2 -2
  175. package/modules/sirdataRtdProvider.js +73 -146
  176. package/modules/sovrnBidAdapter.js +4 -1
  177. package/modules/stroeerCoreBidAdapter.js +55 -6
  178. package/modules/uid2IdSystem.js +27 -210
  179. package/modules/uid2IdSystem.md +104 -23
  180. package/modules/uid2IdSystem_shared.js +232 -0
  181. package/modules/userId/eids.js +8 -0
  182. package/modules/userId/userId.md +2 -1
  183. package/modules/viouslyBidAdapter.js +2 -2
  184. package/modules/weboramaRtdProvider.js +25 -95
  185. package/modules/weboramaRtdProvider.md +4 -4
  186. package/modules/yieldlabBidAdapter.js +23 -14
  187. package/modules/zeta_global_sspBidAdapter.js +27 -22
  188. package/package.json +1 -1
  189. package/src/adloader.js +1 -0
  190. package/test/spec/modules/1plusXRtdProvider_spec.js +98 -149
  191. package/test/spec/modules/adagioBidAdapter_spec.js +46 -17
  192. package/test/spec/modules/airgridRtdProvider_spec.js +2 -0
  193. package/test/spec/modules/beopBidAdapter_spec.js +24 -0
  194. package/test/spec/modules/conceptxBidAdapter_spec.js +136 -0
  195. package/test/spec/modules/criteoBidAdapter_spec.js +1 -1
  196. package/test/spec/modules/eids_spec.js +15 -0
  197. package/test/spec/modules/eskimiBidAdapter_spec.js +264 -112
  198. package/test/spec/modules/euidIdSystem_spec.js +130 -0
  199. package/test/spec/modules/freepassIdSystem_spec.js +186 -0
  200. package/test/spec/modules/id5IdSystem_spec.js +10 -3
  201. package/test/spec/modules/ixBidAdapter_spec.js +30 -0
  202. package/test/spec/modules/logicadBidAdapter_spec.js +122 -2
  203. package/test/spec/modules/mediasquareBidAdapter_spec.js +4 -0
  204. package/test/spec/modules/richaudienceBidAdapter_spec.js +44 -0
  205. package/test/spec/modules/schain_spec.js +9 -0
  206. package/test/spec/modules/sirdataRtdProvider_spec.js +110 -17
  207. package/test/spec/modules/sovrnBidAdapter_spec.js +13 -0
  208. package/test/spec/modules/stroeerCoreBidAdapter_spec.js +151 -6
  209. package/test/spec/modules/uid2IdSystem_helpers.js +70 -0
  210. package/test/spec/modules/uid2IdSystem_spec.js +131 -86
  211. package/test/spec/modules/userId_spec.js +16 -12
  212. package/test/spec/modules/weboramaRtdProvider_spec.js +331 -205
  213. package/test/spec/modules/yieldlabBidAdapter_spec.js +42 -2
  214. package/test/spec/modules/zeta_global_sspBidAdapter_spec.js +200 -4
@@ -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 = `1.0`;
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 getStorage() {
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
- logInfo(prefix + ' ', ...strings);
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
- function storeValue(value) {
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
- const result = getIdImpl(config, consentData);
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 an old-style ID from an earlier version of the module. Refresh is unavailable for this token.');
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);
@@ -1,25 +1,56 @@
1
- ## UID 2.0 User ID Submodule
1
+ ## UID2 User ID Submodule
2
2
 
3
- UID 2.0 ID Module.
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
- ### Prebid Params
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
- Individual params may be set for the UID 2.0 Submodule. At least one identifier must be set in the params.
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
- The module will handle refreshing the token periodically and storing the updated token using the Prebid.js storage manager. 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.
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
- You should supply either `uid2Token` or `uid2ServerCookie`.
62
+ ## Server-Only Mode
34
63
 
35
- If you provide `uid2Token`, the value should be a JavaScript/JSON object with the decrypted `body` payload response from a call to either `/token/generate` or `/token/refresh`.
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
- If you provide `uid2ServerCookie`, the module will expect that same JSON object to be stored in the cookie - i.e. it will pass the cookie value to `JSON.parse` and expect to receive an object containing similar to what you see in the `Sample token` section below.
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
- The module will make calls to the `/token/refresh` endpoint to update the token it stores internally, so bids may contain an updated token.
70
+ ### Server only cookie example
40
71
 
41
- If neither of `uid2Token` or `uid2ServerCookie` are supplied, and the module has stored a token using the Prebid.js storage system (typically in a cookie named `__uid2_advertising_token`), it will use that token. This cookie is internal to the module and should not be set directly.
72
+ Cookie:
73
+ ```
74
+ __uid2_advertising_token=...advertising token...
75
+ ```
42
76
 
43
- 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).
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
- ### Sample token
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 />&nbsp;&nbsp;`"advertising_token": "...",`<br />&nbsp;&nbsp;`"refresh_token": "...",`<br />&nbsp;&nbsp;`"identity_expires": 1633643601000,`<br />&nbsp;&nbsp;`"refresh_from": 1633643001000,`<br />&nbsp;&nbsp;`"refresh_expires": 1636322000000,`<br />&nbsp;&nbsp;`"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 UID20 module - `"uid2"` | `"uid2"` |
52
- | params.uid2Token | Optional | 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. |
53
- | params.uid2ServerCookie | Optional | 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 alternative uid2Token param. **If uid2Token is supplied, this param is ignored.** | See the sample token above. |
54
- | params.uid2ApiBase | Optional | String | Overrides the default UID2 API endpoint. | `https://prod.uidapi.com` _(default)_ |
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)_ |