prebid.js 7.11.0 → 7.12.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 (170) hide show
  1. package/.github/workflows/issue_tracker.yml +1 -1
  2. package/dist/33acrossBidAdapter.js +1 -1
  3. package/dist/adagioBidAdapter.js +1 -1
  4. package/dist/adbookpspBidAdapter.js +1 -1
  5. package/dist/adgenerationBidAdapter.js +1 -1
  6. package/dist/adkernelBidAdapter.js +1 -1
  7. package/dist/adrelevantisBidAdapter.js +1 -1
  8. package/dist/adriverBidAdapter.js +1 -1
  9. package/dist/adriverIdSystem.js +1 -1
  10. package/dist/adtelligentBidAdapter.js +1 -1
  11. package/dist/adtrgtmeBidAdapter.js +1 -1
  12. package/dist/adxcgBidAdapter.js +1 -1
  13. package/dist/ajaBidAdapter.js +1 -1
  14. package/dist/alkimiBidAdapter.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/betweenBidAdapter.js +1 -1
  22. package/dist/bidglassBidAdapter.js +1 -1
  23. package/dist/bidwatchAnalyticsAdapter.js +1 -1
  24. package/dist/big-richmediaBidAdapter.js +1 -1
  25. package/dist/bridgewellBidAdapter.js +1 -1
  26. package/dist/brightMountainMediaBidAdapter.js +1 -1
  27. package/dist/concertBidAdapter.js +1 -1
  28. package/dist/connectadBidAdapter.js +1 -1
  29. package/dist/consumableBidAdapter.js +1 -1
  30. package/dist/conversantBidAdapter.js +1 -1
  31. package/dist/craftBidAdapter.js +1 -1
  32. package/dist/criteoBidAdapter.js +1 -1
  33. package/dist/dfpAdServerVideo.js +1 -1
  34. package/dist/dgkeywordRtdProvider.js +1 -1
  35. package/dist/displayioBidAdapter.js +1 -3
  36. package/dist/dspxBidAdapter.js +1 -1
  37. package/dist/eplanningBidAdapter.js +1 -1
  38. package/dist/finativeBidAdapter.js +1 -1
  39. package/dist/glimpseBidAdapter.js +1 -1
  40. package/dist/gmosspBidAdapter.js +1 -1
  41. package/dist/goldbachBidAdapter.js +1 -1
  42. package/dist/gridBidAdapter.js +1 -1
  43. package/dist/gridNMBidAdapter.js +1 -1
  44. package/dist/gumgumBidAdapter.js +1 -1
  45. package/dist/h12mediaBidAdapter.js +1 -1
  46. package/dist/id5IdSystem.js +1 -1
  47. package/dist/improvedigitalBidAdapter.js +1 -1
  48. package/dist/inmarBidAdapter.js +1 -1
  49. package/dist/insticatorBidAdapter.js +1 -1
  50. package/dist/ixBidAdapter.js +1 -1
  51. package/dist/justpremiumBidAdapter.js +1 -1
  52. package/dist/konduitAnalyticsAdapter.js +1 -1
  53. package/dist/kueezBidAdapter.js +1 -1
  54. package/dist/lassoBidAdapter.js +1 -1
  55. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  56. package/dist/logicadBidAdapter.js +1 -1
  57. package/dist/loglyliftBidAdapter.js +1 -1
  58. package/dist/malltvAnalyticsAdapter.js +1 -1
  59. package/dist/marsmediaBidAdapter.js +1 -1
  60. package/dist/mediafuseBidAdapter.js +1 -1
  61. package/dist/mediagoBidAdapter.js +1 -0
  62. package/dist/mediasquareBidAdapter.js +1 -1
  63. package/dist/mgidBidAdapter.js +1 -1
  64. package/dist/minutemediaBidAdapter.js +1 -1
  65. package/dist/nextMillenniumBidAdapter.js +1 -1
  66. package/dist/not-for-prod/prebid.js +120 -121
  67. package/dist/oguryBidAdapter.js +1 -1
  68. package/dist/onetagBidAdapter.js +1 -1
  69. package/dist/ooloAnalyticsAdapter.js +1 -1
  70. package/dist/outbrainBidAdapter.js +1 -1
  71. package/dist/parrableIdSystem.js +1 -1
  72. package/dist/pixfutureBidAdapter.js +1 -1
  73. package/dist/prebid-core.js +1 -1
  74. package/dist/publinkIdSystem.js +1 -1
  75. package/dist/pubmaticAnalyticsAdapter.js +1 -1
  76. package/dist/pubmaticBidAdapter.js +1 -1
  77. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  78. package/dist/pxyzBidAdapter.js +1 -1
  79. package/dist/quantcastBidAdapter.js +1 -1
  80. package/dist/rasBidAdapter.js +1 -1
  81. package/dist/readpeakBidAdapter.js +1 -1
  82. package/dist/relaidoBidAdapter.js +1 -1
  83. package/dist/rhythmoneBidAdapter.js +1 -1
  84. package/dist/riseBidAdapter.js +1 -1
  85. package/dist/rubiconAnalyticsAdapter.js +1 -1
  86. package/dist/rubiconBidAdapter.js +1 -1
  87. package/dist/seedingAllianceBidAdapter.js +1 -1
  88. package/dist/seedtagBidAdapter.js +1 -1
  89. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  90. package/dist/sharethroughBidAdapter.js +1 -1
  91. package/dist/shinezBidAdapter.js +1 -1
  92. package/dist/smaatoBidAdapter.js +1 -1
  93. package/dist/smartadserverBidAdapter.js +1 -1
  94. package/dist/smartxBidAdapter.js +1 -1
  95. package/dist/smilewantedBidAdapter.js +1 -1
  96. package/dist/sonobiBidAdapter.js +1 -1
  97. package/dist/sovrnAnalyticsAdapter.js +1 -1
  98. package/dist/sovrnBidAdapter.js +1 -1
  99. package/dist/sspBCBidAdapter.js +1 -1
  100. package/dist/sublimeBidAdapter.js +1 -1
  101. package/dist/synacormediaBidAdapter.js +1 -1
  102. package/dist/tappxBidAdapter.js +1 -1
  103. package/dist/targetVideoBidAdapter.js +1 -1
  104. package/dist/teadsBidAdapter.js +1 -1
  105. package/dist/trionBidAdapter.js +1 -1
  106. package/dist/tripleliftBidAdapter.js +1 -1
  107. package/dist/ttdBidAdapter.js +1 -1
  108. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  109. package/dist/underdogmediaBidAdapter.js +1 -1
  110. package/dist/undertoneBidAdapter.js +1 -1
  111. package/dist/userId.js +1 -1
  112. package/dist/vidazooBidAdapter.js +1 -1
  113. package/dist/videobyteBidAdapter.js +1 -1
  114. package/dist/visxBidAdapter.js +1 -1
  115. package/dist/vuukleBidAdapter.js +1 -1
  116. package/dist/widespaceBidAdapter.js +1 -1
  117. package/dist/winrBidAdapter.js +1 -1
  118. package/dist/yahoosspBidAdapter.js +1 -1
  119. package/dist/yieldmoBidAdapter.js +1 -1
  120. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  121. package/modules/adkernelBidAdapter.js +28 -12
  122. package/modules/adriverBidAdapter.js +5 -12
  123. package/modules/adriverIdSystem.js +2 -1
  124. package/modules/adtelligentBidAdapter.js +2 -0
  125. package/modules/alkimiBidAdapter.js +2 -1
  126. package/modules/betweenBidAdapter.js +3 -3
  127. package/modules/bidwatchAnalyticsAdapter.js +112 -59
  128. package/modules/consumableBidAdapter.js +2 -2
  129. package/modules/criteoBidAdapter.js +19 -13
  130. package/modules/dgkeywordRtdProvider.js +9 -0
  131. package/modules/displayioBidAdapter.js +92 -97
  132. package/modules/id5IdSystem.js +160 -111
  133. package/modules/id5IdSystem.md +16 -14
  134. package/modules/improvedigitalBidAdapter.js +50 -28
  135. package/modules/ixBidAdapter.js +13 -306
  136. package/modules/mediagoBidAdapter.js +462 -0
  137. package/modules/mediagoBidAdapter.md +34 -0
  138. package/modules/nextMillenniumBidAdapter.js +25 -6
  139. package/modules/pubmaticAnalyticsAdapter.js +1 -1
  140. package/modules/rasBidAdapter.js +8 -0
  141. package/modules/rasBidAdapter.md +14 -13
  142. package/modules/sonobiBidAdapter.js +1 -0
  143. package/modules/tappxBidAdapter.js +9 -0
  144. package/package.json +1 -1
  145. package/src/adloader.js +2 -1
  146. package/src/adserver.js +0 -56
  147. package/src/auction.js +58 -15
  148. package/src/native.js +1 -0
  149. package/src/refererDetection.js +12 -1
  150. package/src/videoCache.js +8 -2
  151. package/test/spec/modules/adkernelBidAdapter_spec.js +11 -2
  152. package/test/spec/modules/adriverBidAdapter_spec.js +6 -13
  153. package/test/spec/modules/adriverIdSystem_spec.js +3 -8
  154. package/test/spec/modules/adtelligentBidAdapter_spec.js +1 -0
  155. package/test/spec/modules/alkimiBidAdapter_spec.js +2 -1
  156. package/test/spec/modules/betweenBidAdapter_spec.js +17 -0
  157. package/test/spec/modules/bidwatchAnalyticsAdapter_spec.js +28 -12
  158. package/test/spec/modules/criteoBidAdapter_spec.js +35 -26
  159. package/test/spec/modules/dgkeywordRtdProvider_spec.js +1 -1
  160. package/test/spec/modules/displayioBidAdapter_spec.js +16 -52
  161. package/test/spec/modules/enrichmentFpdModule_spec.js +2 -1
  162. package/test/spec/modules/fpdModule_spec.js +2 -1
  163. package/test/spec/modules/id5IdSystem_spec.js +529 -172
  164. package/test/spec/modules/improvedigitalBidAdapter_spec.js +9 -13
  165. package/test/spec/modules/ixBidAdapter_spec.js +210 -104
  166. package/test/spec/modules/mediagoBidAdapter_spec.js +97 -0
  167. package/test/spec/modules/nextMillenniumBidAdapter_spec.js +2 -7
  168. package/test/spec/modules/rasBidAdapter_spec.js +2 -0
  169. package/test/spec/native_spec.js +144 -0
  170. package/test/spec/videoCache_spec.js +37 -7
@@ -7,19 +7,19 @@
7
7
 
8
8
  import {
9
9
  deepAccess,
10
- logInfo,
11
10
  deepSetValue,
12
- logError,
13
11
  isEmpty,
14
12
  isEmptyStr,
13
+ logError,
14
+ logInfo,
15
15
  logWarn,
16
16
  safeJSONParse
17
17
  } from '../src/utils.js';
18
- import { ajax } from '../src/ajax.js';
19
- import { submodule } from '../src/hook.js';
20
- import { getRefererInfo } from '../src/refererDetection.js';
21
- import { getStorageManager } from '../src/storageManager.js';
22
- import { uspDataHandler } from '../src/adapterManager.js';
18
+ import {ajax} from '../src/ajax.js';
19
+ import {submodule} from '../src/hook.js';
20
+ import {getRefererInfo} from '../src/refererDetection.js';
21
+ import {getStorageManager} from '../src/storageManager.js';
22
+ import {uspDataHandler} from '../src/adapterManager.js';
23
23
 
24
24
  const MODULE_NAME = 'id5Id';
25
25
  const GVLID = 131;
@@ -28,10 +28,11 @@ export const ID5_STORAGE_NAME = 'id5id';
28
28
  export const ID5_PRIVACY_STORAGE_NAME = `${ID5_STORAGE_NAME}_privacy`;
29
29
  const LOCAL_STORAGE = 'html5';
30
30
  const LOG_PREFIX = 'User ID - ID5 submodule: ';
31
+ const ID5_API_CONFIG_URL = 'https://id5-sync.com/api/config/prebid'
31
32
 
32
33
  // order the legacy cookie names in reverse priority order so the last
33
34
  // cookie in the array is the most preferred to use
34
- const LEGACY_COOKIE_NAMES = [ 'pbjs-id5id', 'id5id.1st', 'id5id' ];
35
+ const LEGACY_COOKIE_NAMES = ['pbjs-id5id', 'id5id.1st', 'id5id'];
35
36
 
36
37
  export const storage = getStorageManager({gvlid: GVLID, moduleName: MODULE_NAME});
37
38
 
@@ -102,92 +103,27 @@ export const id5IdSubmodule = {
102
103
  /**
103
104
  * performs action to obtain id and return a value in the callback's response argument
104
105
  * @function getId
105
- * @param {SubmoduleConfig} config
106
+ * @param {SubmoduleConfig} submoduleConfig
106
107
  * @param {ConsentData} consentData
107
108
  * @param {(Object|undefined)} cacheIdObj
108
109
  * @returns {IdResponse|undefined}
109
110
  */
110
- getId(config, consentData, cacheIdObj) {
111
- if (!hasRequiredConfig(config)) {
111
+ getId(submoduleConfig, consentData, cacheIdObj) {
112
+ if (!hasRequiredConfig(submoduleConfig)) {
112
113
  return undefined;
113
114
  }
114
115
 
115
- const url = `https://id5-sync.com/g/v2/${config.params.partner}.json`;
116
- const hasGdpr = (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) ? 1 : 0;
117
- const usp = uspDataHandler.getConsentData();
118
- const referer = getRefererInfo();
119
- const signature = (cacheIdObj && cacheIdObj.signature) ? cacheIdObj.signature : getLegacyCookieSignature();
120
- const data = {
121
- 'partner': config.params.partner,
122
- 'gdpr': hasGdpr,
123
- 'nbPage': incrementNb(config.params.partner),
124
- 'o': 'pbjs',
125
- 'rf': referer.topmostLocation,
126
- 'top': referer.reachedTop ? 1 : 0,
127
- 'u': referer.stack[0] || window.location.href,
128
- 'v': '$prebid.version$'
129
- };
130
-
131
- // pass in optional data, but only if populated
132
- if (hasGdpr && typeof consentData.consentString !== 'undefined' && !isEmpty(consentData.consentString) && !isEmptyStr(consentData.consentString)) {
133
- data.gdpr_consent = consentData.consentString;
134
- }
135
- if (typeof usp !== 'undefined' && !isEmpty(usp) && !isEmptyStr(usp)) {
136
- data.us_privacy = usp;
137
- }
138
- if (typeof signature !== 'undefined' && !isEmptyStr(signature)) {
139
- data.s = signature;
140
- }
141
- if (typeof config.params.pd !== 'undefined' && !isEmptyStr(config.params.pd)) {
142
- data.pd = config.params.pd;
143
- }
144
- if (typeof config.params.provider !== 'undefined' && !isEmptyStr(config.params.provider)) {
145
- data.provider = config.params.provider;
146
- }
147
-
148
- const abTestingConfig = getAbTestingConfig(config);
149
- if (abTestingConfig.enabled === true) {
150
- data.ab_testing = {
151
- enabled: true,
152
- control_group_pct: abTestingConfig.controlGroupPct // The server validates
153
- };
154
- }
155
-
156
- const resp = function (callback) {
157
- const callbacks = {
158
- success: response => {
159
- let responseObj;
160
- if (response) {
161
- try {
162
- responseObj = JSON.parse(response);
163
- logInfo(LOG_PREFIX + 'response received from the server', responseObj);
164
-
165
- resetNb(config.params.partner);
166
-
167
- if (responseObj.privacy) {
168
- storeInLocalStorage(ID5_PRIVACY_STORAGE_NAME, JSON.stringify(responseObj.privacy), NB_EXP_DAYS);
169
- }
170
-
171
- // TODO: remove after requiring publishers to use localstorage and
172
- // all publishers have upgraded
173
- if (config.storage.type === LOCAL_STORAGE) {
174
- removeLegacyCookies(config.params.partner);
175
- }
176
- } catch (error) {
177
- logError(LOG_PREFIX + error);
178
- }
179
- }
180
- callback(responseObj);
181
- },
182
- error: error => {
116
+ const resp = function (cbFunction) {
117
+ new IdFetchFlow(submoduleConfig, consentData, cacheIdObj, uspDataHandler.getConsentData()).execute()
118
+ .then(response => {
119
+ cbFunction(response)
120
+ })
121
+ .catch(error => {
183
122
  logError(LOG_PREFIX + 'getId fetch encountered an error', error);
184
- callback();
185
- }
186
- };
187
- logInfo(LOG_PREFIX + 'requesting an ID from the server', data);
188
- ajax(url, callbacks, JSON.stringify(data), { method: 'POST', withCredentials: true });
123
+ cbFunction();
124
+ });
189
125
  };
190
- return { callback: resp };
126
+ return {callback: resp};
191
127
  },
192
128
 
193
129
  /**
@@ -212,6 +148,139 @@ export const id5IdSubmodule = {
212
148
  }
213
149
  };
214
150
 
151
+ class IdFetchFlow {
152
+ constructor(submoduleConfig, gdprConsentData, cacheIdObj, usPrivacyData) {
153
+ this.submoduleConfig = submoduleConfig
154
+ this.gdprConsentData = gdprConsentData
155
+ this.cacheIdObj = cacheIdObj
156
+ this.usPrivacyData = usPrivacyData
157
+ }
158
+
159
+ execute() {
160
+ return this.#callForConfig(this.submoduleConfig)
161
+ .then(fetchFlowConfig => {
162
+ return this.#callForExtensions(fetchFlowConfig.extensionsCall)
163
+ .then(extensionsData => {
164
+ return this.#callId5Fetch(fetchFlowConfig.fetchCall, extensionsData)
165
+ })
166
+ })
167
+ .then(fetchCallResponse => {
168
+ try {
169
+ resetNb(this.submoduleConfig.params.partner);
170
+ if (fetchCallResponse.privacy) {
171
+ storeInLocalStorage(ID5_PRIVACY_STORAGE_NAME, JSON.stringify(fetchCallResponse.privacy), NB_EXP_DAYS);
172
+ }
173
+ } catch (error) {
174
+ logError(LOG_PREFIX + error);
175
+ }
176
+ return fetchCallResponse;
177
+ })
178
+ }
179
+
180
+ #ajaxPromise(url, data, options) {
181
+ return new Promise((resolve, reject) => {
182
+ ajax(url,
183
+ {
184
+ success: function (res) {
185
+ resolve(res)
186
+ },
187
+ error: function (err) {
188
+ reject(err)
189
+ }
190
+ }, data, options)
191
+ })
192
+ }
193
+
194
+ // eslint-disable-next-line no-dupe-class-members
195
+ #callForConfig(submoduleConfig) {
196
+ let url = submoduleConfig.params.configUrl || ID5_API_CONFIG_URL; // override for debug/test purposes only
197
+ return this.#ajaxPromise(url, JSON.stringify(submoduleConfig), {method: 'POST'})
198
+ .then(response => {
199
+ let responseObj = JSON.parse(response);
200
+ logInfo(LOG_PREFIX + 'config response received from the server', responseObj);
201
+ return responseObj;
202
+ });
203
+ }
204
+
205
+ // eslint-disable-next-line no-dupe-class-members
206
+ #callForExtensions(extensionsCallConfig) {
207
+ if (extensionsCallConfig === undefined) {
208
+ return Promise.resolve(undefined)
209
+ }
210
+ let extensionsUrl = extensionsCallConfig.url
211
+ let method = extensionsCallConfig.method || 'GET'
212
+ let data = method === 'GET' ? undefined : JSON.stringify(extensionsCallConfig.body || {})
213
+ return this.#ajaxPromise(extensionsUrl, data, {'method': method})
214
+ .then(response => {
215
+ let responseObj = JSON.parse(response);
216
+ logInfo(LOG_PREFIX + 'extensions response received from the server', responseObj);
217
+ return responseObj;
218
+ })
219
+ }
220
+
221
+ // eslint-disable-next-line no-dupe-class-members
222
+ #callId5Fetch(fetchCallConfig, extensionsData) {
223
+ let url = fetchCallConfig.url;
224
+ let additionalData = fetchCallConfig.overrides || {};
225
+ let data = {
226
+ ...this.#createFetchRequestData(),
227
+ ...additionalData,
228
+ extensions: extensionsData
229
+ };
230
+ return this.#ajaxPromise(url, JSON.stringify(data), {method: 'POST', withCredentials: true})
231
+ .then(response => {
232
+ let responseObj = JSON.parse(response);
233
+ logInfo(LOG_PREFIX + 'fetch response received from the server', responseObj);
234
+ return responseObj;
235
+ });
236
+ }
237
+
238
+ // eslint-disable-next-line no-dupe-class-members
239
+ #createFetchRequestData() {
240
+ const params = this.submoduleConfig.params;
241
+ const hasGdpr = (this.gdprConsentData && typeof this.gdprConsentData.gdprApplies === 'boolean' && this.gdprConsentData.gdprApplies) ? 1 : 0;
242
+ const referer = getRefererInfo();
243
+ const signature = (this.cacheIdObj && this.cacheIdObj.signature) ? this.cacheIdObj.signature : getLegacyCookieSignature();
244
+ const nbPage = incrementNb(params.partner);
245
+ const data = {
246
+ 'partner': params.partner,
247
+ 'gdpr': hasGdpr,
248
+ 'nbPage': nbPage,
249
+ 'o': 'pbjs',
250
+ 'rf': referer.topmostLocation,
251
+ 'top': referer.reachedTop ? 1 : 0,
252
+ 'u': referer.stack[0] || window.location.href,
253
+ 'v': '$prebid.version$',
254
+ 'storage': this.submoduleConfig.storage
255
+ };
256
+
257
+ // pass in optional data, but only if populated
258
+ if (hasGdpr && this.gdprConsentData.consentString !== undefined && !isEmpty(this.gdprConsentData.consentString) && !isEmptyStr(this.gdprConsentData.consentString)) {
259
+ data.gdpr_consent = this.gdprConsentData.consentString;
260
+ }
261
+ if (this.usPrivacyData !== undefined && !isEmpty(this.usPrivacyData) && !isEmptyStr(this.usPrivacyData)) {
262
+ data.us_privacy = this.usPrivacyData;
263
+ }
264
+ if (signature !== undefined && !isEmptyStr(signature)) {
265
+ data.s = signature;
266
+ }
267
+ if (params.pd !== undefined && !isEmptyStr(params.pd)) {
268
+ data.pd = params.pd;
269
+ }
270
+ if (params.provider !== undefined && !isEmptyStr(params.provider)) {
271
+ data.provider = params.provider;
272
+ }
273
+ const abTestingConfig = params.abTesting || {enabled: false};
274
+
275
+ if (abTestingConfig.enabled) {
276
+ data.ab_testing = {
277
+ enabled: true, control_group_pct: abTestingConfig.controlGroupPct // The server validates
278
+ };
279
+ }
280
+ return data
281
+ }
282
+ }
283
+
215
284
  function hasRequiredConfig(config) {
216
285
  if (!config || !config.params || !config.params.partner || typeof config.params.partner !== 'number') {
217
286
  logError(LOG_PREFIX + 'partner required to be defined as a number');
@@ -242,25 +311,29 @@ export function expDaysStr(expDays) {
242
311
  export function nbCacheName(partnerId) {
243
312
  return `${ID5_STORAGE_NAME}_${partnerId}_nb`;
244
313
  }
314
+
245
315
  export function storeNbInCache(partnerId, nb) {
246
316
  storeInLocalStorage(nbCacheName(partnerId), nb, NB_EXP_DAYS);
247
317
  }
318
+
248
319
  export function getNbFromCache(partnerId) {
249
320
  let cacheNb = getFromLocalStorage(nbCacheName(partnerId));
250
321
  return (cacheNb) ? parseInt(cacheNb) : 0;
251
322
  }
323
+
252
324
  function incrementNb(partnerId) {
253
325
  const nb = (getNbFromCache(partnerId) + 1);
254
326
  storeNbInCache(partnerId, nb);
255
327
  return nb;
256
328
  }
329
+
257
330
  function resetNb(partnerId) {
258
331
  storeNbInCache(partnerId, 0);
259
332
  }
260
333
 
261
334
  function getLegacyCookieSignature() {
262
335
  let legacyStoredValue;
263
- LEGACY_COOKIE_NAMES.forEach(function(cookie) {
336
+ LEGACY_COOKIE_NAMES.forEach(function (cookie) {
264
337
  if (storage.getCookie(cookie)) {
265
338
  legacyStoredValue = safeJSONParse(storage.getCookie(cookie)) || legacyStoredValue;
266
339
  }
@@ -268,21 +341,6 @@ function getLegacyCookieSignature() {
268
341
  return (legacyStoredValue && legacyStoredValue.signature) || '';
269
342
  }
270
343
 
271
- /**
272
- * Remove our legacy cookie values. Needed until we move all publishers
273
- * to html5 storage in a future release
274
- * @param {integer} partnerId
275
- */
276
- function removeLegacyCookies(partnerId) {
277
- logInfo(LOG_PREFIX + 'removing legacy cookies');
278
- LEGACY_COOKIE_NAMES.forEach(function(cookie) {
279
- storage.setCookie(`${cookie}`, ' ', expDaysStr(-1));
280
- storage.setCookie(`${cookie}_nb`, ' ', expDaysStr(-1));
281
- storage.setCookie(`${cookie}_${partnerId}_nb`, ' ', expDaysStr(-1));
282
- storage.setCookie(`${cookie}_last`, ' ', expDaysStr(-1));
283
- });
284
- }
285
-
286
344
  /**
287
345
  * This will make sure we check for expiration before accessing local storage
288
346
  * @param {string} key
@@ -303,6 +361,7 @@ export function getFromLocalStorage(key) {
303
361
  storage.removeDataFromLocalStorage(key);
304
362
  return null;
305
363
  }
364
+
306
365
  /**
307
366
  * Ensure that we always set an expiration in local storage since
308
367
  * by default it's not required
@@ -315,14 +374,4 @@ export function storeInLocalStorage(key, value, expDays) {
315
374
  storage.setDataInLocalStorage(`${key}`, value);
316
375
  }
317
376
 
318
- /**
319
- * gets the existing abTesting config or generates a default config with abTesting off
320
- *
321
- * @param {SubmoduleConfig|undefined} config
322
- * @returns {Object} an object which always contains at least the property "enabled"
323
- */
324
- function getAbTestingConfig(config) {
325
- return deepAccess(config, 'params.abTesting', { enabled: false });
326
- }
327
-
328
377
  submodule('userId', id5IdSubmodule);
@@ -29,7 +29,8 @@ pbjs.setConfig({
29
29
  abTesting: { // optional
30
30
  enabled: true, // false by default
31
31
  controlGroupPct: 0.1 // valid values are 0.0 - 1.0 (inclusive)
32
- }
32
+ },
33
+ disableExtensions: false // optional
33
34
  },
34
35
  storage: {
35
36
  type: 'html5', // "html5" is the required storage type
@@ -43,21 +44,22 @@ pbjs.setConfig({
43
44
  });
44
45
  ```
45
46
 
46
- | Param under userSync.userIds[] | Scope | Type | Description | Example |
47
+ | Param under userSync.userIds[] | Scope | Type | Description | Example |
47
48
  | --- | --- | --- | --- | --- |
48
- | name | Required | String | The name of this module: `"id5Id"` | `"id5Id"` |
49
- | params | Required | Object | Details for the ID5 ID. | |
50
- | params.partner | Required | Number | This is the ID5 Partner Number obtained from registering with ID5. | `173` |
51
- | params.pd | Optional | String | Partner-supplied data used for linking ID5 IDs across domains. See [our documentation](https://support.id5.io/portal/en/kb/articles/passing-partner-data-to-id5) for details on generating the string. Omit the parameter or leave as an empty string if no data to supply | `"MT1iNTBjY..."` |
52
- | params.provider | Optional | String | An identifier provided by ID5 to technology partners who manage Prebid setups on behalf of publishers. Reach out to [ID5](mailto:prebid@id5.io) if you have questions about this parameter | `pubmatic-identity-hub` |
53
- | params.abTesting | Optional | Object | Allows publishers to easily run an A/B Test. If enabled and the user is in the Control Group, the ID5 ID will NOT be exposed to bid adapters for that request | Disabled by default |
54
- | params.abTesting.enabled | Optional | Boolean | Set this to `true` to turn on this feature | `true` or `false` |
49
+ | name | Required | String | The name of this module: `"id5Id"` | `"id5Id"` |
50
+ | params | Required | Object | Details for the ID5 ID. | |
51
+ | params.partner | Required | Number | This is the ID5 Partner Number obtained from registering with ID5. | `173` |
52
+ | params.pd | Optional | String | Partner-supplied data used for linking ID5 IDs across domains. See [our documentation](https://support.id5.io/portal/en/kb/articles/passing-partner-data-to-id5) for details on generating the string. Omit the parameter or leave as an empty string if no data to supply | `"MT1iNTBjY..."` |
53
+ | params.provider | Optional | String | An identifier provided by ID5 to technology partners who manage Prebid setups on behalf of publishers. Reach out to [ID5](mailto:prebid@id5.io) if you have questions about this parameter | `pubmatic-identity-hub` |
54
+ | params.abTesting | Optional | Object | Allows publishers to easily run an A/B Test. If enabled and the user is in the Control Group, the ID5 ID will NOT be exposed to bid adapters for that request | Disabled by default |
55
+ | params.abTesting.enabled | Optional | Boolean | Set this to `true` to turn on this feature | `true` or `false` |
55
56
  | params.abTesting.controlGroupPct | Optional | Number | Must be a number between `0.0` and `1.0` (inclusive) and is used to determine the percentage of requests that fall into the control group (and thus not exposing the ID5 ID). For example, a value of `0.20` will result in 20% of requests without an ID5 ID and 80% with an ID. | `0.1` |
56
- | storage | Required | Object | Storage settings for how the User ID module will cache the ID5 ID locally | |
57
- | storage.type | Required | String | This is where the results of the user ID will be stored. ID5 **requires** `"html5"`. | `"html5"` |
58
- | storage.name | Required | String | The name of the local storage where the user ID will be stored. ID5 **requires** `"id5id"`. | `"id5id"` |
59
- | storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. ID5 recommends `90`. | `90` |
60
- | storage.refreshInSeconds | Optional | Integer | How many seconds until the ID5 ID will be refreshed. ID5 strongly recommends 8 hours between refreshes | `8*3600` |
57
+ | params.disableExtensions | Optional | Boolean | Set this to `true` to force turn off extensions call. Default `false` | `true` or `false` |
58
+ | storage | Required | Object | Storage settings for how the User ID module will cache the ID5 ID locally | |
59
+ | storage.type | Required | String | This is where the results of the user ID will be stored. ID5 **requires** `"html5"`. | `"html5"` |
60
+ | storage.name | Required | String | The name of the local storage where the user ID will be stored. ID5 **requires** `"id5id"`. | `"id5id"` |
61
+ | storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. ID5 recommends `90`. | `90` |
62
+ | storage.refreshInSeconds | Optional | Integer | How many seconds until the ID5 ID will be refreshed. ID5 strongly recommends 8 hours between refreshes | `8*3600` |
61
63
 
62
64
  **ATTENTION:** As of Prebid.js v4.14.0, ID5 requires `storage.type` to be `"html5"` and `storage.name` to be `"id5id"`. Using other values will display a warning today, but in an upcoming release, it will prevent the ID5 module from loading. This change is to ensure the ID5 module in Prebid.js interoperates properly with the [ID5 API](https://github.com/id5io/id5-api.js) and to reduce the size of publishers' first-party cookies that are sent to their web servers. If you have any questions, please reach out to us at [prebid@id5.io](mailto:prebid@id5.io).
63
65
 
@@ -19,6 +19,7 @@ import {Renderer} from '../src/Renderer.js';
19
19
  import {createEidsArray} from './userId/eids.js';
20
20
  import {hasPurpose1Consent} from '../src/utils/gpdr.js';
21
21
  import { convertOrtbRequestToProprietaryNative } from '../src/native.js';
22
+ import {loadExternalScript} from '../src/adloader.js';
22
23
 
23
24
  const BIDDER_CODE = 'improvedigital';
24
25
  const CREATIVE_TTL = 300;
@@ -212,7 +213,7 @@ export const spec = {
212
213
 
213
214
  ID_RESPONSE.buildAd(bid, bidRequest, bidObject);
214
215
 
215
- ID_RAZR.addBidData({
216
+ ID_RAZR.forwardBid({
216
217
  bidRequest,
217
218
  bid
218
219
  });
@@ -640,37 +641,58 @@ const ID_OUTSTREAM = {
640
641
  };
641
642
 
642
643
  const ID_RAZR = {
643
- RENDERER_URL: 'https://razr.improvedigital.com/renderer.js',
644
- addBidData({bid, bidRequest}) {
645
- if (this.isValidBid(bid)) {
646
- bid.renderer = Renderer.install({
647
- url: this.RENDERER_URL,
648
- config: {bidRequest}
649
- });
650
- bid.renderer.setRender(this.render);
644
+ RENDERER_URL: 'https://cdn.360yield.com/razr/tag.js',
645
+
646
+ forwardBid({bidRequest, bid}) {
647
+ if (bid.mediaType !== BANNER) {
648
+ return;
651
649
  }
652
- },
653
650
 
654
- isValidBid(bid) {
655
- return bid && /razr:\/\//.test(bid.ad);
651
+ const cfg = {
652
+ prebid: {
653
+ bidRequest,
654
+ bid
655
+ }
656
+ };
657
+
658
+ const cfgStr = JSON.stringify(cfg).replace(/<\/script>/g, '\\x3C/script>');
659
+ const s = `<script>window.__razr_config = ${cfgStr};</script>`;
660
+ bid.ad = bid.ad.replace(/<body[^>]*>/, match => match + s);
661
+
662
+ this.installListener();
656
663
  },
657
664
 
658
- render(bid) {
659
- const {bidRequest} = bid.renderer.getConfig();
660
-
661
- const payload = {
662
- type: 'prebid',
663
- bidRequest,
664
- bid,
665
- config: mergeDeep(
666
- {},
667
- config.getConfig('improvedigital.rendererConfig'),
668
- deepAccess(bidRequest, 'params.rendererConfig')
669
- )
670
- };
665
+ installListener() {
666
+ if (this._listenerInstalled) {
667
+ return;
668
+ }
669
+
670
+ window.addEventListener('message', function(e) {
671
+ const data = e.data?.razr?.load;
672
+ if (!data) {
673
+ return;
674
+ }
675
+
676
+ if (e.source) {
677
+ data.source = e.source;
678
+ if (data.id) {
679
+ e.source.postMessage({
680
+ razr: {
681
+ id: data.id
682
+ }
683
+ }, '*');
684
+ }
685
+ }
686
+
687
+ const ns = window.razr = window.razr || {};
688
+ ns.q = ns.q || [];
689
+ ns.q.push(data);
690
+
691
+ if (!ns.loaded) {
692
+ loadExternalScript(ID_RAZR.RENDERER_URL, BIDDER_CODE);
693
+ }
694
+ });
671
695
 
672
- const razr = window.razr = window.razr || {};
673
- razr.queue = razr.queue || [];
674
- razr.queue.push(payload);
696
+ this._listenerInstalled = true;
675
697
  }
676
698
  };