prebid.js 7.31.0 → 7.32.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 (180) hide show
  1. package/dist/33acrossBidAdapter.js +1 -1
  2. package/dist/33acrossIdSystem.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/adlooxRtdProvider.js +1 -1
  7. package/dist/adrelevantisBidAdapter.js +1 -1
  8. package/dist/adtrgtmeBidAdapter.js +1 -1
  9. package/dist/adxcgBidAdapter.js +1 -1
  10. package/dist/aidemBidAdapter.js +1 -1
  11. package/dist/ajaBidAdapter.js +1 -1
  12. package/dist/alkimiBidAdapter.js +1 -1
  13. package/dist/amxBidAdapter.js +1 -1
  14. package/dist/amxIdSystem.js +1 -1
  15. package/dist/aolBidAdapter.js +1 -1
  16. package/dist/appierAnalyticsAdapter.js +1 -1
  17. package/dist/appnexusBidAdapter.js +1 -1
  18. package/dist/appushBidAdapter.js +1 -0
  19. package/dist/asoBidAdapter.js +1 -1
  20. package/dist/axonixBidAdapter.js +1 -1
  21. package/dist/bidglassBidAdapter.js +1 -1
  22. package/dist/big-richmediaBidAdapter.js +1 -1
  23. package/dist/bridgewellBidAdapter.js +1 -1
  24. package/dist/brightMountainMediaBidAdapter.js +1 -1
  25. package/dist/carodaBidAdapter.js +1 -1
  26. package/dist/chtnwBidAdapter.js +1 -1
  27. package/dist/concertBidAdapter.js +1 -1
  28. package/dist/connectIdSystem.js +1 -1
  29. package/dist/connectadBidAdapter.js +1 -1
  30. package/dist/consumableBidAdapter.js +1 -1
  31. package/dist/conversantBidAdapter.js +1 -1
  32. package/dist/craftBidAdapter.js +1 -1
  33. package/dist/criteoBidAdapter.js +1 -1
  34. package/dist/dspxBidAdapter.js +1 -1
  35. package/dist/eplanningBidAdapter.js +1 -1
  36. package/dist/feedadBidAdapter.js +1 -1
  37. package/dist/finativeBidAdapter.js +1 -1
  38. package/dist/glimpseBidAdapter.js +1 -1
  39. package/dist/gmosspBidAdapter.js +1 -1
  40. package/dist/goldbachBidAdapter.js +1 -1
  41. package/dist/gridBidAdapter.js +1 -1
  42. package/dist/gridNMBidAdapter.js +1 -1
  43. package/dist/gumgumBidAdapter.js +1 -1
  44. package/dist/h12mediaBidAdapter.js +1 -1
  45. package/dist/holidBidAdapter.js +1 -0
  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/jwplayerVideoProvider.js +1 -1
  53. package/dist/konduitAnalyticsAdapter.js +1 -1
  54. package/dist/kueezBidAdapter.js +1 -1
  55. package/dist/kueezRtbBidAdapter.js +1 -1
  56. package/dist/lassoBidAdapter.js +1 -1
  57. package/dist/lifestreetBidAdapter.js +1 -1
  58. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  59. package/dist/logicadBidAdapter.js +1 -1
  60. package/dist/loglyliftBidAdapter.js +1 -1
  61. package/dist/magniteAnalyticsAdapter.js +1 -1
  62. package/dist/malltvAnalyticsAdapter.js +1 -1
  63. package/dist/marsmediaBidAdapter.js +1 -1
  64. package/dist/mediafuseBidAdapter.js +1 -1
  65. package/dist/medianetRtdProvider.js +1 -1
  66. package/dist/mediasquareBidAdapter.js +1 -1
  67. package/dist/mgidBidAdapter.js +1 -1
  68. package/dist/minutemediaBidAdapter.js +1 -1
  69. package/dist/nexx360BidAdapter.js +1 -1
  70. package/dist/not-for-prod/prebid.js +126 -123
  71. package/dist/oguryBidAdapter.js +1 -1
  72. package/dist/onetagBidAdapter.js +1 -1
  73. package/dist/ooloAnalyticsAdapter.js +1 -1
  74. package/dist/orbitsoftBidAdapter.js +1 -0
  75. package/dist/outbrainBidAdapter.js +1 -1
  76. package/dist/parrableIdSystem.js +1 -1
  77. package/dist/permutiveRtdProvider.js +1 -1
  78. package/dist/pixfutureBidAdapter.js +1 -1
  79. package/dist/prebid-core.js +1 -1
  80. package/dist/publinkIdSystem.js +1 -1
  81. package/dist/pubmaticBidAdapter.js +1 -1
  82. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  83. package/dist/pxyzBidAdapter.js +1 -1
  84. package/dist/quantcastBidAdapter.js +1 -1
  85. package/dist/readpeakBidAdapter.js +1 -1
  86. package/dist/relaidoBidAdapter.js +1 -1
  87. package/dist/rhythmoneBidAdapter.js +1 -1
  88. package/dist/riseBidAdapter.js +1 -1
  89. package/dist/rubiconAnalyticsAdapter.js +1 -1
  90. package/dist/rubiconBidAdapter.js +1 -1
  91. package/dist/seedingAllianceBidAdapter.js +1 -1
  92. package/dist/seedtagBidAdapter.js +1 -1
  93. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  94. package/dist/sharethroughBidAdapter.js +1 -1
  95. package/dist/shinezBidAdapter.js +1 -1
  96. package/dist/smaatoBidAdapter.js +1 -1
  97. package/dist/smartadserverBidAdapter.js +1 -1
  98. package/dist/smartxBidAdapter.js +1 -1
  99. package/dist/smilewantedBidAdapter.js +1 -1
  100. package/dist/sonobiBidAdapter.js +1 -1
  101. package/dist/sovrnAnalyticsAdapter.js +1 -1
  102. package/dist/sovrnBidAdapter.js +1 -1
  103. package/dist/sspBCBidAdapter.js +1 -1
  104. package/dist/sublimeBidAdapter.js +1 -1
  105. package/dist/synacormediaBidAdapter.js +1 -1
  106. package/dist/taboolaBidAdapter.js +1 -1
  107. package/dist/targetVideoBidAdapter.js +1 -1
  108. package/dist/teadsBidAdapter.js +1 -1
  109. package/dist/trionBidAdapter.js +1 -1
  110. package/dist/tripleliftBidAdapter.js +1 -1
  111. package/dist/ttdBidAdapter.js +1 -1
  112. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  113. package/dist/uid2IdSystem.js +1 -1
  114. package/dist/underdogmediaBidAdapter.js +1 -1
  115. package/dist/undertoneBidAdapter.js +1 -1
  116. package/dist/vidazooBidAdapter.js +1 -1
  117. package/dist/videobyteBidAdapter.js +1 -1
  118. package/dist/visxBidAdapter.js +1 -1
  119. package/dist/vuukleBidAdapter.js +1 -1
  120. package/dist/widespaceBidAdapter.js +1 -1
  121. package/dist/winrBidAdapter.js +1 -1
  122. package/dist/yahoosspBidAdapter.js +1 -1
  123. package/dist/yieldlabBidAdapter.js +1 -1
  124. package/dist/yieldmoBidAdapter.js +1 -1
  125. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  126. package/integrationExamples/gpt/adloox.html +5 -0
  127. package/modules/adagioBidAdapter.js +0 -4
  128. package/modules/adagioBidAdapter.md +4 -22
  129. package/modules/adlooxAnalyticsAdapter.md +5 -3
  130. package/modules/adlooxRtdProvider.js +82 -278
  131. package/modules/adlooxRtdProvider.md +6 -6
  132. package/modules/aidemBidAdapter.js +4 -0
  133. package/modules/aidemBidAdapter.md +1 -0
  134. package/modules/alkimiBidAdapter.js +23 -6
  135. package/modules/aolBidAdapter.js +12 -0
  136. package/modules/appnexusBidAdapter.js +2 -2
  137. package/modules/appushBidAdapter.js +188 -0
  138. package/modules/appushBidAdapter.md +79 -0
  139. package/modules/asoBidAdapter.js +8 -5
  140. package/modules/confiantRtdProvider.js +1 -1
  141. package/modules/connectIdSystem.js +15 -1
  142. package/modules/feedadBidAdapter.js +7 -5
  143. package/modules/holidBidAdapter.js +170 -0
  144. package/modules/holidBidAdapter.md +36 -0
  145. package/modules/jwplayerVideoProvider.js +10 -3
  146. package/modules/kueezRtbBidAdapter.js +21 -8
  147. package/modules/medianetRtdProvider.js +4 -4
  148. package/modules/nexx360BidAdapter.js +5 -7
  149. package/modules/orbitsoftBidAdapter.js +150 -0
  150. package/modules/permutiveRtdProvider.js +1 -1
  151. package/modules/riseBidAdapter.js +2 -1
  152. package/modules/riseBidAdapter.md +2 -0
  153. package/modules/seedtagBidAdapter.js +12 -0
  154. package/modules/smartxBidAdapter.js +6 -0
  155. package/modules/taboolaBidAdapter.js +61 -14
  156. package/modules/yahoosspBidAdapter.js +5 -0
  157. package/modules/yieldlabBidAdapter.js +150 -134
  158. package/modules/yieldmoBidAdapter.js +1 -12
  159. package/package.json +1 -1
  160. package/test/spec/modules/adagioBidAdapter_spec.js +1 -28
  161. package/test/spec/modules/adlooxRtdProvider_spec.js +28 -120
  162. package/test/spec/modules/aidemBidAdapter_spec.js +10 -2
  163. package/test/spec/modules/alkimiBidAdapter_spec.js +15 -3
  164. package/test/spec/modules/aolBidAdapter_spec.js +22 -0
  165. package/test/spec/modules/appnexusBidAdapter_spec.js +7 -3
  166. package/test/spec/modules/appushBidAdapter_spec.js +372 -0
  167. package/test/spec/modules/connectIdSystem_spec.js +17 -5
  168. package/test/spec/modules/feedadBidAdapter_spec.js +23 -1
  169. package/test/spec/modules/holidBidAdapter_spec.js +165 -0
  170. package/test/spec/modules/kueezRtbBidAdapter_spec.js +147 -24
  171. package/test/spec/modules/medianetRtdProvider_spec.js +3 -3
  172. package/test/spec/modules/orbitsoftBidAdapter_spec.js +255 -0
  173. package/test/spec/modules/riseBidAdapter_spec.js +7 -0
  174. package/test/spec/modules/seedtagBidAdapter_spec.js +56 -10
  175. package/test/spec/modules/smartxBidAdapter_spec.js +10 -0
  176. package/test/spec/modules/taboolaBidAdapter_spec.js +142 -5
  177. package/test/spec/modules/videoModule/submodules/jwplayerVideoProvider_spec.js +45 -10
  178. package/test/spec/modules/yahoosspBidAdapter_spec.js +16 -1
  179. package/test/spec/modules/yieldlabBidAdapter_spec.js +311 -301
  180. package/test/spec/modules/yieldmoBidAdapter_spec.js +70 -0
@@ -6,11 +6,13 @@
6
6
  * @module modules/adlooxRtdProvider
7
7
  * @requires module:modules/realTimeData
8
8
  * @requires module:modules/adlooxAnalyticsAdapter
9
+ * @optional module:modules/intersectionRtdProvider
9
10
  */
10
11
 
11
12
  /* eslint standard/no-callback-literal: "off" */
12
13
  /* eslint prebid/validate-imports: "off" */
13
14
 
15
+ import {auctionManager} from '../src/auctionManager.js';
14
16
  import {command as analyticsCommand, COMMAND} from './adlooxAnalyticsAdapter.js';
15
17
  import {submodule} from '../src/hook.js';
16
18
  import {ajax} from '../src/ajax.js';
@@ -18,142 +20,31 @@ import {getGlobal} from '../src/prebidGlobal.js';
18
20
  import {getRefererInfo} from '../src/refererDetection.js';
19
21
  import {
20
22
  _each,
23
+ _map,
24
+ buildUrl,
21
25
  deepAccess,
26
+ deepClone,
22
27
  deepSetValue,
23
- getAdUnitSizes,
24
28
  getGptSlotInfoForAdUnitCode,
25
29
  isArray,
26
30
  isBoolean,
27
31
  isInteger,
28
32
  isPlainObject,
29
- isStr,
30
33
  logError,
31
34
  logInfo,
32
35
  logWarn,
33
- mergeDeep
36
+ mergeDeep,
37
+ parseUrl,
38
+ safeJSONParse
34
39
  } from '../src/utils.js';
35
- import {includes} from '../src/polyfill.js';
36
40
 
37
41
  const MODULE_NAME = 'adloox';
38
42
  const MODULE = `${MODULE_NAME}RtdProvider`;
39
43
 
40
44
  const API_ORIGIN = 'https://p.adlooxtracking.com';
41
45
  const SEGMENT_HISTORIC = { 'a': 'aud', 'd': 'dis', 'v': 'vid' };
42
- const SEGMENT_HISTORIC_VALUES = Object.keys(SEGMENT_HISTORIC).map(k => SEGMENT_HISTORIC[k]);
43
46
 
44
- const ADSERVER_TARGETING_PREFIX = 'adl_';
45
-
46
- const CREATIVE_WIDTH_MIN = 20;
47
- const CREATIVE_HEIGHT_MIN = 20;
48
- const CREATIVE_AREA_MIN = CREATIVE_WIDTH_MIN * CREATIVE_HEIGHT_MIN;
49
- // try to avoid using IntersectionObserver as it has unbounded (observed multi-second) latency
50
- let intersectionObserver = window == top ? false : undefined;
51
- const intersectionObserverElements = [];
52
- // .map/.findIndex are safe here as they are only used for intersectionObserver
53
- function atf(adUnit, cb) {
54
- analyticsCommand(COMMAND.TOSELECTOR, { bid: { adUnitCode: adUnit.code } }, function(selector) {
55
- const element = document.querySelector(selector);
56
- if (!element) return cb(null);
57
-
58
- if (window.getComputedStyle(element)['display'] == 'none') return cb(NaN);
59
-
60
- try {
61
- // short circuit for cross-origin
62
- if (intersectionObserver) throw false;
63
-
64
- // Google's advice is to collapse slots on no fill but
65
- // we have to cater to clients that grow slots on fill
66
- const rect = (function(rect) {
67
- const sizes = getAdUnitSizes(adUnit);
68
-
69
- if (sizes.length == 0) return false;
70
- // interstitial (0x0, 1x1)
71
- if (sizes.length == 1 && (sizes[0][0] * sizes[0][1]) <= 1) return true;
72
- // try to catch premium slots (coord=0,0) as they will likely bounce into view
73
- if (rect.top <= -window.pageYOffset && rect.left <= -window.pageXOffset && rect.top == rect.bottom) return true;
74
-
75
- // pick the smallest creative size as many publishers will just leave the element unbounded in the vertical
76
- let width = Infinity;
77
- let height = Infinity;
78
- for (let i = 0; i < sizes.length; i++) {
79
- const area = sizes[i][0] * sizes[i][1];
80
- if (area < CREATIVE_AREA_MIN) continue;
81
- if (area < (width * height)) {
82
- width = sizes[i][0];
83
- height = sizes[i][1];
84
- }
85
- }
86
- // we also scale the smallest size to the size of the slot as publishers resize units depending on viewport
87
- const scale = Math.min(1, (rect.right - rect.left) / width);
88
-
89
- return {
90
- left: rect.left,
91
- right: rect.left + Math.max(CREATIVE_WIDTH_MIN, scale * width),
92
- top: rect.top,
93
- bottom: rect.top + Math.max(CREATIVE_HEIGHT_MIN, scale * height)
94
- };
95
- })(element.getBoundingClientRect());
96
-
97
- if (rect === false) return cb(NaN);
98
- if (rect === true) return cb(1);
99
-
100
- const W = rect.right - rect.left;
101
- const H = rect.bottom - rect.top;
102
-
103
- if (W * H < CREATIVE_AREA_MIN) return cb(NaN);
104
-
105
- let el;
106
- let win = window;
107
- while (1) {
108
- // https://stackoverflow.com/a/8876069
109
- const vw = Math.max(win.document.documentElement.clientWidth || 0, win.innerWidth || 0);
110
- const vh = Math.max(win.document.documentElement.clientHeight || 0, win.innerHeight || 0);
111
-
112
- // cut to viewport
113
- rect.left = Math.min(Math.max(rect.left, 0), vw);
114
- rect.right = Math.min(Math.max(rect.right, 0), vw);
115
- rect.top = Math.min(Math.max(rect.top, 0), vh);
116
- rect.bottom = Math.min(Math.max(rect.bottom, 0), vh);
117
-
118
- if (win == top) return cb(((rect.right - rect.left) * (rect.bottom - rect.top)) / (W * H));
119
- el = win.frameElement;
120
- if (!el) throw false; // cross-origin
121
- win = win.parent;
122
-
123
- // transpose to frame element
124
- const frameElementRect = el.getBoundingClientRect();
125
- rect.left += frameElementRect.left;
126
- rect.right = Math.min(rect.right + frameElementRect.left, frameElementRect.right);
127
- rect.top += frameElementRect.top;
128
- rect.bottom = Math.min(rect.bottom + frameElementRect.top, frameElementRect.bottom);
129
- }
130
- } catch (_) {
131
- if (intersectionObserver === undefined) {
132
- try {
133
- intersectionObserver = new IntersectionObserver(function(entries) {
134
- entries.forEach(entry => {
135
- const ratio = entry.intersectionRect.width * entry.intersectionRect.height < CREATIVE_AREA_MIN ? NaN : entry.intersectionRatio;
136
- const idx = intersectionObserverElements.findIndex(x => x.element == entry.target);
137
- intersectionObserverElements[idx].cb.forEach(cb => cb(ratio));
138
- intersectionObserverElements.splice(idx, 1);
139
- intersectionObserver.unobserve(entry.target);
140
- });
141
- });
142
- } catch (_) {
143
- intersectionObserver = false;
144
- }
145
- }
146
- if (!intersectionObserver) return cb(null);
147
- const idx = intersectionObserverElements.findIndex(x => x.element == element);
148
- if (idx == -1) {
149
- intersectionObserverElements.push({ element, cb: [ cb ] });
150
- intersectionObserver.observe(element);
151
- } else {
152
- intersectionObserverElements[idx].cb.push(cb);
153
- }
154
- }
155
- });
156
- }
47
+ const ADSERVER_TARGETING_PREFIX = 'adl';
157
48
 
158
49
  function init(config, userConsent) {
159
50
  logInfo(MODULE, 'init', config, userConsent);
@@ -167,10 +58,6 @@ function init(config, userConsent) {
167
58
  logError(MODULE, 'invalid params');
168
59
  return false;
169
60
  }
170
- if (!(config.params.api_origin === undefined || isStr(config.params.api_origin))) {
171
- logError(MODULE, 'invalid api_origin params value');
172
- return false;
173
- }
174
61
  if (!(config.params.imps === undefined || (isInteger(config.params.imps) && config.params.imps > 0))) {
175
62
  logError(MODULE, 'invalid imps params value');
176
63
  return false;
@@ -213,193 +100,110 @@ function init(config, userConsent) {
213
100
  }
214
101
 
215
102
  function getBidRequestData(reqBidsConfigObj, callback, config, userConsent) {
216
- // gptPreAuction runs *after* RTD so pbadslot may not be populated... (╯°□°)╯ ┻━┻
217
- const adUnits = (reqBidsConfigObj.adUnits || getGlobal().adUnits).map(adUnit => {
218
- return {
219
- gpid: deepAccess(adUnit, 'ortb2Imp.ext.gpid') || deepAccess(adUnit, 'ortb2Imp.ext.data.pbadslot') || getGptSlotInfoForAdUnitCode(adUnit.code).gptSlot || adUnit.code,
220
- unit: adUnit
221
- };
222
- }).filter(adUnit => !!adUnit.gpid);
223
-
224
- let response = {};
225
- function setSegments() {
226
- function val(v, k) {
227
- if (!((SEGMENT_HISTORIC[k] || k == 'atf') && v >= 0)) return v;
228
- return config.params.thresholds.filter(t => t <= v);
229
- }
230
-
231
- const ortb2 = reqBidsConfigObj.ortb2Fragments?.global || {};
232
- const dataSite = deepAccess(ortb2, 'site.ext.data') || {};
233
- const dataUser = deepAccess(ortb2, 'user.ext.data') || {};
234
-
235
- _each(response, (v0, k0) => {
236
- if (k0 == '_') return;
237
- const k = SEGMENT_HISTORIC[k0] || k0;
238
- const v = val(v0, k0);
239
- deepSetValue(k == k0 ? dataUser : dataSite, `${MODULE_NAME}_rtd.${k}`, v);
240
- });
241
- deepSetValue(dataSite, `${MODULE_NAME}_rtd.ok`, true);
103
+ const adUnits0 = reqBidsConfigObj.adUnits || getGlobal().adUnits;
104
+ // adUnits must be ordered according to adUnitCodes for stable 's' param usage and handling the response below
105
+ const adUnits = reqBidsConfigObj.adUnitCodes.map(code => adUnits0.find(unit => unit.code == code));
106
+
107
+ // buildUrl creates PHP style multi-parameters and includes undefined... (╯°□°)╯ ┻━┻
108
+ const url = buildUrl(mergeDeep(parseUrl(`${API_ORIGIN}/q`), { search: {
109
+ 'v': `pbjs-${getGlobal().version}`,
110
+ 'c': config.params.clientid,
111
+ 'p': config.params.platformid,
112
+ 't': config.params.tagid,
113
+ 'imp': config.params.imps,
114
+ 'fc_ip': config.params.freqcap_ip,
115
+ 'fc_ipua': config.params.freqcap_ipua,
116
+ 'pn': (getRefererInfo().page || '').substr(0, 300).split(/[?#]/)[0],
117
+ 's': _map(adUnits, function(unit) {
118
+ // gptPreAuction runs *after* RTD so pbadslot may not be populated... (╯°□°)╯ ┻━┻
119
+ const gpid = deepAccess(unit, 'ortb2Imp.ext.gpid') ||
120
+ deepAccess(unit, 'ortb2Imp.ext.data.pbadslot') ||
121
+ getGptSlotInfoForAdUnitCode(unit.code).gptSlot ||
122
+ unit.code;
123
+ const ref = [ gpid ];
124
+ if (!config.params.slotinpath) ref.push(unit.code);
125
+ return ref.join('\t');
126
+ })
127
+ } })).replace(/\[\]|[^?&]+=undefined/g, '').replace(/([?&])&+/g, '$1');
128
+
129
+ ajax(url,
130
+ function(responseText, q) {
131
+ function val(v, k) {
132
+ if (!(SEGMENT_HISTORIC[k] && v >= 0)) return v;
133
+ return config.params.thresholds.filter(t => t <= v);
134
+ }
242
135
 
243
- deepSetValue(ortb2, 'site.ext.data', dataSite);
244
- deepSetValue(ortb2, 'user.ext.data', dataUser);
245
- deepSetValue(reqBidsConfigObj, 'ortb2Fragments.global', ortb2);
136
+ const response = safeJSONParse(responseText);
137
+ if (!response) {
138
+ logError(MODULE, 'unexpected response');
139
+ return callback();
140
+ }
246
141
 
247
- adUnits.forEach((adUnit, i) => {
248
- _each(response['_'][i], (v0, k0) => {
142
+ const { site: ortb2site, user: ortb2user } = reqBidsConfigObj.ortb2Fragments.global;
143
+ _each(response, function(v0, k0) {
144
+ if (k0 == '_') return;
249
145
  const k = SEGMENT_HISTORIC[k0] || k0;
250
146
  const v = val(v0, k0);
251
- deepSetValue(adUnit.unit, `ortb2Imp.ext.data.${MODULE_NAME}_rtd.${k}`, v);
147
+ deepSetValue(k == k0 ? ortb2user : ortb2site, `ext.data.${MODULE_NAME}_rtd.${k}`, v);
252
148
  });
253
- });
254
- };
255
-
256
- // mergeDeep does not handle merging deep arrays... (╯°□°)╯ ┻━┻
257
- function mergeDeep(target, ...sources) {
258
- function emptyValue(v) {
259
- if (isPlainObject(v)) {
260
- return {};
261
- } else if (isArray(v)) {
262
- return [];
263
- } else {
264
- return undefined;
265
- }
266
- }
267
149
 
268
- if (!sources.length) return target;
269
- const source = sources.shift();
270
-
271
- if (isPlainObject(target) && isPlainObject(source)) {
272
- Object.keys(source).forEach(key => {
273
- if (!(key in target)) target[key] = emptyValue(source[key]);
274
- target[key] = target[key] !== undefined ? mergeDeep(target[key], source[key]) : source[key];
275
- });
276
- } else if (isArray(target) && isArray(source)) {
277
- source.forEach((v, i) => {
278
- if (!(i in target)) target[i] = emptyValue(v);
279
- target[i] = target[i] !== undefined ? mergeDeep(target[i], v) : v;
150
+ _each(response._, function(segments, i) {
151
+ _each(segments, function(v0, k0) {
152
+ const k = SEGMENT_HISTORIC[k0] || k0;
153
+ const v = val(v0, k0);
154
+ deepSetValue(adUnits[i], `ortb2Imp.ext.data.${MODULE_NAME}_rtd.${k}`, v);
155
+ });
280
156
  });
281
- } else {
282
- target = source;
283
- }
284
157
 
285
- return mergeDeep(target, ...sources);
286
- }
158
+ deepSetValue(ortb2site, `ext.data.${MODULE_NAME}_rtd.ok`, true);
287
159
 
288
- let semaphore = 1;
289
- function semaphoreInc(inc) {
290
- if (semaphore == 0) return;
291
- semaphore += inc;
292
- if (semaphore == 0) {
293
- setSegments()
294
160
  callback();
295
161
  }
296
- }
297
-
298
- const refererInfo = getRefererInfo();
299
- const args = [
300
- [ 'v', `pbjs-${getGlobal().version}` ],
301
- [ 'c', config.params.clientid ],
302
- [ 'p', config.params.platformid ],
303
- [ 't', config.params.tagid ],
304
- [ 'imp', config.params.imps ],
305
- [ 'fc_ip', config.params.freqcap_ip ],
306
- [ 'fc_ipua', config.params.freqcap_ipua ],
307
- [ 'pn', (refererInfo.page || '').substr(0, 300).split(/[?#]/)[0] ]
308
- ];
309
-
310
- if (!adUnits.length) {
311
- logWarn(MODULE, 'no suitable adUnits (missing pbadslot?)');
312
- }
313
- const atfQueue = [];
314
- adUnits.map((adUnit, i) => {
315
- const ref = [ adUnit.gpid ];
316
- if (!config.params.slotinpath) ref.push(adUnit.unit.code);
317
- args.push(['s', ref.join('\t')]);
318
-
319
- semaphoreInc(1);
320
- atfQueue.push(function() {
321
- atf(adUnit.unit, function(x) {
322
- let viewable = document.visibilityState === undefined || document.visibilityState == 'visible';
323
- try { viewable = viewable && top.document.hasFocus() } catch (_) {}
324
- logInfo(MODULE, `atf code=${adUnit.unit.code} has area=${x}, viewable=${viewable}`);
325
- const atfList = []; atfList[i] = { atf: parseInt(x * 100) };
326
- response = mergeDeep(response, { _: atfList });
327
- semaphoreInc(-1);
328
- });
329
- });
330
- });
331
- function atfCb() {
332
- atfQueue.forEach(x => x());
333
- }
334
- if (document.readyState == 'loading') {
335
- document.addEventListener('DOMContentLoaded', atfCb, false);
336
- } else {
337
- atfCb();
338
- }
339
-
340
- analyticsCommand(COMMAND.URL, {
341
- url: (config.params.api_origin || API_ORIGIN) + '/q?',
342
- args: args
343
- }, function(url) {
344
- ajax(url, {
345
- success: function(responseText, q) {
346
- try {
347
- if (q.getResponseHeader('content-type') == 'application/json') {
348
- response = mergeDeep(response, JSON.parse(responseText));
349
- } else {
350
- throw false;
351
- }
352
- } catch (_) {
353
- logError(MODULE, 'unexpected response');
354
- }
355
- semaphoreInc(-1);
356
- },
357
- error: function(statusText, q) {
358
- logError(MODULE, 'request failed');
359
- semaphoreInc(-1);
360
- }
361
- });
362
- });
162
+ );
363
163
  }
364
164
 
365
165
  function getTargetingData(adUnitArray, config, userConsent, auction) {
366
- function targetingNormalise(v) {
166
+ function val(v) {
367
167
  if (isArray(v) && v.length == 0) return undefined;
368
168
  if (isBoolean(v)) v = ~~v;
369
169
  if (!v) return undefined; // empty string and zero
370
170
  return v;
371
171
  }
372
172
 
373
- const ortb2 = auction.getFPD().global || {};
374
- const dataSite = deepAccess(ortb2, `site.ext.data.${MODULE_NAME}_rtd`) || {};
375
- if (!dataSite.ok) return {};
173
+ const { site: ortb2site, user: ortb2user } = auctionManager.index.getAuction(auction).getFPD().global;
376
174
 
377
- const dataUser = deepAccess(ortb2, `user.ext.data.${MODULE_NAME}_rtd`) || {};
378
- return getGlobal().adUnits.filter(adUnit => includes(adUnitArray, adUnit.code)).reduce((a, adUnit) => {
379
- a[adUnit.code] = {};
175
+ const ortb2base = {};
176
+ _each(deepAccess(mergeDeep(ortb2site, ortb2user), `ext.data.${MODULE_NAME}_rtd`), function(v0, k) {
177
+ const v = val(v0);
178
+ if (v) ortb2base[`${ADSERVER_TARGETING_PREFIX}_${k}`] = v;
179
+ });
380
180
 
381
- _each(dataSite, (v0, k) => {
382
- if (includes(SEGMENT_HISTORIC_VALUES, k)) return; // ignore site average viewability
383
- const v = targetingNormalise(v0);
384
- if (v) a[adUnit.code][ADSERVER_TARGETING_PREFIX + k] = v;
385
- });
181
+ const targeting = {};
182
+ _each(auction.adUnits.filter(unit => adUnitArray.includes(unit.code)), function(unit) {
183
+ targeting[unit.code] = deepClone(ortb2base);
386
184
 
387
- const adUnitSegments = deepAccess(adUnit, `ortb2Imp.ext.data.${MODULE_NAME}_rtd`, {});
388
- _each(Object.assign({}, dataUser, adUnitSegments), (v0, k) => {
389
- const v = targetingNormalise(v0);
390
- if (v) a[adUnit.code][ADSERVER_TARGETING_PREFIX + k] = v;
185
+ const ortb2imp = deepAccess(unit, `ortb2Imp.ext.data.${MODULE_NAME}_rtd`);
186
+ _each(ortb2imp, function(v0, k) {
187
+ const v = val(v0);
188
+ if (v) targeting[unit.code][`${ADSERVER_TARGETING_PREFIX}_${k}`] = v;
391
189
  });
392
190
 
393
- return a;
394
- }, {});
191
+ // ATF results shamelessly exfiltrated from intersectionRtdProvider
192
+ const bid = unit.bids.find(bid => !!bid.intersection);
193
+ if (bid) {
194
+ const v = val(config.params.thresholds.filter(t => t <= (bid.intersection.intersectionRatio * 100)));
195
+ if (v) targeting[unit.code][`${ADSERVER_TARGETING_PREFIX}_atf`] = v;
196
+ }
197
+ });
198
+
199
+ return targeting;
395
200
  }
396
201
 
397
202
  export const subModuleObj = {
398
203
  name: MODULE_NAME,
399
204
  init,
400
205
  getBidRequestData,
401
- getTargetingData,
402
- atf // used by adlooxRtdProvider_spec.js
206
+ getTargetingData
403
207
  };
404
208
 
405
209
  submodule('realTimeData', subModuleObj);
@@ -19,12 +19,7 @@ This provider fetches segments and populates the [First Party Data](https://docs
19
19
  * AdUnit segments are placed into `AdUnit.ortb2Imp.ext.data.adloox_rtd`:
20
20
  * **`{dis,vid,aud}`:** an list of integers describing the likelihood the AdUnit will be visible
21
21
  * **`atf`:** an list of integers describing the percentage of pixels visible at auction
22
- * measured only once at pre-auction
23
- * usable when the publisher uses the strategy of collapsing ad slots on no-fill
24
- * using the reverse strategy, growing ad slots on fill, invalidates the measurement the position of all content (including the slots) changes post-auction
25
- * works best when your page loads your ad slots have their actual size rendered (ie. not zero height)
26
- * uses the smallest ad unit (above a threshold area of 20x20) supplied by the [publisher to Prebid.js](https://docs.prebid.org/dev-docs/examples/basic-example.html) and measures viewability as if that size to be used
27
- * when used in cross-origin (unfriendly) IFRAME environments the ad slot is directly measured as is (ignoring publisher provided sizes) due to limitations in using [IntersectionObserver](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver)
22
+ * measured at pre-auction time using the [Intersection Module](https://docs.prebid.org/dev-docs/modules/intersectionRtdProvider.html); if not enabled then this measurement is not available
28
23
 
29
24
  **N.B.** this provider does not offer or utilise any user orientated data
30
25
 
@@ -57,8 +52,13 @@ To use this, you *must* also integrate the [Adloox Analytics Adapter](./adlooxAn
57
52
  realTimeData: {
58
53
  auctionDelay: 100, // see below for guidance
59
54
  dataProviders: [
55
+ {
56
+ name: 'intersection',
57
+ waitForIt: true
58
+ },
60
59
  {
61
60
  name: 'adloox',
61
+ waitForIt: true,
62
62
  params: { // optional, defaults shown
63
63
  thresholds: [ 50, 60, 70, 80, 90 ],
64
64
  slotinpath: false
@@ -220,6 +220,8 @@ function setPrebidImpressionObject(bidRequests, payload) {
220
220
  deepSetValue(impressionObject, 'id', bidRequest.bidId);
221
221
  // Transaction id
222
222
  deepSetValue(impressionObject, 'tid', deepAccess(bidRequest, 'transactionId'));
223
+ // Placement id
224
+ deepSetValue(impressionObject, 'tagid', deepAccess(bidRequest, 'params.placementId', null));
223
225
  // Publisher id
224
226
  deepSetValue(payload, 'site.publisher.id', deepAccess(bidRequest, 'params.publisherId'));
225
227
  // Site id
@@ -265,6 +267,8 @@ function setPrebidRequestEnvironment(payload) {
265
267
  deepSetValue(payload, 'environment.inp.jp', window.JSON.parse.name === 'parse' && typeof window.JSON.parse.prototype === 'undefined');
266
268
  deepSetValue(payload, 'environment.inp.ofe', window.Object.fromEntries.name === 'fromEntries' && typeof window.Object.fromEntries.prototype === 'undefined');
267
269
  deepSetValue(payload, 'environment.inp.oa', window.Object.assign.name === 'assign' && typeof window.Object.assign.prototype === 'undefined');
270
+ deepSetValue(payload, 'environment.wpar.innerWidth', window.innerWidth);
271
+ deepSetValue(payload, 'environment.wpar.innerHeight', window.innerHeight);
268
272
  }
269
273
 
270
274
  function setPrebidImpressionObjectFloor(bidRequest, impressionObject) {
@@ -18,6 +18,7 @@ This module is GDPR and CCPA compliant, and no 3rd party userIds are allowed.
18
18
  |---------------|----------|---------------------|---------------|----------|
19
19
  | `siteId` | required | Unique site ID | `'ABCDEF'` | `String` |
20
20
  | `publisherId` | required | Unique publisher ID | `'ABCDEF'` | `String` |
21
+ | `placementId` | optional | Unique publisher tag ID | `'ABCDEF'` | `String` |
21
22
 
22
23
 
23
24
  ### Banner Bid Params
@@ -20,18 +20,20 @@ export const spec = {
20
20
  let bidIds = [];
21
21
  let eids;
22
22
  validBidRequests.forEach(bidRequest => {
23
- let sizes = prepareSizes(bidRequest.sizes)
23
+ let formatType = getFormatType(bidRequest)
24
+ let alkimiSizes = prepareAlkimiSizes(bidRequest.sizes)
24
25
 
25
26
  if (bidRequest.userIdAsEids) {
26
27
  eids = eids || bidRequest.userIdAsEids
27
28
  }
29
+
28
30
  bids.push({
29
31
  token: bidRequest.params.token,
30
32
  pos: bidRequest.params.pos,
31
- bidFloor: bidRequest.params.bidFloor,
32
- width: sizes[0].width,
33
- height: sizes[0].height,
34
- impMediaType: getFormatType(bidRequest),
33
+ bidFloor: getBidFloor(bidRequest, formatType),
34
+ width: alkimiSizes[0].width,
35
+ height: alkimiSizes[0].height,
36
+ impMediaType: formatType,
35
37
  adUnitCode: bidRequest.adUnitCode
36
38
  })
37
39
  bidIds.push(bidRequest.bidId)
@@ -128,10 +130,25 @@ export const spec = {
128
130
  }
129
131
  }
130
132
 
131
- function prepareSizes(sizes) {
133
+ function prepareAlkimiSizes(sizes) {
132
134
  return sizes && sizes.map(size => ({ width: size[0], height: size[1] }));
133
135
  }
134
136
 
137
+ function prepareBidFloorSize(sizes) {
138
+ return sizes && sizes.length === 1 ? sizes[0] : '*';
139
+ }
140
+
141
+ function getBidFloor(bidRequest, formatType) {
142
+ if (typeof bidRequest.getFloor === 'function') {
143
+ const bidFloorSize = prepareBidFloorSize(bidRequest.sizes)
144
+ const floor = bidRequest.getFloor({ currency: 'USD', mediaType: formatType.toLowerCase(), size: bidFloorSize });
145
+ if (floor && !isNaN(floor.floor) && (floor.currency === 'USD')) {
146
+ return floor.floor;
147
+ }
148
+ }
149
+ return bidRequest.params.bidFloor;
150
+ }
151
+
135
152
  const getFormatType = bidRequest => {
136
153
  if (deepAccess(bidRequest, 'mediaTypes.banner')) return 'Banner'
137
154
  if (deepAccess(bidRequest, 'mediaTypes.video')) return 'Video'
@@ -159,6 +159,13 @@ export const spec = {
159
159
  if (bidderRequest) {
160
160
  consentData.gdpr = bidderRequest.gdprConsent;
161
161
  consentData.uspConsent = bidderRequest.uspConsent;
162
+ consentData.gppConsent = bidderRequest.gppConsent;
163
+ if (!consentData.gppConsent && bidderRequest.ortb2?.regs?.gpp) {
164
+ consentData.gppConsent = {
165
+ gppString: bidderRequest.ortb2.regs.gpp,
166
+ applicableSections: bidderRequest.ortb2.regs.gpp_sid
167
+ }
168
+ }
162
169
  }
163
170
 
164
171
  return bids.map(bid => {
@@ -373,6 +380,11 @@ export const spec = {
373
380
  params.us_privacy = consentData.uspConsent;
374
381
  }
375
382
 
383
+ if (consentData.gppConsent && consentData.gppConsent.gppString) {
384
+ params.gpp = consentData.gppConsent.gppString;
385
+ params.gpp_sid = consentData.gppConsent.applicableSections;
386
+ }
387
+
376
388
  return params;
377
389
  },
378
390
  parsePixelItems(pixels) {
@@ -625,9 +625,8 @@ function newBid(serverBid, rtbBid, bidderRequest) {
625
625
  }
626
626
  };
627
627
 
628
- // WE DON'T FULLY SUPPORT THIS ATM - future spot for adomain code; creating a stub for 5.0 compliance
629
628
  if (rtbBid.adomain) {
630
- bid.meta = Object.assign({}, bid.meta, { advertiserDomains: [] });
629
+ bid.meta = Object.assign({}, bid.meta, { advertiserDomains: [rtbBid.adomain] });
631
630
  }
632
631
 
633
632
  if (rtbBid.advertiser_id) {
@@ -731,6 +730,7 @@ function newBid(serverBid, rtbBid, bidderRequest) {
731
730
  displayUrl: nativeAd.displayurl,
732
731
  clickTrackers: nativeAd.link.click_trackers,
733
732
  impressionTrackers: nativeAd.impression_trackers,
733
+ video: nativeAd.video,
734
734
  javascriptTrackers: jsTrackers
735
735
  };
736
736
  if (nativeAd.main_img) {