prebid.js 7.48.0 → 7.50.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 (219) hide show
  1. package/README.md +3 -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/admixerBidAdapter.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/appierAnalyticsAdapter.js +1 -1
  17. package/dist/appnexusBidAdapter.js +1 -1
  18. package/dist/asoBidAdapter.js +1 -1
  19. package/dist/axonixBidAdapter.js +1 -1
  20. package/dist/beopBidAdapter.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/confiantRtdProvider.js +1 -1
  29. package/dist/connectadBidAdapter.js +1 -1
  30. package/dist/consumableBidAdapter.js +1 -1
  31. package/dist/conversantAnalyticsAdapter.js +1 -1
  32. package/dist/conversantBidAdapter.js +1 -1
  33. package/dist/craftBidAdapter.js +1 -1
  34. package/dist/criteoBidAdapter.js +1 -1
  35. package/dist/cwireBidAdapter.js +1 -1
  36. package/dist/dependencies.json +3 -0
  37. package/dist/dspxBidAdapter.js +1 -1
  38. package/dist/eplanningBidAdapter.js +1 -1
  39. package/dist/feedadBidAdapter.js +1 -1
  40. package/dist/finativeBidAdapter.js +1 -1
  41. package/dist/freewheel-sspBidAdapter.js +1 -1
  42. package/dist/glimpseBidAdapter.js +1 -1
  43. package/dist/gmosspBidAdapter.js +1 -1
  44. package/dist/goldbachBidAdapter.js +1 -1
  45. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  46. package/dist/greenbidsRtdProvider.js +1 -1
  47. package/dist/gridBidAdapter.js +1 -1
  48. package/dist/gumgumBidAdapter.js +1 -1
  49. package/dist/h12mediaBidAdapter.js +1 -1
  50. package/dist/id5IdSystem.js +1 -1
  51. package/dist/improvedigitalBidAdapter.js +1 -1
  52. package/dist/inmarBidAdapter.js +1 -1
  53. package/dist/insticatorBidAdapter.js +1 -1
  54. package/dist/ixBidAdapter.js +1 -1
  55. package/dist/justpremiumBidAdapter.js +1 -1
  56. package/dist/kargoBidAdapter.js +1 -1
  57. package/dist/konduitAnalyticsAdapter.js +1 -1
  58. package/dist/kueezBidAdapter.js +1 -1
  59. package/dist/kueezRtbBidAdapter.js +1 -1
  60. package/dist/kulturemediaBidAdapter.js +1 -1
  61. package/dist/lassoBidAdapter.js +1 -1
  62. package/dist/lifestreetBidAdapter.js +1 -1
  63. package/dist/liveIntentIdSystem.js +1 -1
  64. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  65. package/dist/logicadBidAdapter.js +1 -1
  66. package/dist/loglyliftBidAdapter.js +1 -1
  67. package/dist/magniteAnalyticsAdapter.js +1 -1
  68. package/dist/malltvAnalyticsAdapter.js +1 -1
  69. package/dist/marsmediaBidAdapter.js +1 -1
  70. package/dist/mediafuseBidAdapter.js +1 -1
  71. package/dist/mediasquareBidAdapter.js +1 -1
  72. package/dist/mgidBidAdapter.js +1 -1
  73. package/dist/minutemediaBidAdapter.js +1 -1
  74. package/dist/minutemediaplusBidAdapter.js +1 -1
  75. package/dist/nexx360BidAdapter.js +1 -1
  76. package/dist/not-for-prod/prebid.js +136 -134
  77. package/dist/oguryBidAdapter.js +1 -1
  78. package/dist/onetagBidAdapter.js +1 -1
  79. package/dist/ooloAnalyticsAdapter.js +1 -1
  80. package/dist/optidigitalBidAdapter.js +1 -1
  81. package/dist/outbrainBidAdapter.js +1 -1
  82. package/dist/parrableIdSystem.js +1 -1
  83. package/dist/permutiveRtdProvider.js +1 -1
  84. package/dist/pixfutureBidAdapter.js +1 -1
  85. package/dist/prebid-core.js +1 -1
  86. package/dist/prebidServerBidAdapter.js +1 -1
  87. package/dist/publinkIdSystem.js +1 -1
  88. package/dist/pubmaticAnalyticsAdapter.js +1 -1
  89. package/dist/pubmaticBidAdapter.js +1 -1
  90. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  91. package/dist/pxyzBidAdapter.js +1 -1
  92. package/dist/quantcastBidAdapter.js +1 -1
  93. package/dist/readpeakBidAdapter.js +1 -1
  94. package/dist/relaidoBidAdapter.js +1 -1
  95. package/dist/retailspotBidAdapter.js +1 -0
  96. package/dist/rhythmoneBidAdapter.js +1 -1
  97. package/dist/riseBidAdapter.js +1 -1
  98. package/dist/rubiconAnalyticsAdapter.js +1 -1
  99. package/dist/rubiconBidAdapter.js +1 -1
  100. package/dist/seedingAllianceBidAdapter.js +1 -1
  101. package/dist/seedtagBidAdapter.js +1 -1
  102. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  103. package/dist/sharethroughBidAdapter.js +1 -1
  104. package/dist/shinezBidAdapter.js +1 -1
  105. package/dist/silverpushBidAdapter.js +1 -0
  106. package/dist/smaatoBidAdapter.js +1 -1
  107. package/dist/smartadserverBidAdapter.js +1 -1
  108. package/dist/smartxBidAdapter.js +1 -1
  109. package/dist/smilewantedBidAdapter.js +1 -1
  110. package/dist/sonobiBidAdapter.js +1 -1
  111. package/dist/sovrnAnalyticsAdapter.js +1 -1
  112. package/dist/sovrnBidAdapter.js +1 -1
  113. package/dist/sspBCBidAdapter.js +1 -1
  114. package/dist/stvBidAdapter.js +1 -1
  115. package/dist/sublimeBidAdapter.js +1 -1
  116. package/dist/synacormediaBidAdapter.js +1 -1
  117. package/dist/targetVideoBidAdapter.js +1 -1
  118. package/dist/teadsBidAdapter.js +1 -1
  119. package/dist/trionBidAdapter.js +1 -1
  120. package/dist/tripleliftBidAdapter.js +1 -1
  121. package/dist/ttdBidAdapter.js +1 -1
  122. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  123. package/dist/uid2IdSystem.js +1 -1
  124. package/dist/underdogmediaBidAdapter.js +1 -1
  125. package/dist/undertoneBidAdapter.js +1 -1
  126. package/dist/vidazooBidAdapter.js +1 -1
  127. package/dist/video.js +1 -1
  128. package/dist/videoModule.js +1 -1
  129. package/dist/videobyteBidAdapter.js +1 -1
  130. package/dist/visxBidAdapter.js +1 -1
  131. package/dist/vuukleBidAdapter.js +1 -1
  132. package/dist/widespaceBidAdapter.js +1 -1
  133. package/dist/winrBidAdapter.js +1 -1
  134. package/dist/yahoosspBidAdapter.js +1 -1
  135. package/dist/yieldlabBidAdapter.js +1 -1
  136. package/dist/yieldmoBidAdapter.js +1 -1
  137. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  138. package/integrationExamples/videoModule/eventsUI/eventsUI.css +205 -0
  139. package/integrationExamples/videoModule/eventsUI/eventsUI.js +181 -0
  140. package/integrationExamples/videoModule/jwplayer/eventsUI.html +295 -0
  141. package/integrationExamples/videoModule/videojs/eventsUI.html +319 -0
  142. package/libraries/video/shared/helpers.js +14 -0
  143. package/modules/33acrossBidAdapter.js +1 -1
  144. package/modules/adgenerationBidAdapter.js +24 -15
  145. package/modules/admixerBidAdapter.js +15 -9
  146. package/modules/aidemBidAdapter.js +3 -1
  147. package/modules/appnexusBidAdapter.js +1 -0
  148. package/modules/beopBidAdapter.js +1 -0
  149. package/modules/confiantRtdProvider.js +15 -12
  150. package/modules/conversantAnalyticsAdapter.js +7 -5
  151. package/modules/conversantBidAdapter.js +1 -1
  152. package/modules/criteoBidAdapter.js +17 -1
  153. package/modules/gridBidAdapter.js +3 -0
  154. package/modules/ixBidAdapter.js +65 -47
  155. package/modules/kueezRtbBidAdapter.js +30 -33
  156. package/modules/liveIntentIdSystem.js +8 -4
  157. package/modules/magniteAnalyticsAdapter.js +26 -3
  158. package/modules/mgidBidAdapter.js +9 -8
  159. package/modules/minutemediaBidAdapter.js +6 -0
  160. package/modules/minutemediaplusBidAdapter.js +30 -32
  161. package/modules/nexx360BidAdapter.js +2 -1
  162. package/modules/permutiveRtdProvider.js +9 -38
  163. package/modules/prebidServerBidAdapter/index.js +1 -3
  164. package/modules/prebidServerBidAdapter/ortbConverter.js +5 -1
  165. package/modules/pubmaticAnalyticsAdapter.js +3 -2
  166. package/modules/retailspotBidAdapter .md +32 -0
  167. package/modules/retailspotBidAdapter.js +186 -0
  168. package/modules/riseBidAdapter.js +6 -0
  169. package/modules/rubiconBidAdapter.js +6 -2
  170. package/modules/silverpushBidAdapter.js +326 -0
  171. package/modules/silverpushBidAdapter.md +107 -0
  172. package/modules/ttdBidAdapter.js +23 -22
  173. package/modules/underdogmediaBidAdapter.js +2 -2
  174. package/modules/vidazooBidAdapter.js +28 -32
  175. package/modules/videoModule/adQueue.js +2 -2
  176. package/modules/videoModule/index.js +9 -5
  177. package/modules/yahoosspBidAdapter.js +6 -0
  178. package/modules/yahoosspBidAdapter.md +37 -0
  179. package/modules/yieldlabBidAdapter.js +27 -5
  180. package/package.json +1 -1
  181. package/src/adapterManager.js +4 -0
  182. package/src/adapters/bidderFactory.js +1 -0
  183. package/src/auction.js +2 -0
  184. package/src/prebid.js +36 -12
  185. package/src/utils/cpm.js +4 -1
  186. package/test/spec/modules/33acrossBidAdapter_spec.js +4 -3
  187. package/test/spec/modules/adgenerationBidAdapter_spec.js +6 -6
  188. package/test/spec/modules/admixerBidAdapter_spec.js +64 -25
  189. package/test/spec/modules/aidemBidAdapter_spec.js +3 -0
  190. package/test/spec/modules/beopBidAdapter_spec.js +4 -0
  191. package/test/spec/modules/confiantRtdProvider_spec.js +4 -1
  192. package/test/spec/modules/conversantBidAdapter_spec.js +2 -1
  193. package/test/spec/modules/criteoBidAdapter_spec.js +109 -0
  194. package/test/spec/modules/gridBidAdapter_spec.js +3 -0
  195. package/test/spec/modules/ixBidAdapter_spec.js +66 -1
  196. package/test/spec/modules/kueezRtbBidAdapter_spec.js +3 -2
  197. package/test/spec/modules/liveIntentIdMinimalSystem_spec.js +28 -0
  198. package/test/spec/modules/liveIntentIdSystem_spec.js +45 -0
  199. package/test/spec/modules/magniteAnalyticsAdapter_spec.js +16 -36
  200. package/test/spec/modules/mass_spec.js +2 -0
  201. package/test/spec/modules/mgidBidAdapter_spec.js +9 -9
  202. package/test/spec/modules/minutemediaBidAdapter_spec.js +18 -0
  203. package/test/spec/modules/minutemediaplusBidAdapter_spec.js +3 -2
  204. package/test/spec/modules/permutiveRtdProvider_spec.js +0 -20
  205. package/test/spec/modules/prebidServerBidAdapter_spec.js +96 -1
  206. package/test/spec/modules/pubmaticAnalyticsAdapter_spec.js +6 -1
  207. package/test/spec/modules/retailspotBidAdapter_spec.js +426 -0
  208. package/test/spec/modules/riseBidAdapter_spec.js +18 -0
  209. package/test/spec/modules/rubiconBidAdapter_spec.js +143 -67
  210. package/test/spec/modules/silverpushBidAdapter_spec.js +394 -0
  211. package/test/spec/modules/ttdBidAdapter_spec.js +129 -2
  212. package/test/spec/modules/underdogmediaBidAdapter_spec.js +1 -1
  213. package/test/spec/modules/vidazooBidAdapter_spec.js +3 -2
  214. package/test/spec/modules/videoModule/shared/helpers_spec.js +22 -0
  215. package/test/spec/modules/yahoosspBidAdapter_spec.js +60 -1
  216. package/test/spec/modules/yieldlabBidAdapter_spec.js +8 -1
  217. package/test/spec/unit/core/bidderFactory_spec.js +9 -9
  218. package/test/spec/unit/pbjs_api_spec.js +59 -1
  219. package/test/spec/unit/utils/cpm_spec.js +56 -1
@@ -0,0 +1,186 @@
1
+ import {buildUrl, deepAccess, parseSizesInput} from '../src/utils.js';
2
+ import {registerBidder} from '../src/adapters/bidderFactory.js';
3
+ import {BANNER, VIDEO} from '../src/mediaTypes.js';
4
+
5
+ const BIDDER_CODE = 'retailspot';
6
+ const DEFAULT_SUBDOMAIN = 'ssp';
7
+ const PREPROD_SUBDOMAIN = 'ssp-preprod';
8
+ const HOST = 'retail-spot.io';
9
+ const ENDPOINT = '/prebid';
10
+ const DEV_URL = 'http://localhost:8090/prebid';
11
+
12
+ export const spec = {
13
+ code: BIDDER_CODE,
14
+ supportedMediaTypes: [BANNER, VIDEO],
15
+ aliases: ['rs'], // short code
16
+ /**
17
+ * Determines whether or not the given bid request is valid.
18
+ *
19
+ * @param {BidRequest} bid The bid params to validate.
20
+ * @return boolean True if this is a valid bid, and false otherwise.
21
+ */
22
+ isBidRequestValid: function (bid) {
23
+ const sizes = getSize(getSizeArray(bid));
24
+ const sizeValid = sizes.width > 0 && sizes.height > 0;
25
+
26
+ return deepAccess(bid, 'params.placement') && sizeValid;
27
+ },
28
+ /**
29
+ * Make a server request from the list of BidRequests.
30
+ *
31
+ * @param {bidRequests} - bidRequests.bids[] is an array of AdUnits and bids
32
+ * @return ServerRequest Info describing the request to the server.
33
+ */
34
+ buildRequests: function (bidRequests, bidderRequest) {
35
+ const payload = bidderRequest;
36
+ payload.rs_pbjs_version = '$prebid.version$';
37
+
38
+ const data = JSON.stringify(payload);
39
+ const options = {
40
+ withCredentials: true
41
+ };
42
+
43
+ const envParam = bidRequests[0].params.env;
44
+ var subDomain = DEFAULT_SUBDOMAIN;
45
+ if (envParam === 'preprod') {
46
+ subDomain = PREPROD_SUBDOMAIN;
47
+ }
48
+
49
+ let url = buildUrl({
50
+ protocol: 'https',
51
+ host: `${subDomain}.${HOST}`,
52
+ pathname: ENDPOINT
53
+ });
54
+
55
+ if (envParam === 'dev') {
56
+ url = DEV_URL;
57
+ }
58
+
59
+ return {
60
+ method: 'POST',
61
+ url,
62
+ data,
63
+ options
64
+ };
65
+ },
66
+ /**
67
+ * Unpack the response from the server into a list of bids.
68
+ *
69
+ * @param {*} serverResponse A successful response from the server.
70
+ * @return {Bid[]} An array of bids which were nested inside the server.
71
+ */
72
+ interpretResponse: function (serverResponse, request) {
73
+ const bidResponses = [];
74
+ var bidRequests = {};
75
+
76
+ try {
77
+ bidRequests = JSON.parse(request.data).bids;
78
+ } catch (err) {
79
+ // json error initial request can't be read
80
+ }
81
+
82
+ // For this adapter, serverResponse is a list
83
+ serverResponse.body.forEach(response => {
84
+ const bid = createBid(response, bidRequests);
85
+ if (bid) {
86
+ bidResponses.push(bid);
87
+ }
88
+ });
89
+
90
+ return bidResponses;
91
+ }
92
+ }
93
+
94
+ function getSizeArray(bid) {
95
+ let inputSize = bid.sizes || [];
96
+
97
+ if (bid.mediaTypes && bid.mediaTypes.banner) {
98
+ inputSize = bid.mediaTypes.banner.sizes || [];
99
+ }
100
+
101
+ // handle size in bid.params in formats: [w, h] and [[w,h]].
102
+ if (bid.params && Array.isArray(bid.params.size)) {
103
+ inputSize = bid.params.size;
104
+ if (!Array.isArray(inputSize[0])) {
105
+ inputSize = [inputSize]
106
+ }
107
+ }
108
+
109
+ return parseSizesInput(inputSize);
110
+ }
111
+
112
+ /* Get parsed size from request size */
113
+ function getSize(sizesArray) {
114
+ const parsed = {};
115
+ // the main requested size is the first one
116
+ const size = sizesArray[0];
117
+
118
+ if (typeof size !== 'string') {
119
+ return parsed;
120
+ }
121
+
122
+ const parsedSize = size.toUpperCase().split('X');
123
+ const width = parseInt(parsedSize[0], 10);
124
+ if (width) {
125
+ parsed.width = width;
126
+ }
127
+
128
+ const height = parseInt(parsedSize[1], 10);
129
+ if (height) {
130
+ parsed.height = height;
131
+ }
132
+
133
+ return parsed;
134
+ }
135
+
136
+ /* Create bid from response */
137
+ function createBid(response, bidRequests) {
138
+ if (!response || !response.mediaType ||
139
+ (response.mediaType === 'video' && !response.vastXml) ||
140
+ (response.mediaType === 'banner' && !response.ad)) {
141
+ return;
142
+ }
143
+
144
+ const request = bidRequests && bidRequests.length && bidRequests.find(itm => response.requestId === itm.bidId);
145
+ // In case we don't retreive the size from the adserver, use the given one.
146
+ if (request) {
147
+ if (!response.width || response.width === '0') {
148
+ response.width = request.width;
149
+ }
150
+
151
+ if (!response.height || response.height === '0') {
152
+ response.height = request.height;
153
+ }
154
+ }
155
+
156
+ const bid = {
157
+ bidderCode: BIDDER_CODE,
158
+ width: response.width,
159
+ height: response.height,
160
+ requestId: response.requestId,
161
+ ttl: response.ttl || 3600,
162
+ creativeId: response.creativeId,
163
+ cpm: response.cpm,
164
+ netRevenue: response.netRevenue,
165
+ currency: response.currency,
166
+ meta: response.meta || { advertiserDomains: ['retail-spot.io'] },
167
+ mediaType: response.mediaType
168
+ };
169
+
170
+ // retreive video response if present
171
+ if (response.mediaType === 'video') {
172
+ bid.vastXml = window.atob(response.vastXml);
173
+ } else {
174
+ bid.ad = response.ad;
175
+ }
176
+ if (response.adId) {
177
+ bid.adId = response.adId;
178
+ }
179
+ if (response.dealId) {
180
+ bid.dealId = response.dealId;
181
+ }
182
+
183
+ return bid;
184
+ }
185
+
186
+ registerBidder(spec);
@@ -292,6 +292,7 @@ function generateBidParameters(bid, bidderRequest) {
292
292
  bidderRequestId: getBidIdParameter('bidderRequestId', bid),
293
293
  loop: getBidIdParameter('bidderRequestsCount', bid),
294
294
  transactionId: getBidIdParameter('transactionId', bid),
295
+ coppa: 0
295
296
  };
296
297
 
297
298
  const pos = deepAccess(bid, `mediaTypes.${mediaType}.pos`);
@@ -364,6 +365,11 @@ function generateBidParameters(bid, bidderRequest) {
364
365
  if (protocols) {
365
366
  bidObject.protocols = protocols;
366
367
  }
368
+
369
+ const coppa = deepAccess(bid, 'ortb2.regs.coppa')
370
+ if (coppa) {
371
+ bidObject.coppa = 1;
372
+ }
367
373
  }
368
374
 
369
375
  return bidObject;
@@ -207,11 +207,15 @@ export const converter = ortbConverter({
207
207
  const bidResponse = buildBidResponse(bid, context);
208
208
  bidResponse.meta.mediaType = deepAccess(bid, 'ext.prebid.type');
209
209
  const {bidRequest} = context;
210
+
211
+ let [parseSizeWidth, parseSizeHeight] = bidRequest.mediaTypes.video?.context === 'outstream' ? parseSizes(bidRequest, VIDEO) : [undefined, undefined];
212
+
213
+ bidResponse.width = bid.w || parseSizeWidth || bidResponse.playerWidth;
214
+ bidResponse.height = bid.h || parseSizeHeight || bidResponse.playerHeight;
215
+
210
216
  if (bidResponse.mediaType === VIDEO && bidRequest.mediaTypes.video.context === 'outstream') {
211
217
  bidResponse.renderer = outstreamRenderer(bidResponse);
212
218
  }
213
- bidResponse.width = bid.w || deepAccess(bidRequest, 'mediaTypes.video.w') || deepAccess(bidRequest, 'params.video.playerWidth');
214
- bidResponse.height = bid.h || deepAccess(bidRequest, 'mediaTypes.video.h') || deepAccess(bidRequest, 'params.video.playerHeight');
215
219
 
216
220
  if (deepAccess(bid, 'ext.bidder.rp.advid')) {
217
221
  deepSetValue(bidResponse, 'meta.advertiserId', bid.ext.bidder.rp.advid);
@@ -0,0 +1,326 @@
1
+ import { config } from '../src/config.js';
2
+ import { registerBidder } from '../src/adapters/bidderFactory.js';
3
+ import * as utils from '../src/utils.js';
4
+ import { mergeDeep } from '../src/utils.js';
5
+ import { BANNER, VIDEO } from '../src/mediaTypes.js';
6
+ import { ortbConverter } from '../libraries/ortbConverter/converter.js';
7
+ import { Renderer } from '../src/Renderer.js';
8
+ import { ajax } from '../src/ajax.js';
9
+
10
+ const BIDDER_CODE = 'silverpush';
11
+ const bidderConfig = 'sp_pb_ortb';
12
+ const bidderVersion = '1.0.0';
13
+ const DEFAULT_CURRENCY = 'USD';
14
+
15
+ export const REQUEST_URL = 'https://apac.chocolateplatform.com/bidder/?identifier=prebidchoc';
16
+ export const SP_OUTSTREAM_PLAYER_URL = 'https://xaido.sgp1.cdn.digitaloceanspaces.com/prebid/spoutstream.min.js';
17
+
18
+ const VIDEO_ORTB_PARAMS = [
19
+ 'mimes',
20
+ 'minduration',
21
+ 'maxduration',
22
+ 'placement',
23
+ 'protocols',
24
+ 'startdelay',
25
+ 'skip',
26
+ 'skipafter',
27
+ 'minbitrate',
28
+ 'maxbitrate',
29
+ 'delivery',
30
+ 'playbackmethod',
31
+ 'api',
32
+ 'linearity'
33
+ ];
34
+
35
+ export const VIDEO_ORTB_REQUIRED = ['api', 'mimes', 'placement', 'protocols', 'minduration', 'maxduration', 'startdelay'];
36
+
37
+ export const spec = {
38
+ code: BIDDER_CODE,
39
+ supportedMediaTypes: [BANNER, VIDEO],
40
+ isBidRequestValid,
41
+ buildRequests,
42
+ interpretResponse,
43
+ onBidWon,
44
+ getRequest: function(endpoint) {
45
+ ajax(endpoint, null, undefined, {method: 'GET'});
46
+ },
47
+ getOS: function(ua) {
48
+ if (ua.indexOf('Windows') != -1) { return 'Windows'; } else if (ua.match(/(iPhone|iPod|iPad)/)) { return 'iOS'; } else if (ua.indexOf('Mac OS X') != -1) { return 'macOS'; } else if (ua.match(/Android/)) { return 'Android'; } else if (ua.indexOf('Linux') != -1) { return 'Linux'; } else { return 'Unknown'; }
49
+ }
50
+ };
51
+
52
+ registerBidder(spec);
53
+
54
+ export const CONVERTER = ortbConverter({
55
+ context: {
56
+ netRevenue: true,
57
+ ttl: 300
58
+ },
59
+ imp(buildImp, bidRequest, context) {
60
+ let imp = buildImp(bidRequest, context);
61
+
62
+ if (bidRequest.mediaTypes[VIDEO]) {
63
+ imp = buildVideoImp(bidRequest, imp);
64
+ } else if (bidRequest.mediaTypes[BANNER]) {
65
+ imp = buildBannerImp(bidRequest, imp);
66
+ }
67
+
68
+ const bidFloor = getBidFloor(bidRequest);
69
+
70
+ utils.deepSetValue(imp, 'bidfloor', bidFloor);
71
+
72
+ if (bidRequest.params.deals && bidRequest.params.deals.length > 0) {
73
+ utils.deepSetValue(imp, 'pmp', { deals: bidRequest.params.deals });
74
+ }
75
+
76
+ return imp;
77
+ },
78
+ request(buildRequest, imps, bidderRequest, context) {
79
+ const req = buildRequest(imps, bidderRequest, context);
80
+ mergeDeep(req, {
81
+ at: 1,
82
+ ext: {
83
+ bc: `${bidderConfig}_${bidderVersion}`
84
+ }
85
+ })
86
+
87
+ let userAgent = navigator.userAgent;
88
+ utils.deepSetValue(req, 'device.os', spec.getOS(userAgent));
89
+ utils.deepSetValue(req, 'device.devicetype', _isMobile() ? 1 : _isConnectedTV() ? 3 : 2);
90
+
91
+ const bid = context.bidRequests[0];
92
+ if (bid.params.publisherId) {
93
+ utils.deepSetValue(req, 'site.publisher.id', bid.params.publisherId);
94
+ }
95
+
96
+ return req;
97
+ },
98
+
99
+ bidResponse(buildBidResponse, bid, context) {
100
+ let bidResponse = buildBidResponse(bid, context);
101
+
102
+ if (bid.ext) {
103
+ bidResponse.meta.networkId = bid.ext.dsp_id;
104
+ bidResponse.meta.advertiserId = bid.ext.buyer_id;
105
+ bidResponse.meta.brandId = bid.ext.brand_id;
106
+ }
107
+
108
+ if (context.ortbResponse.ext && context.ortbResponse.ext.paf) {
109
+ bidResponse.meta.paf = Object.assign({}, context.ortbResponse.ext.paf);
110
+ bidResponse.meta.paf.content_id = utils.deepAccess(bid, 'ext.paf.content_id');
111
+ }
112
+
113
+ bidResponse = buildVideoVastResponse(bidResponse)
114
+ bidResponse = buildVideoOutstreamResponse(bidResponse, context)
115
+
116
+ return bidResponse;
117
+ },
118
+ response(buildResponse, bidResponses, ortbResponse, context) {
119
+ const response = buildResponse(bidResponses, ortbResponse, context);
120
+
121
+ let fledgeAuctionConfigs = utils.deepAccess(ortbResponse, 'ext.fledge_auction_configs');
122
+ if (fledgeAuctionConfigs) {
123
+ fledgeAuctionConfigs = Object.entries(fledgeAuctionConfigs).map(([bidId, cfg]) => {
124
+ return Object.assign({
125
+ bidId,
126
+ auctionSignals: {}
127
+ }, cfg);
128
+ });
129
+ return {
130
+ bids: response.bids,
131
+ fledgeAuctionConfigs,
132
+ }
133
+ } else {
134
+ return response.bids
135
+ }
136
+ }
137
+ });
138
+
139
+ function isBidRequestValid(bidRequest) {
140
+ return (isPublisherIdValid(bidRequest) && (isValidBannerRequest(bidRequest) || isValidVideoRequest(bidRequest)));
141
+ }
142
+
143
+ function isPublisherIdValid(bidRequest) {
144
+ let pubId = utils.deepAccess(bidRequest, 'params.publisherId');
145
+ return (pubId != null && utils.isStr(pubId) && pubId != '');
146
+ }
147
+
148
+ function isValidBannerRequest(bidRequest) {
149
+ const bannerSizes = utils.deepAccess(bidRequest, `mediaTypes.${BANNER}.sizes`);
150
+
151
+ return utils.isArray(bannerSizes) && bannerSizes.length > 0 && bannerSizes.every(size => utils.isNumber(size[0]) && utils.isNumber(size[1]));
152
+ }
153
+
154
+ function isValidVideoRequest(bidRequest) {
155
+ const videoSizes = utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}.playerSize`);
156
+ const PARAM_EXISTS = VIDEO_ORTB_REQUIRED.every(param => utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}.${param}`) != null);
157
+
158
+ return PARAM_EXISTS && utils.isArray(videoSizes) && videoSizes.length > 0 && videoSizes.every(size => utils.isNumber(size[0]) && utils.isNumber(size[1]));
159
+ }
160
+
161
+ function buildRequests(validBids, bidderRequest) {
162
+ let videoBids = validBids.filter(bid => isVideoBid(bid));
163
+ let bannerBids = validBids.filter(bid => isBannerBid(bid));
164
+ let requests = [];
165
+
166
+ bannerBids.forEach(bid => {
167
+ requests.push(createRequest([bid], bidderRequest, BANNER));
168
+ });
169
+
170
+ videoBids.forEach(bid => {
171
+ requests.push(createRequest([bid], bidderRequest, VIDEO));
172
+ });
173
+
174
+ return requests;
175
+ }
176
+
177
+ function buildVideoImp(bidRequest, imp) {
178
+ if (bidRequest.mediaTypes[VIDEO]?.context === 'outstream') {
179
+ imp.video.placement = imp.video.placement || 4;
180
+ }
181
+
182
+ const videoMediaType = utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}`);
183
+ const videoSizes = (videoMediaType && videoMediaType.playerSize) || [];
184
+
185
+ if (videoSizes && videoSizes.length > 0) {
186
+ utils.deepSetValue(imp, 'video.w', videoSizes[0][0]);
187
+ utils.deepSetValue(imp, 'video.h', videoSizes[0][1]);
188
+ }
189
+
190
+ const videoAdUnitParams = utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}`, {});
191
+ const videoBidderParams = utils.deepAccess(bidRequest, `params.${VIDEO}`, {});
192
+
193
+ const videoParams = { ...videoAdUnitParams, ...videoBidderParams };
194
+
195
+ VIDEO_ORTB_PARAMS.forEach((param) => {
196
+ if (videoParams.hasOwnProperty(param)) {
197
+ utils.deepSetValue(imp, `video.${param}`, videoParams[param]);
198
+ }
199
+ });
200
+
201
+ return { ...imp };
202
+ }
203
+
204
+ function buildBannerImp(bidRequest, imp) {
205
+ const bannerSizes = utils.deepAccess(bidRequest, `mediaTypes.${BANNER}.sizes`, []);
206
+
207
+ if (bannerSizes && bannerSizes.length > 0) {
208
+ utils.deepSetValue(imp, 'banner.w', bannerSizes[0][0]);
209
+ utils.deepSetValue(imp, 'banner.h', bannerSizes[0][1]);
210
+ }
211
+
212
+ return {...imp};
213
+ }
214
+
215
+ function createRequest(bidRequests, bidderRequest, mediaType) {
216
+ return {
217
+ method: 'POST',
218
+ url: REQUEST_URL,
219
+ data: CONVERTER.toORTB({ bidRequests, bidderRequest, context: { mediaType } })
220
+ }
221
+ }
222
+
223
+ function buildVideoVastResponse(bidResponse) {
224
+ if (bidResponse.mediaType == VIDEO && bidResponse.vastXml) {
225
+ bidResponse.vastUrl = bidResponse.vastXml;
226
+ }
227
+
228
+ return { ...bidResponse }
229
+ }
230
+
231
+ function buildVideoOutstreamResponse(bidResponse, context) {
232
+ if (context.bidRequest.mediaTypes[VIDEO]?.context === 'outstream') {
233
+ bidResponse.rendererUrl = SP_OUTSTREAM_PLAYER_URL;
234
+ bidResponse.adUnitCode = context.bidRequest.adUnitCode;
235
+
236
+ bidResponse.renderer = Renderer.install({
237
+ id: bidResponse.requestId,
238
+ adUnitCode: context.bidRequest.adUnitCode,
239
+ url: bidResponse.rendererUrl
240
+ });
241
+
242
+ bidResponse.renderer.setRender(_renderer(bidResponse));
243
+
244
+ bidResponse.renderer.render(bidResponse);
245
+ }
246
+
247
+ return {...bidResponse};
248
+ }
249
+
250
+ function getBidFloor(bid) {
251
+ const currency = config.getConfig('currency.adServerCurrency') || DEFAULT_CURRENCY;
252
+
253
+ if (typeof bid.getFloor !== 'function') {
254
+ return utils.deepAccess(bid, 'params.bidFloor', 0.05);
255
+ }
256
+
257
+ const bidFloor = bid.getFloor({
258
+ currency: currency,
259
+ mediaType: '*',
260
+ size: '*',
261
+ });
262
+ return bidFloor.floor;
263
+ }
264
+
265
+ function _renderer(bid) {
266
+ bid.renderer.push(() => {
267
+ if (typeof window.SPOutStreamPlayer === 'function') {
268
+ const spoplayer = new window.SPOutStreamPlayer(bid);
269
+
270
+ spoplayer.on('ready', () => {
271
+ spoplayer.startAd();
272
+ });
273
+
274
+ try {
275
+ let vastUrlbt = 'data:text/xml;charset=utf-8;base64,' + btoa(bid.vastUrl.replace(/\\"/g, '"'));
276
+ spoplayer.load(vastUrlbt).then(function() {
277
+ window.spoplayer = spoplayer;
278
+ }).catch(function(reason) {
279
+ setTimeout(function() { throw reason; }, 0);
280
+ });
281
+ } catch (err) {
282
+ utils.logMessage(err);
283
+ }
284
+ } else {
285
+ utils.logMessage(`Silverpush outstream player is not defined`);
286
+ }
287
+ });
288
+ }
289
+
290
+ function isVideoBid(bid) {
291
+ return utils.deepAccess(bid, 'mediaTypes.video');
292
+ }
293
+
294
+ function isBannerBid(bid) {
295
+ return utils.deepAccess(bid, 'mediaTypes.banner') || !isVideoBid(bid);
296
+ }
297
+
298
+ function interpretResponse(resp, req) {
299
+ if (!resp.body) {
300
+ resp.body = { nbr: 0 };
301
+ }
302
+
303
+ return CONVERTER.fromORTB({ request: req.data, response: resp.body });
304
+ }
305
+
306
+ function onBidWon(bid) {
307
+ if (bid == null) { return; }
308
+ if (bid['burl'] == null) { return; }
309
+
310
+ let burlMac = bid['burl'];
311
+ burlMac = burlMac.replace('$' + '{AUCTION_PRICE}', bid['cpm']);
312
+ burlMac = burlMac.replace('$' + '{AUCTION_ID}', bid['auctionId']);
313
+ burlMac = burlMac.replace('$' + '{AUCTION_IMP_ID}', bid['requestId']);
314
+ burlMac = burlMac.replace('$' + '{AUCTION_AD_ID}', bid['adId']);
315
+ burlMac = burlMac.replace('$' + '{AUCTION_SEAT_ID}', bid['seatBidId']);
316
+
317
+ spec.getRequest(burlMac);
318
+ }
319
+
320
+ function _isMobile() {
321
+ return (/(ios|ipod|ipad|iphone|android)/i).test(navigator.userAgent);
322
+ }
323
+
324
+ function _isConnectedTV() {
325
+ return (/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(navigator.userAgent);
326
+ }
@@ -0,0 +1,107 @@
1
+ # Overview
2
+
3
+ ```
4
+ Module Name: Silverpush OpenRTB Bidder Adapter
5
+ Module Type: Bidder Adapter
6
+ Maintainer: prebid@silverpush.co
7
+ ```
8
+
9
+ # Description
10
+
11
+ Prebid.JS adapter that connects to the Chocolate Ad Exchange.
12
+
13
+ *NOTE*: The Silverpush Bidder Adapter requires setup and approval before use. Please reach out to prebid@silverpush.co representative for more details.
14
+
15
+ # Bid Parameters
16
+
17
+ ## Banner/Video
18
+
19
+ {: .table .table-bordered .table-striped }
20
+ | Name | Scope | Description | Example | Type |
21
+ | -------------- | ----------- | ------------------------------------------ | ------------- | ------------ |
22
+ | `publisherId` | required | Publisher id provided by silverpush | "123456" | String |
23
+ | `bidFloor` | optional | Minimum price in USD. bidFloor applies to a specific unit. For example, use the following value to set a $1.50 floor: 1.50. <br/> | 1.50 | Number |
24
+
25
+
26
+
27
+
28
+ # mediaTypes Parameters
29
+
30
+ ## mediaTypes.banner
31
+
32
+ The following banner parameters are supported here so publishers may fully declare their banner inventory:
33
+
34
+ {: .table .table-bordered .table-striped }
35
+ | Name | Scope | Description | Example | Type |
36
+ | --------- | ------------| ----------------------------------------------------------------- | --------- | --------- |
37
+ | sizes | required | Avalaible sizes supported for banner ad unit | [ [300, 250], [300, 600] ] | [[Integer, Integer], [Integer, Integer]] |
38
+
39
+ ## mediaTypes.video
40
+
41
+
42
+ The following video parameters are supported here so publishers may fully declare their video inventory:
43
+
44
+ {: .table .table-bordered .table-striped }
45
+ | Name | Scope | Description | Example | Type |
46
+ | --------- | ------------| ----------------------------------------------------------------- | --------- | --------- |
47
+ | context | required | instream or outstream |"outstream" | string |
48
+ | playerSize | required | Avalaible sizes supported for video ad unit. | [300, 250] | [Integer, Integer] |
49
+ | mimes | required | List of content MIME types supported by the player. | ["video/mp4"]| [String]|
50
+ | protocols | required | Supported video bid response protocol values. | [2,3,5,6] | [integers]|
51
+ | api | required | Supported API framework values. | [2] | [integers] |
52
+ | maxduration | required | Maximum video ad duration in seconds. | 30 | Integer |
53
+ | minduration | required | Minimum video ad duration in seconds. | 6 | Integer |
54
+ | startdelay | required | Indicates the start delay in seconds for pre-roll, mid-roll, or post-roll ad placements. | 0 | Integer |
55
+ | placement | required | Placement type for the impression. | 1 | Integer |
56
+ | minbitrate | optional | Minimum bit rate in Kbps. | 300 | Integer |
57
+ | maxbitrate | optional | Maximum bit rate in Kbps. | 9600 | Integer |
58
+ | playbackmethod | optional | Playback methods that may be in use. Only one method is typically used in practice. | [2]| [Integers] |
59
+ | linearity | optional | OpenRTB2 linearity. in-strea,overlay... | 1 | Integer |
60
+ | skip | optional | Indicates if the player will allow the video to be skipped, where 0 = no, 1 = yes . | 1 | Integer |
61
+ | skipafter | optional | Number of seconds a video must play before skipping is enabled; only applicable if the ad is skippable. | 5 | Integer |
62
+ | delivery | optional | OpenRTB2 delivery. Supported delivery methods (e.g., streaming, progressive). If none specified, assume all are supported. | 1 | [Integer] |
63
+
64
+
65
+ # Example
66
+ ```javascript
67
+ var adUnits = [{
68
+ code: 'div-1',
69
+ mediaTypes: {
70
+ banner: {
71
+ sizes: [ [300, 250], [300,600] ]
72
+ }
73
+ },
74
+ bids: [{
75
+ bidder: 'silverpush',
76
+ params: {
77
+ publisherId: "123456",
78
+ bidFloor: 1.2
79
+ }
80
+ }]
81
+ },{
82
+ code: 'video-1',
83
+ mediaTypes: {
84
+ video: {
85
+ api: [1, 2, 4, 6],
86
+ mimes: ['video/mp4'],
87
+ context: 'instream', // or 'outstream'
88
+ playerSize: [ 640, 480 ],
89
+ protocols: [4,5,6,7],
90
+ placement: 1,
91
+ minduration: 0,
92
+ maxduration: 60,
93
+ startdelay: 0
94
+ }
95
+ },
96
+ bids: [
97
+ {
98
+ bidder: 'silverpush',
99
+ params: {
100
+ publisherId: "123456",
101
+ bidfloor: 2.5
102
+ }
103
+ }
104
+ ]
105
+ }
106
+ ];
107
+ ```