prebid.js 8.40.0 → 8.41.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 (199) hide show
  1. package/dist/33acrossAnalyticsAdapter.js +1 -1
  2. package/dist/33acrossBidAdapter.js +1 -1
  3. package/dist/33acrossIdSystem.js +1 -1
  4. package/dist/BTBidAdapter.js +1 -1
  5. package/dist/adagioAnalyticsAdapter.js +1 -1
  6. package/dist/adagioBidAdapter.js +1 -1
  7. package/dist/adbookpspBidAdapter.js +1 -1
  8. package/dist/adgenerationBidAdapter.js +1 -1
  9. package/dist/adkernelBidAdapter.js +1 -1
  10. package/dist/adqueryBidAdapter.js +1 -1
  11. package/dist/adrelevantisBidAdapter.js +1 -1
  12. package/dist/adstirBidAdapter.js +1 -1
  13. package/dist/adtrgtmeBidAdapter.js +1 -1
  14. package/dist/adxcgBidAdapter.js +1 -1
  15. package/dist/adyoulikeBidAdapter.js +1 -1
  16. package/dist/agmaAnalyticsAdapter.js +1 -1
  17. package/dist/ajaBidAdapter.js +1 -1
  18. package/dist/amxBidAdapter.js +1 -1
  19. package/dist/amxIdSystem.js +1 -1
  20. package/dist/appierAnalyticsAdapter.js +1 -1
  21. package/dist/appnexusBidAdapter.js +1 -1
  22. package/dist/asoBidAdapter.js +1 -1
  23. package/dist/automatadAnalyticsAdapter.js +1 -1
  24. package/dist/axonixBidAdapter.js +1 -1
  25. package/dist/bidglassBidAdapter.js +1 -1
  26. package/dist/big-richmediaBidAdapter.js +1 -1
  27. package/dist/bridBidAdapter.js +1 -1
  28. package/dist/bridgewellBidAdapter.js +1 -1
  29. package/dist/brightMountainMediaBidAdapter.js +1 -1
  30. package/dist/carodaBidAdapter.js +1 -1
  31. package/dist/chtnwBidAdapter.js +1 -1
  32. package/dist/concertBidAdapter.js +1 -1
  33. package/dist/connectadBidAdapter.js +1 -1
  34. package/dist/consumableBidAdapter.js +1 -1
  35. package/dist/conversantAnalyticsAdapter.js +1 -1
  36. package/dist/conversantBidAdapter.js +1 -1
  37. package/dist/craftBidAdapter.js +1 -1
  38. package/dist/criteoBidAdapter.js +1 -1
  39. package/dist/cwireBidAdapter.js +1 -1
  40. package/dist/discoveryBidAdapter.js +1 -1
  41. package/dist/dspxBidAdapter.js +1 -1
  42. package/dist/dxkultureBidAdapter.js +1 -1
  43. package/dist/eplanningBidAdapter.js +1 -1
  44. package/dist/euidIdSystem.js +1 -1
  45. package/dist/feedadBidAdapter.js +1 -1
  46. package/dist/finativeBidAdapter.js +1 -1
  47. package/dist/freewheel-sspBidAdapter.js +1 -1
  48. package/dist/gmosspBidAdapter.js +1 -1
  49. package/dist/goldbachBidAdapter.js +1 -1
  50. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  51. package/dist/greenbidsRtdProvider.js +1 -1
  52. package/dist/gridBidAdapter.js +1 -1
  53. package/dist/gumgumBidAdapter.js +1 -1
  54. package/dist/h12mediaBidAdapter.js +1 -1
  55. package/dist/hypelabBidAdapter.js +1 -1
  56. package/dist/id5IdSystem.js +1 -1
  57. package/dist/illuminBidAdapter.js +1 -1
  58. package/dist/imdsBidAdapter.js +1 -1
  59. package/dist/improvedigitalBidAdapter.js +1 -1
  60. package/dist/insticatorBidAdapter.js +1 -1
  61. package/dist/ixBidAdapter.js +1 -1
  62. package/dist/jixieBidAdapter.js +1 -1
  63. package/dist/justpremiumBidAdapter.js +1 -1
  64. package/dist/kargoBidAdapter.js +1 -1
  65. package/dist/kimberliteBidAdapter.js +1 -1
  66. package/dist/konduitAnalyticsAdapter.js +1 -1
  67. package/dist/kueezBidAdapter.js +1 -1
  68. package/dist/kueezRtbBidAdapter.js +1 -1
  69. package/dist/lassoBidAdapter.js +1 -1
  70. package/dist/lifestreetBidAdapter.js +1 -1
  71. package/dist/liveIntentIdSystem.js +1 -1
  72. package/dist/logicadBidAdapter.js +1 -1
  73. package/dist/loglyliftBidAdapter.js +1 -1
  74. package/dist/luceadBidAdapter.js +1 -1
  75. package/dist/magniteAnalyticsAdapter.js +1 -1
  76. package/dist/malltvAnalyticsAdapter.js +1 -1
  77. package/dist/marsmediaBidAdapter.js +1 -1
  78. package/dist/mediafuseBidAdapter.js +1 -1
  79. package/dist/mediasquareBidAdapter.js +1 -1
  80. package/dist/mgidBidAdapter.js +1 -1
  81. package/dist/minutemediaBidAdapter.js +1 -1
  82. package/dist/minutemediaplusBidAdapter.js +1 -1
  83. package/dist/missenaBidAdapter.js +1 -1
  84. package/dist/nextMillenniumBidAdapter.js +1 -1
  85. package/dist/nexx360BidAdapter.js +1 -1
  86. package/dist/not-for-prod/prebid.js +155 -153
  87. package/dist/oguryBidAdapter.js +1 -1
  88. package/dist/onetagBidAdapter.js +1 -1
  89. package/dist/ooloAnalyticsAdapter.js +1 -1
  90. package/dist/openxBidAdapter.js +1 -1
  91. package/dist/optidigitalBidAdapter.js +1 -1
  92. package/dist/outbrainBidAdapter.js +1 -1
  93. package/dist/parrableIdSystem.js +1 -1
  94. package/dist/pixfutureBidAdapter.js +1 -1
  95. package/dist/prebid-core.js +1 -1
  96. package/dist/pstudioBidAdapter.js +1 -0
  97. package/dist/publinkIdSystem.js +1 -1
  98. package/dist/publirBidAdapter.js +1 -0
  99. package/dist/pubmaticAnalyticsAdapter.js +1 -1
  100. package/dist/pubmaticBidAdapter.js +1 -1
  101. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  102. package/dist/pxyzBidAdapter.js +1 -1
  103. package/dist/quantcastBidAdapter.js +1 -1
  104. package/dist/rasBidAdapter.js +1 -1
  105. package/dist/readpeakBidAdapter.js +1 -1
  106. package/dist/relaidoBidAdapter.js +1 -1
  107. package/dist/retailspotBidAdapter.js +1 -1
  108. package/dist/rhythmoneBidAdapter.js +1 -1
  109. package/dist/riseBidAdapter.js +1 -1
  110. package/dist/rtbhouseBidAdapter.js +1 -1
  111. package/dist/rubiconBidAdapter.js +1 -1
  112. package/dist/seedingAllianceBidAdapter.js +1 -1
  113. package/dist/seedtagBidAdapter.js +1 -1
  114. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  115. package/dist/sharethroughBidAdapter.js +1 -1
  116. package/dist/shinezBidAdapter.js +1 -1
  117. package/dist/shinezRtbBidAdapter.js +1 -1
  118. package/dist/smaatoBidAdapter.js +1 -1
  119. package/dist/smartadserverBidAdapter.js +1 -1
  120. package/dist/smartxBidAdapter.js +1 -1
  121. package/dist/smartyadsBidAdapter.js +1 -1
  122. package/dist/smilewantedBidAdapter.js +1 -1
  123. package/dist/sonobiBidAdapter.js +1 -1
  124. package/dist/sovrnAnalyticsAdapter.js +1 -1
  125. package/dist/sovrnBidAdapter.js +1 -1
  126. package/dist/sspBCBidAdapter.js +1 -1
  127. package/dist/stnBidAdapter.js +1 -1
  128. package/dist/stvBidAdapter.js +1 -1
  129. package/dist/sublimeBidAdapter.js +1 -1
  130. package/dist/taboolaBidAdapter.js +1 -1
  131. package/dist/tagorasBidAdapter.js +1 -1
  132. package/dist/targetVideoBidAdapter.js +1 -1
  133. package/dist/teadsBidAdapter.js +1 -1
  134. package/dist/themoneytizerBidAdapter.js +1 -1
  135. package/dist/trionBidAdapter.js +1 -1
  136. package/dist/tripleliftBidAdapter.js +1 -1
  137. package/dist/ttdBidAdapter.js +1 -1
  138. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  139. package/dist/uid2IdSystem.js +1 -1
  140. package/dist/underdogmediaBidAdapter.js +1 -1
  141. package/dist/undertoneBidAdapter.js +1 -1
  142. package/dist/unrulyBidAdapter.js +1 -1
  143. package/dist/userId.js +1 -1
  144. package/dist/vidazooBidAdapter.js +1 -1
  145. package/dist/videobyteBidAdapter.js +1 -1
  146. package/dist/visxBidAdapter.js +1 -1
  147. package/dist/vuukleBidAdapter.js +1 -1
  148. package/dist/weboramaRtdProvider.js +1 -1
  149. package/dist/widespaceBidAdapter.js +1 -1
  150. package/dist/winrBidAdapter.js +1 -1
  151. package/dist/yahoosspBidAdapter.js +1 -1
  152. package/dist/yieldmoBidAdapter.js +1 -1
  153. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  154. package/dist/zeta_global_sspBidAdapter.js +1 -1
  155. package/integrationExamples/gpt/publir_hello_world.html +84 -0
  156. package/modules/adkernelBidAdapter.js +2 -1
  157. package/modules/automatadAnalyticsAdapter.js +31 -22
  158. package/modules/discoveryBidAdapter.js +5 -4
  159. package/modules/hypelabBidAdapter.js +31 -5
  160. package/modules/kargoBidAdapter.js +25 -13
  161. package/modules/kueezRtbBidAdapter.js +1 -1
  162. package/modules/nextMillenniumBidAdapter.js +52 -33
  163. package/modules/nexx360BidAdapter.js +2 -3
  164. package/modules/onetagBidAdapter.js +2 -1
  165. package/modules/pstudioBidAdapter.js +435 -0
  166. package/modules/pstudioBidAdapter.md +148 -0
  167. package/modules/publirBidAdapter.js +391 -0
  168. package/modules/publirBidAdapter.md +47 -0
  169. package/modules/pubmaticAnalyticsAdapter.js +7 -2
  170. package/modules/rasBidAdapter.js +178 -22
  171. package/modules/rasBidAdapter.md +2 -2
  172. package/modules/rtbhouseBidAdapter.js +2 -1
  173. package/modules/sharethroughBidAdapter.js +4 -0
  174. package/modules/smartyadsBidAdapter.js +10 -2
  175. package/modules/sovrnBidAdapter.js +15 -8
  176. package/modules/sspBCBidAdapter.js +22 -17
  177. package/modules/taboolaBidAdapter.js +1 -1
  178. package/modules/userId/index.js +1 -1
  179. package/modules/weboramaRtdProvider.js +99 -36
  180. package/modules/weboramaRtdProvider.md +13 -4
  181. package/modules/zeta_global_sspBidAdapter.js +26 -1
  182. package/package.json +1 -1
  183. package/test/spec/modules/automatadAnalyticsAdapter_spec.js +102 -15
  184. package/test/spec/modules/discoveryBidAdapter_spec.js +1 -1
  185. package/test/spec/modules/hypelabBidAdapter_spec.js +5 -1
  186. package/test/spec/modules/kargoBidAdapter_spec.js +29 -11
  187. package/test/spec/modules/nextMillenniumBidAdapter_spec.js +34 -3
  188. package/test/spec/modules/nexx360BidAdapter_spec.js +5 -5
  189. package/test/spec/modules/onetagBidAdapter_spec.js +4 -1
  190. package/test/spec/modules/pstudioBidAdapter_spec.js +514 -0
  191. package/test/spec/modules/publirBidAdapter_spec.js +488 -0
  192. package/test/spec/modules/pubmaticAnalyticsAdapter_spec.js +12 -1
  193. package/test/spec/modules/rasBidAdapter_spec.js +364 -2
  194. package/test/spec/modules/sharethroughBidAdapter_spec.js +35 -0
  195. package/test/spec/modules/sovrnBidAdapter_spec.js +39 -0
  196. package/test/spec/modules/sspBCBidAdapter_spec.js +1 -1
  197. package/test/spec/modules/taboolaBidAdapter_spec.js +1 -1
  198. package/test/spec/modules/weboramaRtdProvider_spec.js +114 -0
  199. package/test/spec/modules/zeta_global_sspBidAdapter_spec.js +4 -4
@@ -104,18 +104,18 @@ import {
104
104
  getGlobal
105
105
  } from '../src/prebidGlobal.js';
106
106
  import {
107
+ deepAccess,
107
108
  deepClone,
108
109
  deepSetValue,
109
- isEmpty,
110
- isFn,
111
- logError,
112
- logMessage,
113
110
  isArray,
114
- isStr,
115
111
  isBoolean,
112
+ isEmpty,
113
+ isFn,
116
114
  isPlainObject,
115
+ isStr,
117
116
  logWarn,
118
- mergeDeep
117
+ mergeDeep,
118
+ prefixLog,
119
119
  } from '../src/utils.js';
120
120
  import {
121
121
  submodule
@@ -126,9 +126,13 @@ import {
126
126
  import {
127
127
  getStorageManager
128
128
  } from '../src/storageManager.js';
129
+ import {
130
+ MODULE_TYPE_RTD
131
+ } from '../src/activities/modules.js';
129
132
  import adapterManager from '../src/adapterManager.js';
130
- import {MODULE_TYPE_RTD} from '../src/activities/modules.js';
131
- import {tryAppendQueryString} from '../libraries/urlUtils/urlUtils.js';
133
+ import {
134
+ tryAppendQueryString
135
+ } from '../libraries/urlUtils/urlUtils.js';
132
136
 
133
137
  /** @type {string} */
134
138
  const MODULE_NAME = 'realTimeData';
@@ -159,6 +163,8 @@ const SFBX_LITE_DATA_SOURCE_LABEL = 'lite';
159
163
  /** @type {number} */
160
164
  const GVLID = 284;
161
165
 
166
+ const logger = prefixLog('[WeboramaRTD]');
167
+
162
168
  export const storage = getStorageManager({
163
169
  moduleType: MODULE_TYPE_RTD,
164
170
  moduleName: SUBMODULE_NAME
@@ -199,9 +205,11 @@ class WeboramaRtdProvider {
199
205
  * @method
200
206
  * @param {Object} moduleConfig
201
207
  * @param {?ModuleParams} moduleConfig.params
208
+ * @param {Object} userConsent
209
+ * @param {?Object} userConsent.gdpr
202
210
  * @return {boolean} true if module was initialized with success
203
211
  */
204
- init(moduleConfig) {
212
+ init(moduleConfig, userConsent) {
205
213
  /** @type {Object} */
206
214
  const globalDefaults = {
207
215
  setPrebidTargeting: true,
@@ -219,8 +227,14 @@ class WeboramaRtdProvider {
219
227
  this.#components.WeboUserData.data = null;
220
228
  this.#components.SfbxLiteData.data = null;
221
229
 
222
- this.#components.WeboCtx.initialized = this.#initSubSection(moduleParams, WEBO_CTX_CONF_SECTION, 'token');
223
- this.#components.WeboUserData.initialized = this.#initSubSection(moduleParams, WEBO_USER_DATA_CONF_SECTION);
230
+ const weboCtxRequiredFields = ['token'];
231
+
232
+ this.#components.WeboCtx.initialized = this.#initSubSection(moduleParams, WEBO_CTX_CONF_SECTION, {
233
+ requiredFields: weboCtxRequiredFields,
234
+ });
235
+ this.#components.WeboUserData.initialized = this.#initSubSection(moduleParams, WEBO_USER_DATA_CONF_SECTION, {
236
+ userConsent: userConsent || {},
237
+ });
224
238
  this.#components.SfbxLiteData.initialized = this.#initSubSection(moduleParams, SFBX_LITE_DATA_CONF_SECTION);
225
239
 
226
240
  return Object.values(this.#components).some((c) => c.initialized);
@@ -251,7 +265,7 @@ class WeboramaRtdProvider {
251
265
  const weboCtxConf = moduleParams.weboCtxConf || {};
252
266
 
253
267
  this.#fetchContextualProfile(weboCtxConf, (data) => {
254
- logMessage('fetchContextualProfile on getBidRequestData is done');
268
+ logger.logMessage('fetchContextualProfile on getBidRequestData is done');
255
269
 
256
270
  this.#setWeboContextualProfile(data);
257
271
  }, () => {
@@ -276,17 +290,17 @@ class WeboramaRtdProvider {
276
290
  const profileHandlers = this.#buildProfileHandlers(moduleParams);
277
291
 
278
292
  if (isEmpty(profileHandlers)) {
279
- logMessage('no data to set targeting');
293
+ logger.logMessage('no data to set targeting');
280
294
  return {};
281
295
  }
282
296
 
283
297
  try {
284
298
  return adUnitsCodes.reduce((data, adUnitCode) => {
285
299
  data[adUnitCode] = profileHandlers.reduce((targeting, ph) => {
286
- // logMessage(`check if should set targeting for adunit '${adUnitCode}'`);
300
+ // logger.logMessage(`check if should set targeting for adunit '${adUnitCode}'`);
287
301
  const [data, metadata] = this.#copyDataAndMetadata(ph);
288
302
  if (ph.setTargeting(adUnitCode, data, metadata)) {
289
- // logMessage(`set targeting for adunit '${adUnitCode}', source '${metadata.source}'`);
303
+ // logger.logMessage(`set targeting for adunit '${adUnitCode}', source '${metadata.source}'`);
290
304
 
291
305
  mergeDeep(targeting, data);
292
306
  }
@@ -297,7 +311,7 @@ class WeboramaRtdProvider {
297
311
  return data;
298
312
  }, {});
299
313
  } catch (e) {
300
- logError(`unable to format weborama rtd targeting data:`, e);
314
+ logger.logError(`unable to format weborama rtd targeting data:`, e);
301
315
 
302
316
  return {};
303
317
  }
@@ -309,10 +323,12 @@ class WeboramaRtdProvider {
309
323
  * @private
310
324
  * @param {ModuleParams} moduleParams
311
325
  * @param {string} subSection subsection name to initialize
312
- * @param {string[]} requiredFields
326
+ * @param {?Object} extra
327
+ * @param {string[]} extra.requiredFields
328
+ * @param {?Object} extra.userConsent
313
329
  * @return {boolean} true if module subsection was initialized with success
314
330
  */
315
- #initSubSection(moduleParams, subSection, ...requiredFields) {
331
+ #initSubSection(moduleParams, subSection, extra) {
316
332
  /** @type {CommonConf} */
317
333
  const weboSectionConf = moduleParams[subSection] || { enabled: false };
318
334
 
@@ -325,21 +341,59 @@ class WeboramaRtdProvider {
325
341
  try {
326
342
  this.#normalizeConf(moduleParams, weboSectionConf);
327
343
 
344
+ extra = extra || {};
345
+ const requiredFields = extra?.requiredFields || [];
346
+
328
347
  requiredFields.forEach(field => {
329
348
  if (!(field in weboSectionConf)) {
330
- throw `missing required field '${field}''`;
349
+ throw `missing required field '${field}'`;
331
350
  }
332
351
  });
352
+
353
+ if (isPlainObject(extra?.userConsent?.gdpr) && !this.#checkTCFv2(extra.userConsent.gdpr)) {
354
+ throw 'gdpr consent not ok';
355
+ }
333
356
  } catch (e) {
334
- logError(`unable to initialize: error on ${subSection} configuration:`, e);
357
+ logger.logError(`unable to initialize: error on '${subSection}' configuration:`, e);
335
358
  return false;
336
359
  }
337
360
 
338
- logMessage(`weborama ${subSection} initialized with success`);
361
+ logger.logMessage(`weborama '${subSection}' initialized with success`);
339
362
 
340
363
  return true;
341
364
  }
342
365
 
366
+ /**
367
+ * check gdpr consent data
368
+ * @method
369
+ * @private
370
+ * @param {Object} gdpr
371
+ * @param {?boolean} gdpr.gdprApplies
372
+ * @param {?Object} gdpr.vendorData
373
+ * @param {?Object} gdpr.vendorData.purpose
374
+ * @param {?Object.<number, boolean>} gdpr.vendorData.purpose.consents
375
+ * @param {?Object} gdpr.vendorData.vendor
376
+ * @param {?Object.<number, boolean>} gdpr.vendorData.vendor.consents
377
+ * @return {boolean}
378
+ */
379
+ // eslint-disable-next-line no-dupe-class-members
380
+ #checkTCFv2(gdpr) {
381
+ if (gdpr?.gdprApplies !== true) {
382
+ return true;
383
+ }
384
+
385
+ if (deepAccess(gdpr, 'vendorData.vendor.consents') &&
386
+ deepAccess(gdpr, 'vendorData.purpose.consents')) {
387
+ return gdpr.vendorData.vendor.consents[GVLID] === true && // check weborama vendor id
388
+ gdpr.vendorData.purpose.consents[1] === true && // info storage access
389
+ gdpr.vendorData.purpose.consents[3] === true && // create personalized ads
390
+ gdpr.vendorData.purpose.consents[4] === true && // select personalized ads
391
+ gdpr.vendorData.purpose.consents[5] === true && // create personalized content
392
+ gdpr.vendorData.purpose.consents[6] === true; // select personalized content
393
+ }
394
+
395
+ return true;
396
+ }
343
397
  /**
344
398
  * normalize submodule configuration
345
399
  * @method
@@ -455,7 +509,7 @@ class WeboramaRtdProvider {
455
509
  const profileHandlers = this.#buildProfileHandlers(moduleParams);
456
510
 
457
511
  if (isEmpty(profileHandlers)) {
458
- logMessage('no data to send to bidders');
512
+ logger.logMessage('no data to send to bidders');
459
513
  return;
460
514
  }
461
515
 
@@ -465,11 +519,11 @@ class WeboramaRtdProvider {
465
519
  adUnits.forEach(
466
520
  adUnit => adUnit.bids?.forEach(
467
521
  bid => profileHandlers.forEach(ph => {
468
- // logMessage(`check if bidder '${bid.bidder}' and adunit '${adUnit.code} are share ${ph.metadata.source} data`);
522
+ // logger.logMessage(`check if bidder '${bid.bidder}' and adunit '${adUnit.code} are share ${ph.metadata.source} data`);
469
523
 
470
524
  const [data, metadata] = this.#copyDataAndMetadata(ph);
471
525
  if (ph.sendToBidders(bid, adUnit.code, data, metadata)) {
472
- // logMessage(`handling bidder '${bid.bidder}' with ${ph.metadata.source} data`);
526
+ // logger.logMessage(`handling bidder '${bid.bidder}' with ${ph.metadata.source} data`);
473
527
 
474
528
  this.#handleBid(reqBidsConfigObj, bid, data, ph.metadata);
475
529
  }
@@ -477,7 +531,7 @@ class WeboramaRtdProvider {
477
531
  )
478
532
  );
479
533
  } catch (e) {
480
- logError('unable to send data to bidders:', e);
534
+ logger.logError('unable to send data to bidders:', e);
481
535
  }
482
536
 
483
537
  profileHandlers.forEach(ph => {
@@ -485,7 +539,7 @@ class WeboramaRtdProvider {
485
539
  const [data, metadata] = this.#copyDataAndMetadata(ph);
486
540
  ph.onData(data, metadata);
487
541
  } catch (e) {
488
- logError(`error while execute onData callback with ${ph.metadata.source}-based data:`, e);
542
+ logger.logError(`error while execute onData callback with ${ph.metadata.source}-based data:`, e);
489
543
  }
490
544
  });
491
545
  }
@@ -529,7 +583,7 @@ class WeboramaRtdProvider {
529
583
  try {
530
584
  assetID = weboCtxConf.assetID();
531
585
  } catch (e) {
532
- logError('unexpected error while fetching asset id from callback', e);
586
+ logger.logError('unexpected error while fetching asset id from callback', e);
533
587
 
534
588
  onDone();
535
589
 
@@ -538,7 +592,7 @@ class WeboramaRtdProvider {
538
592
  }
539
593
 
540
594
  if (!assetID) {
541
- logError('missing asset id');
595
+ logger.logError('missing asset id');
542
596
 
543
597
  onDone();
544
598
 
@@ -565,7 +619,7 @@ class WeboramaRtdProvider {
565
619
  };
566
620
 
567
621
  const error = (e, req) => {
568
- logError(`unable to get weborama data`, e, req);
622
+ logger.logError(`unable to get weborama data`, e, req);
569
623
 
570
624
  onDone();
571
625
  };
@@ -625,7 +679,7 @@ class WeboramaRtdProvider {
625
679
  if (profileHandler) {
626
680
  ph.push(profileHandler);
627
681
  } else {
628
- logMessage(`skip ${source} profile: no data`);
682
+ logger.logMessage(`skip ${source} profile: no data`);
629
683
  }
630
684
 
631
685
  return ph;
@@ -703,17 +757,26 @@ class WeboramaRtdProvider {
703
757
  #handleBid(reqBidsConfigObj, bid, profile, metadata) {
704
758
  this.#handleBidViaORTB2(reqBidsConfigObj, bid.bidder, profile, metadata);
705
759
 
706
- /** @type {Object.<string,string>} */
707
- const bidderAliasRegistry = adapterManager.aliasRegistry || {};
708
-
709
760
  /** @type {string} */
710
- const bidder = bidderAliasRegistry[bid.bidder] || bid.bidder;
761
+ const bidder = this.#getAdapterNameForAlias(bid.bidder);
711
762
 
712
763
  if (bidder == 'appnexus') {
713
764
  this.#handleAppnexusBid(reqBidsConfigObj, bid, profile);
714
765
  }
715
766
  }
716
767
 
768
+ /**
769
+ * return adapter name based on alias, if any
770
+ * @method
771
+ * @private
772
+ * @param {string} aliasName
773
+ * @returns {string}
774
+ */
775
+ // eslint-disable-next-line no-dupe-class-members
776
+ #getAdapterNameForAlias(aliasName) {
777
+ return adapterManager.aliasRegistry[aliasName] || aliasName;
778
+ }
779
+
717
780
  /**
718
781
  * function that handles bid request data
719
782
  * @method
@@ -760,13 +823,13 @@ class WeboramaRtdProvider {
760
823
  // eslint-disable-next-line no-dupe-class-members
761
824
  #handleBidViaORTB2(reqBidsConfigObj, bidder, profile, metadata) {
762
825
  if (isBoolean(metadata.user)) {
763
- logMessage(`bidder '${bidder}' is not directly supported, trying set data via bidder ortb2 fpd`);
826
+ logger.logMessage(`bidder '${bidder}' is not directly supported, trying set data via bidder ortb2 fpd`);
764
827
  const section = metadata.user ? 'user' : 'site';
765
828
  const path = `${section}.ext.data`;
766
829
 
767
830
  this.#setBidderOrtb2(reqBidsConfigObj.ortb2Fragments?.bidder, bidder, path, profile)
768
831
  } else {
769
- logMessage(`SKIP unsupported bidder '${bidder}', data from '${metadata.source}' is not defined as user or site-centric`);
832
+ logger.logMessage(`SKIP unsupported bidder '${bidder}', data from '${metadata.source}' is not defined as user or site-centric`);
770
833
  }
771
834
  }
772
835
  /**
@@ -16,7 +16,7 @@ Weborama provides a Real-Time Data Submodule for `Prebid.js`, allowing to easy i
16
16
 
17
17
  * LiTE by SFBX® (Local inApp Trust Engine) provides “Zero Party Data” given by users, stored and calculated only on the user’s device. Through a unique cohorting system, it enables better monetization in a consent/consentless and identity-less mode.
18
18
 
19
- Contact prebid-support@weborama.com for more information.
19
+ Contact [prebid-support@weborama.com] for more information.
20
20
 
21
21
  ### Publisher Usage
22
22
 
@@ -79,7 +79,7 @@ pbjs.setConfig({
79
79
 
80
80
  Each module can perform two actions:
81
81
 
82
- * set targeting on [GPT](https://docs.prebid.org/dev-docs/publisher-api-reference/setTargetingForGPTAsync.html) / [AST](https://docs.prebid.org/dev-docs/publisher-api-reference/setTargetingForAst.html]) via `prebid.js`
82
+ * set targeting on [GPT](https://docs.prebid.org/dev-docs/publisher-api-reference/setTargetingForGPTAsync.html) / [AST](https://docs.prebid.org/dev-docs/publisher-api-reference/setTargetingForAst.html) via `prebid.js`
83
83
 
84
84
  * send data to other `prebid.js` bidder modules (check the complete list at the end of this page)
85
85
 
@@ -117,9 +117,9 @@ On this section we will explain the `params.weboCtxConf` subconfiguration:
117
117
  | enabled | Boolean| if false, will ignore this configuration| Default is `true` if this section is present|
118
118
  | baseURLProfileAPI | String| if present, update the domain of the contextual api| Optional. Default is `ctx.weborama.com` |
119
119
 
120
- #### WAM User-Centric Configuration
120
+ #### User-Centric Configuration
121
121
 
122
- To be possible use the integration with Weborama Audience Manager (WAM) you must be a client with an account id and you lust include the `wamfactory` script in your pages with `wam2gam` feature activated.
122
+ To be possible use the integration with Weborama Audience Manager (WAM) you must be a client with an account id and you must include the `wamfactory` script in your pages with `wam2gam` feature activated.
123
123
  Please contact weborama if you don't have it.
124
124
 
125
125
  On this section we will explain the `params.weboUserDataConf` subconfiguration:
@@ -134,6 +134,15 @@ On this section we will explain the `params.weboUserDataConf` subconfiguration:
134
134
  | localStorageProfileKey| String | can be used to customize the local storage key | Optional |
135
135
  | enabled | Boolean| if false, will ignore this configuration| Default is `true` if this section is present|
136
136
 
137
+ ##### User Consent
138
+
139
+ The WAM User-Centric configuration will check for user consent if gdpr applies. It will check for consent:
140
+
141
+ * Vendor ID 284 (Weborama)
142
+ * Purpose IDs: 1, 3, 4, 5 and 6
143
+
144
+ If the user consent does not match such conditions, this module will not load, means we will not check for any data in local storage and the default profile will be ignored.
145
+
137
146
  #### Sfbx LiTE Site-Centric Configuration
138
147
 
139
148
  To be possible use the integration between Weborama and Sfbx LiTE you should also contact SFBX® to setup this product.
@@ -50,6 +50,7 @@ const VIDEO_CUSTOM_PARAMS = {
50
50
 
51
51
  export const spec = {
52
52
  code: BIDDER_CODE,
53
+ gvlid: 469,
53
54
  supportedMediaTypes: [BANNER, VIDEO],
54
55
 
55
56
  /**
@@ -140,7 +141,7 @@ export const spec = {
140
141
  };
141
142
  const rInfo = bidderRequest.refererInfo;
142
143
  // TODO: do the fallbacks make sense here?
143
- payload.site.page = rInfo.page || rInfo.topmostLocation;
144
+ payload.site.page = cropPage(rInfo.page || rInfo.topmostLocation);
144
145
  payload.site.domain = parseDomain(payload.site.page, {noLeadingWww: true});
145
146
 
146
147
  payload.device.ua = navigator.userAgent;
@@ -385,6 +386,30 @@ function provideMediaType(zetaBid, bid, bidRequest) {
385
386
  }
386
387
  }
387
388
 
389
+ function cropPage(page) {
390
+ if (page) {
391
+ if (page.length > 100) {
392
+ page = page.substring(0, 100);
393
+ }
394
+ if (page.startsWith('https://')) {
395
+ page = page.substring(8);
396
+ } else if (page.startsWith('http://')) {
397
+ page = page.substring(7);
398
+ }
399
+ if (page.startsWith('www.')) {
400
+ page = page.substring(4);
401
+ }
402
+ for (let i = 3; i < page.length; i++) {
403
+ const c = page[i];
404
+ if (c === '#' || c === '?') {
405
+ return page.substring(0, i);
406
+ }
407
+ }
408
+ return page;
409
+ }
410
+ return '';
411
+ }
412
+
388
413
  function clearEmpties(o) {
389
414
  for (let k in o) {
390
415
  if (o[k] === null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prebid.js",
3
- "version": "8.40.0",
3
+ "version": "8.41.0",
4
4
  "description": "Header Bidding Management Library",
5
5
  "main": "src/prebid.js",
6
6
  "scripts": {
@@ -6,6 +6,18 @@ import spec, {self as exports} from 'modules/automatadAnalyticsAdapter.js';
6
6
  import CONSTANTS from 'src/constants.json';
7
7
  import { expect } from 'chai';
8
8
 
9
+ const obj = {
10
+ auctionInitHandler: (args) => {},
11
+ bidResponseHandler: (args) => {},
12
+ bidderDoneHandler: (args) => {},
13
+ bidWonHandler: (args) => {},
14
+ noBidHandler: (args) => {},
15
+ auctionDebugHandler: (args) => {},
16
+ bidderTimeoutHandler: (args) => {},
17
+ bidRequestedHandler: (args) => {},
18
+ bidRejectedHandler: (args) => {}
19
+ }
20
+
9
21
  const {
10
22
  AUCTION_DEBUG,
11
23
  BID_REQUESTED,
@@ -117,20 +129,10 @@ describe('Automatad Analytics Adapter', () => {
117
129
  describe('Behaviour of the adapter when the sdk has loaded', () => {
118
130
  before(() => {
119
131
  spec.enableAnalytics(CONFIG_WITH_DEBUG);
120
- const obj = {
121
- auctionInitHandler: (args) => {},
122
- bidResponseHandler: (args) => {},
123
- bidderDoneHandler: (args) => {},
124
- bidWonHandler: (args) => {},
125
- noBidHandler: (args) => {},
126
- auctionDebugHandler: (args) => {},
127
- bidderTimeoutHandler: (args) => {},
128
- bidRequestedHandler: (args) => {},
129
- bidRejectedHandler: (args) => {}
130
- }
131
132
 
132
133
  global.window.atmtdAnalytics = obj
133
-
134
+ exports.qBeingUsed = false
135
+ exports.qTraversalComplete = undefined
134
136
  Object.keys(obj).forEach((fn) => sandbox.spy(global.window.atmtdAnalytics, fn))
135
137
  })
136
138
  beforeEach(() => {
@@ -143,8 +145,12 @@ describe('Automatad Analytics Adapter', () => {
143
145
  sandbox.restore();
144
146
  });
145
147
  after(() => {
148
+ const handlers = global.window.atmtdAnalytics
149
+ Object.keys(handlers).forEach((handler) => global.window.atmtdAnalytics[handler].reset())
146
150
  global.window.atmtdAnalytics = undefined;
147
151
  spec.disableAnalytics();
152
+ exports.qBeingUsed = false
153
+ exports.qTraversalComplete = undefined
148
154
  })
149
155
 
150
156
  it('Should call the auctionInitHandler when the auction init event is fired', () => {
@@ -298,6 +304,85 @@ describe('Automatad Analytics Adapter', () => {
298
304
  });
299
305
  });
300
306
 
307
+ describe('Behaviour of the adapter when the SDK has loaded midway', () => {
308
+ before(() => {
309
+ spec.enableAnalytics(CONFIG_WITH_DEBUG);
310
+ })
311
+ beforeEach(() => {
312
+ sandbox = sinon.createSandbox();
313
+
314
+ global.window.atmtdAnalytics = undefined
315
+
316
+ exports.qBeingUsed = undefined
317
+ exports.qTraversalComplete = undefined
318
+ exports.queuePointer = 0
319
+ exports.retryCount = 0
320
+ exports.__atmtdAnalyticsQueue.length = 0
321
+
322
+ clock = sandbox.useFakeTimers();
323
+
324
+ sandbox.spy(exports.__atmtdAnalyticsQueue, 'push')
325
+ });
326
+ afterEach(() => {
327
+ sandbox.restore();
328
+ });
329
+ after(() => {
330
+ spec.disableAnalytics();
331
+ })
332
+
333
+ it('Should push to the que when the auctionInit event is fired and push to the que even after SDK has loaded after auctionInit event', () => {
334
+ events.emit(BID_RESPONSE, {type: BID_RESPONSE})
335
+ expect(exports.__atmtdAnalyticsQueue.push.called).to.equal(true)
336
+ expect(exports.__atmtdAnalyticsQueue).to.be.an('array').to.have.lengthOf(1)
337
+ expect(exports.__atmtdAnalyticsQueue[0]).to.have.lengthOf(2)
338
+ expect(exports.__atmtdAnalyticsQueue[0][0]).to.equal(BID_RESPONSE)
339
+ expect(exports.__atmtdAnalyticsQueue[0][1].type).to.equal(BID_RESPONSE)
340
+ expect(exports.qBeingUsed).to.equal(true)
341
+ expect(exports.qTraversalComplete).to.equal(undefined)
342
+ global.window.atmtdAnalytics = obj
343
+ events.emit(BID_RESPONSE, {type: BID_RESPONSE})
344
+ expect(exports.__atmtdAnalyticsQueue.push.calledTwice).to.equal(true)
345
+ expect(exports.__atmtdAnalyticsQueue).to.be.an('array').to.have.lengthOf(2)
346
+ expect(exports.__atmtdAnalyticsQueue[1]).to.have.lengthOf(2)
347
+ expect(exports.__atmtdAnalyticsQueue[1][0]).to.equal(BID_RESPONSE)
348
+ expect(exports.__atmtdAnalyticsQueue[1][1].type).to.equal(BID_RESPONSE)
349
+ expect(exports.qBeingUsed).to.equal(true)
350
+ expect(exports.qTraversalComplete).to.equal(undefined)
351
+ });
352
+
353
+ it('Should push to the que when the auctionInit event is fired and push to the analytics adapter handler after the que is processed', () => {
354
+ expect(exports.qBeingUsed).to.equal(undefined)
355
+ events.emit(AUCTION_INIT, {type: AUCTION_INIT})
356
+ global.window.atmtdAnalytics = {...obj}
357
+ const handlers = global.window.atmtdAnalytics
358
+ Object.keys(handlers).forEach((handler) => global.window.atmtdAnalytics[handler].reset())
359
+ expect(exports.__atmtdAnalyticsQueue.push.called).to.equal(true)
360
+ expect(exports.__atmtdAnalyticsQueue).to.be.an('array').to.have.lengthOf(1)
361
+ expect(exports.__atmtdAnalyticsQueue[0]).to.have.lengthOf(2)
362
+ expect(exports.__atmtdAnalyticsQueue[0][0]).to.equal(AUCTION_INIT)
363
+ expect(exports.__atmtdAnalyticsQueue[0][1].type).to.equal(AUCTION_INIT)
364
+ expect(exports.qBeingUsed).to.equal(true)
365
+ expect(exports.qTraversalComplete).to.equal(undefined)
366
+ expect(global.window.atmtdAnalytics.auctionInitHandler.callCount).to.equal(0)
367
+ clock.tick(2000)
368
+ expect(exports.qBeingUsed).to.equal(true)
369
+ expect(exports.qTraversalComplete).to.equal(undefined)
370
+ events.emit(NO_BID, {type: NO_BID})
371
+ expect(exports.__atmtdAnalyticsQueue).to.be.an('array').to.have.lengthOf(2)
372
+ expect(exports.__atmtdAnalyticsQueue.push.calledTwice).to.equal(true)
373
+ clock.tick(1500)
374
+ expect(exports.qBeingUsed).to.equal(false)
375
+ expect(exports.qTraversalComplete).to.equal(true)
376
+ events.emit(BID_RESPONSE, {type: BID_RESPONSE})
377
+ expect(exports.__atmtdAnalyticsQueue).to.be.an('array').to.have.lengthOf(2)
378
+ expect(exports.__atmtdAnalyticsQueue.push.calledTwice).to.equal(true)
379
+ expect(exports.__atmtdAnalyticsQueue.push.calledThrice).to.equal(false)
380
+ expect(global.window.atmtdAnalytics.auctionInitHandler.calledOnce).to.equal(true)
381
+ expect(global.window.atmtdAnalytics.noBidHandler.calledOnce).to.equal(true)
382
+ expect(global.window.atmtdAnalytics.bidResponseHandler.calledOnce).to.equal(true)
383
+ });
384
+ });
385
+
301
386
  describe('Process Events from Que when SDK still has not loaded', () => {
302
387
  before(() => {
303
388
  spec.enableAnalytics({
@@ -312,6 +397,8 @@ describe('Automatad Analytics Adapter', () => {
312
397
  sandbox.stub(exports.__atmtdAnalyticsQueue, 'push').callsFake((args) => {
313
398
  Array.prototype.push.apply(exports.__atmtdAnalyticsQueue, [args]);
314
399
  })
400
+ exports.queuePointer = 0;
401
+ exports.retryCount = 0;
315
402
  })
316
403
  beforeEach(() => {
317
404
  sandbox = sinon.createSandbox();
@@ -326,7 +413,6 @@ describe('Automatad Analytics Adapter', () => {
326
413
  sandbox.restore();
327
414
  exports.queuePointer = 0;
328
415
  exports.retryCount = 0;
329
- exports.__atmtdAnalyticsQueue = []
330
416
  spec.disableAnalytics();
331
417
  })
332
418
 
@@ -437,7 +523,6 @@ describe('Automatad Analytics Adapter', () => {
437
523
  }
438
524
  });
439
525
  sandbox = sinon.createSandbox();
440
- sandbox.reset()
441
526
  const obj = {
442
527
  auctionInitHandler: (args) => {},
443
528
  bidResponseHandler: (args) => {},
@@ -473,8 +558,10 @@ describe('Automatad Analytics Adapter', () => {
473
558
  ['impressionViewable', {type: 'impressionViewable'}]
474
559
  ]
475
560
  });
476
- after(() => {
561
+ afterEach(() => {
477
562
  sandbox.restore();
563
+ })
564
+ after(() => {
478
565
  spec.disableAnalytics();
479
566
  })
480
567
 
@@ -219,7 +219,7 @@ describe('discovery:BidAdapterTests', function () {
219
219
  storage.getCookie.callsFake(() => 'existing-uuid');
220
220
  const uid = getPmgUID();
221
221
  expect(uid).to.equal('existing-uuid');
222
- expect(storage.setCookie.called).to.be.false;
222
+ expect(storage.setCookie.called).to.be.true;
223
223
  });
224
224
 
225
225
  it('should not set new UUID when cookies are not enabled', () => {
@@ -92,7 +92,7 @@ const mockBidRequest = {
92
92
  placement_slug: 'test_placement',
93
93
  provider_version: '0.0.1',
94
94
  provider_name: 'prebid',
95
- referrer: 'https://example.com',
95
+ location: 'https://example.com',
96
96
  sdk_version: '7.51.0-pre',
97
97
  sizes: [[728, 90]],
98
98
  wids: [],
@@ -160,6 +160,9 @@ describe('hypelabBidAdapter', function () {
160
160
  expect(data.bidRequestsCount).to.be.a('number');
161
161
  expect(data.bidderRequestsCount).to.be.a('number');
162
162
  expect(data.bidderWinsCount).to.be.a('number');
163
+ expect(data.dpr).to.be.a('number');
164
+ expect(data.location).to.be.a('string');
165
+ expect(data.floor).to.equal(null);
163
166
  });
164
167
 
165
168
  describe('should set uuid to the first id in userIdAsEids', () => {
@@ -211,6 +214,7 @@ describe('hypelabBidAdapter', function () {
211
214
  expect(data.ad).to.be.a('string');
212
215
  expect(data.mediaType).to.be.a('string');
213
216
  expect(data.meta.advertiserDomains).to.be.an('array');
217
+ expect(data.meta.advertiserDomains[0]).to.be.a('string');
214
218
  });
215
219
 
216
220
  describe('should return a blank array if cpm is not set', () => {