prebid.js 7.35.0 → 7.36.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 (188) hide show
  1. package/.devcontainer/Dockerfile +2 -0
  2. package/dist/33acrossBidAdapter.js +1 -1
  3. package/dist/33acrossIdSystem.js +1 -1
  4. package/dist/adagioBidAdapter.js +1 -1
  5. package/dist/adbookpspBidAdapter.js +1 -1
  6. package/dist/adgenerationBidAdapter.js +1 -1
  7. package/dist/admaruBidAdapter.js +1 -1
  8. package/dist/adrelevantisBidAdapter.js +1 -1
  9. package/dist/adtrgtmeBidAdapter.js +1 -1
  10. package/dist/adxcgBidAdapter.js +1 -1
  11. package/dist/adyoulikeBidAdapter.js +1 -1
  12. package/dist/aidemBidAdapter.js +1 -1
  13. package/dist/ajaBidAdapter.js +1 -1
  14. package/dist/amxBidAdapter.js +1 -1
  15. package/dist/amxIdSystem.js +1 -1
  16. package/dist/aolBidAdapter.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/audiencerunBidAdapter.js +1 -1
  21. package/dist/axonixBidAdapter.js +1 -1
  22. package/dist/bidglassBidAdapter.js +1 -1
  23. package/dist/big-richmediaBidAdapter.js +1 -1
  24. package/dist/bluebillywigBidAdapter.js +1 -1
  25. package/dist/bridgewellBidAdapter.js +1 -1
  26. package/dist/brightMountainMediaBidAdapter.js +1 -1
  27. package/dist/brightcomBidAdapter.js +1 -1
  28. package/dist/brightcomSSPBidAdapter.js +1 -0
  29. package/dist/carodaBidAdapter.js +1 -1
  30. package/dist/chtnwBidAdapter.js +1 -1
  31. package/dist/concertBidAdapter.js +1 -1
  32. package/dist/connectadBidAdapter.js +1 -1
  33. package/dist/consumableBidAdapter.js +1 -1
  34. package/dist/conversantBidAdapter.js +1 -1
  35. package/dist/craftBidAdapter.js +1 -1
  36. package/dist/criteoBidAdapter.js +1 -1
  37. package/dist/cwireBidAdapter.js +1 -1
  38. package/dist/dependencies.json +3 -0
  39. package/dist/dspxBidAdapter.js +1 -1
  40. package/dist/eplanningBidAdapter.js +1 -1
  41. package/dist/feedadBidAdapter.js +1 -1
  42. package/dist/finativeBidAdapter.js +1 -1
  43. package/dist/freewheel-sspBidAdapter.js +1 -1
  44. package/dist/glimpseBidAdapter.js +1 -1
  45. package/dist/gmosspBidAdapter.js +1 -1
  46. package/dist/goldbachBidAdapter.js +1 -1
  47. package/dist/gridBidAdapter.js +1 -1
  48. package/dist/gridNMBidAdapter.js +1 -1
  49. package/dist/gumgumBidAdapter.js +1 -1
  50. package/dist/h12mediaBidAdapter.js +1 -1
  51. package/dist/id5IdSystem.js +1 -1
  52. package/dist/impactifyBidAdapter.js +1 -1
  53. package/dist/improvedigitalBidAdapter.js +1 -1
  54. package/dist/inmarBidAdapter.js +1 -1
  55. package/dist/insticatorBidAdapter.js +1 -1
  56. package/dist/ixBidAdapter.js +1 -1
  57. package/dist/jixieBidAdapter.js +1 -1
  58. package/dist/justpremiumBidAdapter.js +1 -1
  59. package/dist/konduitAnalyticsAdapter.js +1 -1
  60. package/dist/kueezBidAdapter.js +1 -1
  61. package/dist/kueezRtbBidAdapter.js +1 -1
  62. package/dist/lassoBidAdapter.js +1 -1
  63. package/dist/lifestreetBidAdapter.js +1 -1
  64. package/dist/limelightDigitalBidAdapter.js +1 -1
  65. package/dist/liveIntentIdSystem.js +1 -1
  66. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  67. package/dist/logicadBidAdapter.js +1 -1
  68. package/dist/loglyliftBidAdapter.js +1 -1
  69. package/dist/magniteAnalyticsAdapter.js +1 -1
  70. package/dist/malltvAnalyticsAdapter.js +1 -1
  71. package/dist/marsmediaBidAdapter.js +1 -1
  72. package/dist/mediafuseBidAdapter.js +1 -1
  73. package/dist/mediakeysBidAdapter.js +1 -1
  74. package/dist/mediasquareBidAdapter.js +1 -1
  75. package/dist/mgidBidAdapter.js +1 -1
  76. package/dist/minutemediaBidAdapter.js +1 -1
  77. package/dist/neuwoRtdProvider.js +1 -0
  78. package/dist/nexx360BidAdapter.js +1 -1
  79. package/dist/not-for-prod/prebid.js +132 -129
  80. package/dist/oguryBidAdapter.js +1 -1
  81. package/dist/onetagBidAdapter.js +1 -1
  82. package/dist/ooloAnalyticsAdapter.js +1 -1
  83. package/dist/outbrainBidAdapter.js +1 -1
  84. package/dist/parrableIdSystem.js +1 -1
  85. package/dist/pixfutureBidAdapter.js +1 -1
  86. package/dist/prebid-core.js +1 -1
  87. package/dist/publinkIdSystem.js +1 -1
  88. package/dist/pubmaticBidAdapter.js +1 -1
  89. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  90. package/dist/pxyzBidAdapter.js +1 -1
  91. package/dist/quantcastBidAdapter.js +1 -1
  92. package/dist/readpeakBidAdapter.js +1 -1
  93. package/dist/relaidoBidAdapter.js +1 -1
  94. package/dist/rhythmoneBidAdapter.js +1 -1
  95. package/dist/riseBidAdapter.js +1 -1
  96. package/dist/rubiconAnalyticsAdapter.js +1 -1
  97. package/dist/rubiconBidAdapter.js +1 -1
  98. package/dist/scatteredBidAdapter.js +1 -0
  99. package/dist/seedingAllianceBidAdapter.js +1 -1
  100. package/dist/seedtagBidAdapter.js +1 -1
  101. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  102. package/dist/sharethroughBidAdapter.js +1 -1
  103. package/dist/shinezBidAdapter.js +1 -1
  104. package/dist/sirdataRtdProvider.js +1 -1
  105. package/dist/smaatoBidAdapter.js +1 -1
  106. package/dist/smartadserverBidAdapter.js +1 -1
  107. package/dist/smartxBidAdapter.js +1 -1
  108. package/dist/smilewantedBidAdapter.js +1 -1
  109. package/dist/sonobiBidAdapter.js +1 -1
  110. package/dist/sovrnAnalyticsAdapter.js +1 -1
  111. package/dist/sovrnBidAdapter.js +1 -1
  112. package/dist/sspBCBidAdapter.js +1 -1
  113. package/dist/sublimeBidAdapter.js +1 -1
  114. package/dist/synacormediaBidAdapter.js +1 -1
  115. package/dist/targetVideoBidAdapter.js +1 -1
  116. package/dist/teadsBidAdapter.js +1 -1
  117. package/dist/trionBidAdapter.js +1 -1
  118. package/dist/tripleliftBidAdapter.js +1 -1
  119. package/dist/ttdBidAdapter.js +1 -1
  120. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  121. package/dist/uid2IdSystem.js +1 -1
  122. package/dist/underdogmediaBidAdapter.js +1 -1
  123. package/dist/undertoneBidAdapter.js +1 -1
  124. package/dist/userId.js +1 -1
  125. package/dist/vidazooBidAdapter.js +1 -1
  126. package/dist/videobyteBidAdapter.js +1 -1
  127. package/dist/visxBidAdapter.js +1 -1
  128. package/dist/vuukleBidAdapter.js +1 -1
  129. package/dist/widespaceBidAdapter.js +1 -1
  130. package/dist/winrBidAdapter.js +1 -1
  131. package/dist/yahoosspBidAdapter.js +1 -1
  132. package/dist/yieldmoBidAdapter.js +1 -1
  133. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  134. package/integrationExamples/gpt/neuwoRtdProvider_example.html +190 -0
  135. package/modules/33acrossBidAdapter.js +13 -4
  136. package/modules/admaruBidAdapter.js +19 -1
  137. package/modules/aidemBidAdapter.js +90 -65
  138. package/modules/aidemBidAdapter.md +10 -7
  139. package/modules/ajaBidAdapter.js +6 -1
  140. package/modules/amxIdSystem.md +2 -10
  141. package/modules/aolBidAdapter.js +1 -1
  142. package/modules/appnexusBidAdapter.js +45 -48
  143. package/modules/brightcomBidAdapter.js +1 -0
  144. package/modules/brightcomSSPBidAdapter.js +323 -0
  145. package/modules/brightcomSSPBidAdapter.md +46 -0
  146. package/modules/feedadBidAdapter.js +35 -15
  147. package/modules/fpdModule/index.md +5 -2
  148. package/modules/freewheel-sspBidAdapter.js +5 -1
  149. package/modules/gridBidAdapter.js +3 -1
  150. package/modules/ixBidAdapter.js +318 -175
  151. package/modules/limelightDigitalBidAdapter.js +6 -1
  152. package/modules/limelightDigitalBidAdapter.md +12 -2
  153. package/modules/liveIntentIdSystem.js +1 -1
  154. package/modules/neuwoRtdProvider.js +171 -0
  155. package/modules/neuwoRtdProvider.md +40 -0
  156. package/modules/nexx360BidAdapter.js +1 -1
  157. package/modules/pubmaticBidAdapter.js +4 -0
  158. package/modules/scatteredBidAdapter.js +72 -0
  159. package/modules/scatteredBidAdapter.md +36 -0
  160. package/modules/sirdataRtdProvider.js +262 -284
  161. package/modules/smartxBidAdapter.js +2 -0
  162. package/modules/smilewantedBidAdapter.js +5 -0
  163. package/modules/topicsFpdModule.md +62 -0
  164. package/modules/userId/eids.js +1 -1
  165. package/modules/vidazooBidAdapter.js +3 -1
  166. package/modules/yahoosspBidAdapter.js +1 -1
  167. package/package.json +2 -2
  168. package/test/spec/modules/33acrossBidAdapter_spec.js +51 -18
  169. package/test/spec/modules/admaruBidAdapter_spec.js +48 -0
  170. package/test/spec/modules/aidemBidAdapter_spec.js +77 -10
  171. package/test/spec/modules/ajaBidAdapter_spec.js +21 -1
  172. package/test/spec/modules/aolBidAdapter_spec.js +2 -2
  173. package/test/spec/modules/appnexusBidAdapter_spec.js +123 -16
  174. package/test/spec/modules/brightcomSSPBidAdapter_spec.js +411 -0
  175. package/test/spec/modules/eids_spec.js +1 -1
  176. package/test/spec/modules/feedadBidAdapter_spec.js +47 -77
  177. package/test/spec/modules/freewheel-sspBidAdapter_spec.js +1 -1
  178. package/test/spec/modules/ixBidAdapter_spec.js +24 -54
  179. package/test/spec/modules/limelightDigitalBidAdapter_spec.js +35 -5
  180. package/test/spec/modules/neuwoRtdProvider_spec.js +123 -0
  181. package/test/spec/modules/pubmaticBidAdapter_spec.js +15 -0
  182. package/test/spec/modules/scatteredBidAdapter_spec.js +210 -0
  183. package/test/spec/modules/sirdataRtdProvider_spec.js +116 -22
  184. package/test/spec/modules/smilewantedBidAdapter_spec.js +54 -3
  185. package/test/spec/modules/tripleliftBidAdapter_spec.js +2 -2
  186. package/test/spec/modules/userId_spec.js +1 -1
  187. package/test/spec/modules/vidazooBidAdapter_spec.js +4 -1
  188. package/test/spec/modules/yahoosspBidAdapter_spec.js +1 -1
@@ -0,0 +1,323 @@
1
+ import {
2
+ getBidIdParameter,
3
+ isArray,
4
+ getWindowTop,
5
+ getUniqueIdentifierStr,
6
+ deepSetValue,
7
+ logError,
8
+ logWarn,
9
+ createTrackPixelHtml,
10
+ getWindowSelf,
11
+ isFn,
12
+ isPlainObject,
13
+ } from '../src/utils.js';
14
+ import {registerBidder} from '../src/adapters/bidderFactory.js';
15
+ import {BANNER} from '../src/mediaTypes.js';
16
+ import {config} from '../src/config.js';
17
+ import {ajax} from '../src/ajax.js';
18
+
19
+ const BIDDER_CODE = 'bcmssp';
20
+ const URL = 'https://rt.marphezis.com/hb';
21
+ const TRACK_EVENT_URL = 'https://rt.marphezis.com/prebid'
22
+
23
+ export const spec = {
24
+ code: BIDDER_CODE,
25
+ gvlid: 883,
26
+ supportedMediaTypes: [BANNER],
27
+ isBidRequestValid,
28
+ buildRequests,
29
+ interpretResponse,
30
+ onBidderError,
31
+ onTimeout,
32
+ onBidWon,
33
+ getUserSyncs,
34
+ };
35
+
36
+ function buildRequests(bidReqs, bidderRequest) {
37
+ try {
38
+ const impressions = bidReqs.map(bid => {
39
+ let bidSizes = bid?.mediaTypes?.banner?.sizes || bid.sizes;
40
+ bidSizes = ((isArray(bidSizes) && isArray(bidSizes[0])) ? bidSizes : [bidSizes]);
41
+ bidSizes = bidSizes.filter(size => isArray(size));
42
+ const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)}));
43
+
44
+ const element = document.getElementById(bid.adUnitCode);
45
+ const minSize = _getMinSize(processedSizes);
46
+ const viewabilityAmount = _isViewabilityMeasurable(element) ? _getViewability(element, getWindowTop(), minSize) : 'na';
47
+ const viewabilityAmountRounded = isNaN(viewabilityAmount) ? viewabilityAmount : Math.round(viewabilityAmount);
48
+
49
+ const imp = {
50
+ id: bid.bidId,
51
+ banner: {
52
+ format: processedSizes,
53
+ ext: {
54
+ viewability: viewabilityAmountRounded
55
+ }
56
+ },
57
+ tagid: String(bid.adUnitCode)
58
+ };
59
+
60
+ const bidFloor = _getBidFloor(bid);
61
+
62
+ if (bidFloor) {
63
+ imp.bidfloor = bidFloor;
64
+ }
65
+
66
+ return imp;
67
+ })
68
+
69
+ const referrer = bidderRequest?.refererInfo?.page || '';
70
+ const publisherId = getBidIdParameter('publisherId', bidReqs[0].params);
71
+
72
+ const payload = {
73
+ id: getUniqueIdentifierStr(),
74
+ imp: impressions,
75
+ site: {
76
+ domain: bidderRequest?.refererInfo?.domain || '',
77
+ page: referrer,
78
+ publisher: {
79
+ id: publisherId
80
+ }
81
+ },
82
+ device: {
83
+ devicetype: _getDeviceType(),
84
+ w: screen.width,
85
+ h: screen.height
86
+ },
87
+ tmax: config.getConfig('bidderTimeout')
88
+ };
89
+
90
+ if (bidderRequest?.gdprConsent) {
91
+ deepSetValue(payload, 'regs.ext.gdpr', +bidderRequest.gdprConsent.gdprApplies);
92
+ deepSetValue(payload, 'user.ext.consent', bidderRequest.gdprConsent.consentString);
93
+ }
94
+
95
+ if (bidderRequest?.uspConsent) {
96
+ deepSetValue(payload, 'regs.ext.us_privacy', bidderRequest.uspConsent);
97
+ }
98
+
99
+ if (config.getConfig('coppa') === true) {
100
+ deepSetValue(payload, 'regs.coppa', 1);
101
+ }
102
+
103
+ if (bidReqs?.[0]?.schain) {
104
+ deepSetValue(payload, 'source.ext.schain', bidReqs[0].schain)
105
+ }
106
+
107
+ if (bidReqs?.[0]?.userIdAsEids) {
108
+ deepSetValue(payload, 'user.ext.eids', bidReqs[0].userIdAsEids || [])
109
+ }
110
+
111
+ if (bidReqs?.[0].userId) {
112
+ deepSetValue(payload, 'user.ext.ids', bidReqs[0].userId || [])
113
+ }
114
+
115
+ return {
116
+ method: 'POST',
117
+ url: URL,
118
+ data: JSON.stringify(payload),
119
+ options: {contentType: 'text/plain', withCredentials: false}
120
+ };
121
+ } catch (e) {
122
+ logError(e, {bidReqs, bidderRequest});
123
+ }
124
+ }
125
+
126
+ function isBidRequestValid(bid) {
127
+ if (bid.bidder !== BIDDER_CODE || !bid.params || !bid.params.publisherId) {
128
+ return false;
129
+ }
130
+
131
+ return true;
132
+ }
133
+
134
+ function interpretResponse(serverResponse) {
135
+ let response = [];
136
+ if (!serverResponse.body || typeof serverResponse.body != 'object') {
137
+ logWarn('Brightcom server returned empty/non-json response: ' + JSON.stringify(serverResponse.body));
138
+ return response;
139
+ }
140
+
141
+ const {body: {id, seatbid}} = serverResponse;
142
+
143
+ try {
144
+ if (id && seatbid && seatbid.length > 0 && seatbid[0].bid && seatbid[0].bid.length > 0) {
145
+ response = seatbid[0].bid.map(bid => {
146
+ return {
147
+ requestId: bid.impid,
148
+ cpm: parseFloat(bid.price),
149
+ width: parseInt(bid.w),
150
+ height: parseInt(bid.h),
151
+ creativeId: bid.crid || bid.id,
152
+ currency: 'USD',
153
+ netRevenue: true,
154
+ mediaType: BANNER,
155
+ ad: _getAdMarkup(bid),
156
+ ttl: 60,
157
+ meta: {
158
+ advertiserDomains: bid?.adomain || []
159
+ }
160
+ };
161
+ });
162
+ }
163
+ } catch (e) {
164
+ logError(e, {id, seatbid});
165
+ }
166
+
167
+ return response;
168
+ }
169
+
170
+ // Don't do user sync for now
171
+ function getUserSyncs(syncOptions, responses, gdprConsent) {
172
+ return [];
173
+ }
174
+
175
+ function onTimeout(timeoutData) {
176
+ if (timeoutData === null) {
177
+ return;
178
+ }
179
+
180
+ _trackEvent('timeout', timeoutData);
181
+ }
182
+
183
+ function onBidderError(errorData) {
184
+ if (errorData === null || !errorData.bidderRequest) {
185
+ return;
186
+ }
187
+
188
+ _trackEvent('error', errorData.bidderRequest)
189
+ }
190
+
191
+ function onBidWon(bid) {
192
+ if (bid === null) {
193
+ return;
194
+ }
195
+
196
+ _trackEvent('bidwon', bid)
197
+ }
198
+
199
+ function _trackEvent(endpoint, data) {
200
+ ajax(`${TRACK_EVENT_URL}/${endpoint}`, null, JSON.stringify(data), {
201
+ method: 'POST',
202
+ withCredentials: false
203
+ });
204
+ }
205
+
206
+ function _isMobile() {
207
+ return (/(ios|ipod|ipad|iphone|android)/i).test(navigator.userAgent);
208
+ }
209
+
210
+ function _isConnectedTV() {
211
+ return (/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(navigator.userAgent);
212
+ }
213
+
214
+ function _getDeviceType() {
215
+ return _isMobile() ? 1 : _isConnectedTV() ? 3 : 2;
216
+ }
217
+
218
+ function _getAdMarkup(bid) {
219
+ let adm = bid.adm;
220
+ if ('nurl' in bid) {
221
+ adm += createTrackPixelHtml(bid.nurl);
222
+ }
223
+ return adm;
224
+ }
225
+
226
+ function _isViewabilityMeasurable(element) {
227
+ return !_isIframe() && element !== null;
228
+ }
229
+
230
+ function _getViewability(element, topWin, {w, h} = {}) {
231
+ return getWindowTop().document.visibilityState === 'visible' ? _getPercentInView(element, topWin, {w, h}) : 0;
232
+ }
233
+
234
+ function _isIframe() {
235
+ try {
236
+ return getWindowSelf() !== getWindowTop();
237
+ } catch (e) {
238
+ return true;
239
+ }
240
+ }
241
+
242
+ function _getMinSize(sizes) {
243
+ return sizes.reduce((min, size) => size.h * size.w < min.h * min.w ? size : min);
244
+ }
245
+
246
+ function _getBoundingBox(element, {w, h} = {}) {
247
+ let {width, height, left, top, right, bottom} = element.getBoundingClientRect();
248
+
249
+ if ((width === 0 || height === 0) && w && h) {
250
+ width = w;
251
+ height = h;
252
+ right = left + w;
253
+ bottom = top + h;
254
+ }
255
+
256
+ return {width, height, left, top, right, bottom};
257
+ }
258
+
259
+ function _getIntersectionOfRects(rects) {
260
+ const bbox = {
261
+ left: rects[0].left, right: rects[0].right, top: rects[0].top, bottom: rects[0].bottom
262
+ };
263
+
264
+ for (let i = 1; i < rects.length; ++i) {
265
+ bbox.left = Math.max(bbox.left, rects[i].left);
266
+ bbox.right = Math.min(bbox.right, rects[i].right);
267
+
268
+ if (bbox.left >= bbox.right) {
269
+ return null;
270
+ }
271
+
272
+ bbox.top = Math.max(bbox.top, rects[i].top);
273
+ bbox.bottom = Math.min(bbox.bottom, rects[i].bottom);
274
+
275
+ if (bbox.top >= bbox.bottom) {
276
+ return null;
277
+ }
278
+ }
279
+
280
+ bbox.width = bbox.right - bbox.left;
281
+ bbox.height = bbox.bottom - bbox.top;
282
+
283
+ return bbox;
284
+ }
285
+
286
+ function _getPercentInView(element, topWin, {w, h} = {}) {
287
+ const elementBoundingBox = _getBoundingBox(element, {w, h});
288
+
289
+ // Obtain the intersection of the element and the viewport
290
+ const elementInViewBoundingBox = _getIntersectionOfRects([{
291
+ left: 0, top: 0, right: topWin.innerWidth, bottom: topWin.innerHeight
292
+ }, elementBoundingBox]);
293
+
294
+ let elementInViewArea, elementTotalArea;
295
+
296
+ if (elementInViewBoundingBox !== null) {
297
+ // Some or all of the element is in view
298
+ elementInViewArea = elementInViewBoundingBox.width * elementInViewBoundingBox.height;
299
+ elementTotalArea = elementBoundingBox.width * elementBoundingBox.height;
300
+
301
+ return ((elementInViewArea / elementTotalArea) * 100);
302
+ }
303
+
304
+ // No overlap between element and the viewport; therefore, the element
305
+ // lies completely out of view
306
+ return 0;
307
+ }
308
+
309
+ function _getBidFloor(bid) {
310
+ if (!isFn(bid.getFloor)) {
311
+ return bid.params.bidFloor ? bid.params.bidFloor : null;
312
+ }
313
+
314
+ let floor = bid.getFloor({
315
+ currency: 'USD', mediaType: '*', size: '*'
316
+ });
317
+ if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') {
318
+ return floor.floor;
319
+ }
320
+ return null;
321
+ }
322
+
323
+ registerBidder(spec);
@@ -0,0 +1,46 @@
1
+ # Overview
2
+
3
+ ```
4
+ Module Name: Brightcom SSP Bid Adapter
5
+ Module Type: Bidder Adapter
6
+ Maintainer: alexandruc@brightcom.com
7
+ ```
8
+
9
+ # Description
10
+
11
+ Brightcom's adapter integration to the Prebid library.
12
+
13
+ # Test Parameters
14
+
15
+ ```
16
+ var adUnits = [
17
+ {
18
+ code: 'test-leaderboard',
19
+ mediaTypes: {
20
+ banner: {
21
+ sizes: [[728, 90]]
22
+ }
23
+ },
24
+ bids: [{
25
+ bidder: 'bcmssp',
26
+ params: {
27
+ publisherId: 2141020,
28
+ bidFloor: 0.01
29
+ }
30
+ }]
31
+ }, {
32
+ code: 'test-banner',
33
+ mediaTypes: {
34
+ banner: {
35
+ sizes: [[300, 250]]
36
+ }
37
+ },
38
+ bids: [{
39
+ bidder: 'bcmssp',
40
+ params: {
41
+ publisherId: 2141020
42
+ }
43
+ }]
44
+ }
45
+ ]
46
+ ```
@@ -7,7 +7,23 @@ import {ajax} from '../src/ajax.js';
7
7
  * Version of the FeedAd bid adapter
8
8
  * @type {string}
9
9
  */
10
- const VERSION = '1.0.5';
10
+ const VERSION = '1.0.6';
11
+
12
+ /**
13
+ * @typedef {object} FeedAdUserSync
14
+ * @inner
15
+ *
16
+ * @property {string} type
17
+ * @property {string} url
18
+ */
19
+
20
+ /**
21
+ * @typedef {object} FeedAdBidExtension
22
+ * @inner
23
+ *
24
+ * @property {FeedAdUserSync[]} pixels
25
+ * @property {FeedAdUserSync[]} iframes
26
+ */
11
27
 
12
28
  /**
13
29
  * @typedef {object} FeedAdApiBidRequest
@@ -41,7 +57,7 @@ const VERSION = '1.0.5';
41
57
  * @property {string} requestId - bids[].bidId
42
58
  * @property {number} ttl - Time to live for this ad
43
59
  * @property {number} width - Width of creative returned in [].ad
44
- * @property {object} [ext] - an extension object
60
+ * @property {FeedAdBidExtension} [ext] - an extension object
45
61
  */
46
62
 
47
63
  /**
@@ -63,6 +79,14 @@ const VERSION = '1.0.5';
63
79
  * @property [device_platform] {1|2|3} 1 - Android | 2 - iOS | 3 - Windows
64
80
  */
65
81
 
82
+ /**
83
+ * @typedef {object} FeedAdServerResponse
84
+ * @extends ServerResponse
85
+ * @inner
86
+ *
87
+ * @property {FeedAdApiBidResponse[]} body - the body of a FeedAd server response
88
+ */
89
+
66
90
  /**
67
91
  * The IAB TCF 2.0 vendor ID for the FeedAd GmbH
68
92
  */
@@ -228,7 +252,7 @@ function buildRequests(validBidRequests, bidderRequest) {
228
252
 
229
253
  /**
230
254
  * Adapts the FeedAd server response to Prebid format
231
- * @param {ServerResponse} serverResponse - the FeedAd server response
255
+ * @param {FeedAdServerResponse} serverResponse - the FeedAd server response
232
256
  * @param {BidRequest} request - the initial bid request
233
257
  * @returns {Bid[]} the FeedAd bids
234
258
  */
@@ -296,24 +320,20 @@ function trackingHandlerFactory(klass) {
296
320
  /**
297
321
  * Reads the user syncs off the server responses and converts them into Prebid.JS format
298
322
  * @param {SyncOptions} syncOptions
299
- * @param {ServerResponse[]} serverResponses
323
+ * @param {FeedAdServerResponse[]} serverResponses
300
324
  * @param gdprConsent
301
325
  * @param uspConsent
302
326
  */
303
327
  function getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent) {
304
- return serverResponses.map(response => {
305
- // validate response format
306
- const ext = deepAccess(response, 'body.ext', []);
307
- if (ext == null) {
308
- return null;
309
- }
310
- return ext;
328
+ return serverResponses.flatMap(response => {
329
+ // merge all response bodies into one
330
+ const body = response.body;
331
+ return isArray(body) ? body : [];
311
332
  })
312
- .filter(ext => ext != null)
313
- .flatMap(extension => {
333
+ .flatMap(/** @param {FeedAdApiBidResponse} bidResponse */ bidResponse => {
314
334
  // extract user syncs from extension
315
- const pixels = syncOptions.pixelEnabled && extension.pixels ? extension.pixels : [];
316
- const iframes = syncOptions.iframeEnabled && extension.iframes ? extension.iframes : [];
335
+ const pixels = (syncOptions.pixelEnabled && bidResponse?.ext?.pixels) ? bidResponse.ext.pixels : [];
336
+ const iframes = (syncOptions.iframeEnabled && bidResponse?.ext?.iframes) ? bidResponse.ext.iframes : [];
317
337
  return pixels.concat(...iframes);
318
338
  })
319
339
  .reduce((syncs, sync) => {
@@ -16,9 +16,11 @@ Validation Submodule:
16
16
  - verify that certain OpenRTB attributes are not specified
17
17
  - optionally suppress user FPD based on the existence of _pubcid_optout
18
18
 
19
+ Topic Submodule:
20
+ - populate first party/third party topics data onto user.data in bid stream.
19
21
 
20
22
  1. Module initializes on first load and set bidRequestHook
21
- 2. When hook runs, corresponding submodule init functions are run to perform enrichments/validations dependant on submodule
23
+ 2. When hook runs, corresponding submodule init functions are run to perform enrichments/validations/topics dependant on submodule
22
24
  3. After hook complete, it is disabled - meaning module only runs on first auction
23
25
  4. To reinitiate the module, run pbjs.refreshFPD(), which allows module to rerun as if initial load
24
26
 
@@ -43,4 +45,5 @@ pbjs.setConfig({
43
45
  At least one of the submodules must be included in order to successfully run the corresponding above operations.
44
46
 
45
47
  enrichmentFpdModule
46
- validationFpdModule
48
+ validationFpdModule
49
+ topicsFpdModule
@@ -348,7 +348,11 @@ export const spec = {
348
348
  // Add schain object
349
349
  var schain = currentBidRequest.schain;
350
350
  if (schain) {
351
- requestParams.schain = schain;
351
+ try {
352
+ requestParams.schain = JSON.stringify(schain);
353
+ } catch (error) {
354
+ logWarn('PREBID - ' + BIDDER_CODE + ': Unable to stringify the schain: ' + error);
355
+ }
352
356
  }
353
357
 
354
358
  var vastParams = currentBidRequest.params.vastUrlParams;
@@ -288,9 +288,11 @@ export const spec = {
288
288
  return;
289
289
  }
290
290
 
291
+ if (request.user) user = request.user;
292
+
291
293
  const ortb2UserData = deepAccess(bidderRequest, 'ortb2.user.data');
292
294
  if (ortb2UserData && ortb2UserData.length) {
293
- user = request.user || { data: [] };
295
+ if (!user) user = { data: [] };
294
296
  user = mergeDeep(user, {
295
297
  data: [...ortb2UserData]
296
298
  });