prebid.js 7.22.0 → 7.23.1

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 (273) hide show
  1. package/dist/33acrossBidAdapter.js +1 -1
  2. package/dist/aaxBlockmeterRtdProvider.js +1 -0
  3. package/dist/adagioBidAdapter.js +1 -1
  4. package/dist/adbookpspBidAdapter.js +1 -1
  5. package/dist/adgenerationBidAdapter.js +1 -1
  6. package/dist/adrelevantisBidAdapter.js +1 -1
  7. package/dist/adtrgtmeBidAdapter.js +1 -1
  8. package/dist/adxcgBidAdapter.js +1 -1
  9. package/dist/ajaBidAdapter.js +1 -1
  10. package/dist/amxBidAdapter.js +1 -1
  11. package/dist/amxIdSystem.js +1 -1
  12. package/dist/analyticsAdapter.js +1 -1
  13. package/dist/appierAnalyticsAdapter.js +1 -1
  14. package/dist/appnexusBidAdapter.js +1 -1
  15. package/dist/asoBidAdapter.js +1 -1
  16. package/dist/axonixBidAdapter.js +1 -1
  17. package/dist/bidViewability.js +1 -1
  18. package/dist/bidViewabilityIO.js +1 -1
  19. package/dist/bidglassBidAdapter.js +1 -1
  20. package/dist/big-richmediaBidAdapter.js +1 -1
  21. package/dist/bridgewellBidAdapter.js +1 -1
  22. package/dist/brightMountainMediaBidAdapter.js +1 -1
  23. package/dist/browsiRtdProvider.js +1 -1
  24. package/dist/carodaBidAdapter.js +1 -1
  25. package/dist/chtnwBidAdapter.js +1 -0
  26. package/dist/cleanioRtdProvider.js +1 -1
  27. package/dist/concertBidAdapter.js +1 -1
  28. package/dist/connectadBidAdapter.js +1 -1
  29. package/dist/consentManagement.js +1 -1
  30. package/dist/consentManagementUsp.js +1 -1
  31. package/dist/consumableBidAdapter.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/currency.js +1 -1
  36. package/dist/dependencies.json +19 -0
  37. package/dist/dfpAdServerVideo.js +1 -1
  38. package/dist/dgkeywordRtdProvider.js +1 -1
  39. package/dist/dspxBidAdapter.js +1 -1
  40. package/dist/eplanningBidAdapter.js +1 -1
  41. package/dist/finativeBidAdapter.js +1 -1
  42. package/dist/gdprEnforcement.js +1 -1
  43. package/dist/glimpseBidAdapter.js +1 -1
  44. package/dist/gmosspBidAdapter.js +1 -1
  45. package/dist/goldbachBidAdapter.js +1 -1
  46. package/dist/googleAnalyticsAdapter.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/id5AnalyticsAdapter.js +1 -1
  52. package/dist/id5IdSystem.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/instreamTracking.js +1 -1
  57. package/dist/ixBidAdapter.js +1 -1
  58. package/dist/justpremiumBidAdapter.js +1 -1
  59. package/dist/jwplayerVideoProvider.js +1 -0
  60. package/dist/kargoBidAdapter.js +1 -1
  61. package/dist/konduitAnalyticsAdapter.js +1 -1
  62. package/dist/kueezBidAdapter.js +1 -1
  63. package/dist/lassoBidAdapter.js +1 -1
  64. package/dist/lifestreetBidAdapter.js +1 -1
  65. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  66. package/dist/logicadBidAdapter.js +1 -1
  67. package/dist/loglyliftBidAdapter.js +1 -1
  68. package/dist/magniteAnalyticsAdapter.js +1 -1
  69. package/dist/malltvAnalyticsAdapter.js +1 -1
  70. package/dist/marsmediaBidAdapter.js +1 -1
  71. package/dist/mediafuseBidAdapter.js +1 -1
  72. package/dist/mediasquareBidAdapter.js +1 -1
  73. package/dist/mgidBidAdapter.js +1 -1
  74. package/dist/minutemediaBidAdapter.js +1 -1
  75. package/dist/multibid.js +1 -1
  76. package/dist/not-for-prod/prebid.js +141 -132
  77. package/dist/oguryBidAdapter.js +1 -1
  78. package/dist/onetagBidAdapter.js +1 -1
  79. package/dist/ooloAnalyticsAdapter.js +1 -1
  80. package/dist/openxOrtbBidAdapter.js +1 -1
  81. package/dist/ortbConverter.js +1 -0
  82. package/dist/outbrainBidAdapter.js +1 -1
  83. package/dist/oxxionRtdProvider.js +1 -0
  84. package/dist/parrableIdSystem.js +1 -1
  85. package/dist/pbsExtensions.js +1 -0
  86. package/dist/pixfutureBidAdapter.js +1 -1
  87. package/dist/prebid-core.js +1 -1
  88. package/dist/prebidServerBidAdapter.js +1 -1
  89. package/dist/priceFloors.js +1 -1
  90. package/dist/pubCommonId.js +1 -1
  91. package/dist/publinkIdSystem.js +1 -1
  92. package/dist/pubmaticBidAdapter.js +1 -1
  93. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  94. package/dist/pxyzBidAdapter.js +1 -1
  95. package/dist/quantcastBidAdapter.js +1 -1
  96. package/dist/readpeakBidAdapter.js +1 -1
  97. package/dist/relaidoBidAdapter.js +1 -1
  98. package/dist/rhythmoneBidAdapter.js +1 -1
  99. package/dist/riseBidAdapter.js +1 -1
  100. package/dist/rtdModule.js +1 -1
  101. package/dist/rubiconAnalyticsAdapter.js +1 -1
  102. package/dist/rubiconBidAdapter.js +1 -1
  103. package/dist/schain.js +1 -1
  104. package/dist/seedingAllianceBidAdapter.js +1 -1
  105. package/dist/seedtagBidAdapter.js +1 -1
  106. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  107. package/dist/sharethroughBidAdapter.js +1 -1
  108. package/dist/shinezBidAdapter.js +1 -1
  109. package/dist/smaatoBidAdapter.js +1 -1
  110. package/dist/smartadserverBidAdapter.js +1 -1
  111. package/dist/smartxBidAdapter.js +1 -1
  112. package/dist/smilewantedBidAdapter.js +1 -1
  113. package/dist/sonobiBidAdapter.js +1 -1
  114. package/dist/sovrnAnalyticsAdapter.js +1 -1
  115. package/dist/sovrnBidAdapter.js +1 -1
  116. package/dist/spotxBidAdapter.js +1 -1
  117. package/dist/sspBCBidAdapter.js +1 -1
  118. package/dist/sublimeBidAdapter.js +1 -1
  119. package/dist/synacormediaBidAdapter.js +1 -1
  120. package/dist/targetVideoBidAdapter.js +1 -1
  121. package/dist/teadsBidAdapter.js +1 -1
  122. package/dist/teadsIdSystem.js +1 -1
  123. package/dist/trionBidAdapter.js +1 -1
  124. package/dist/tripleliftBidAdapter.js +1 -1
  125. package/dist/ttdBidAdapter.js +1 -1
  126. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  127. package/dist/underdogmediaBidAdapter.js +1 -1
  128. package/dist/undertoneBidAdapter.js +1 -1
  129. package/dist/userId.js +1 -1
  130. package/dist/vidazooBidAdapter.js +1 -1
  131. package/dist/video.js +1 -0
  132. package/dist/videoModule.js +1 -0
  133. package/dist/videobyteBidAdapter.js +1 -1
  134. package/dist/videojsVideoProvider.js +1 -0
  135. package/dist/visxBidAdapter.js +1 -1
  136. package/dist/vuukleBidAdapter.js +1 -1
  137. package/dist/widespaceBidAdapter.js +1 -1
  138. package/dist/winrBidAdapter.js +1 -1
  139. package/dist/yahoosspBidAdapter.js +1 -1
  140. package/dist/yieldmoBidAdapter.js +1 -1
  141. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  142. package/integrationExamples/videoModule/jwplayer/bidMarkedAsUsed.html +98 -0
  143. package/integrationExamples/videoModule/jwplayer/bidRequestScheduling.html +89 -0
  144. package/integrationExamples/videoModule/jwplayer/eventListeners.html +244 -0
  145. package/integrationExamples/videoModule/jwplayer/gamAdServerMediation.html +122 -0
  146. package/integrationExamples/videoModule/jwplayer/mediaMetadata.html +80 -0
  147. package/integrationExamples/videoModule/jwplayer/playlist.html +122 -0
  148. package/integrationExamples/videoModule/videojs/bidMarkedAsUsed.html +126 -0
  149. package/integrationExamples/videoModule/videojs/bidRequestScheduling.html +132 -0
  150. package/integrationExamples/videoModule/videojs/eventListeners.html +238 -0
  151. package/integrationExamples/videoModule/videojs/gamAdServerMediation.html +138 -0
  152. package/integrationExamples/videoModule/videojs/mediaMetadata.html +103 -0
  153. package/integrationExamples/videoModule/videojs/playlist.html +151 -0
  154. package/libraries/ortbConverter/README.md +378 -0
  155. package/libraries/ortbConverter/converter.js +135 -0
  156. package/libraries/ortbConverter/lib/composer.js +43 -0
  157. package/libraries/ortbConverter/lib/mergeProcessors.js +9 -0
  158. package/libraries/ortbConverter/lib/sizes.js +14 -0
  159. package/libraries/ortbConverter/processors/banner.js +40 -0
  160. package/libraries/ortbConverter/processors/default.js +167 -0
  161. package/libraries/ortbConverter/processors/mediaType.js +21 -0
  162. package/libraries/ortbConverter/processors/native.js +37 -0
  163. package/libraries/ortbConverter/processors/video.js +66 -0
  164. package/libraries/pbsExtensions/pbsExtensions.js +12 -0
  165. package/libraries/pbsExtensions/processors/aliases.js +17 -0
  166. package/libraries/pbsExtensions/processors/mediaType.js +23 -0
  167. package/libraries/pbsExtensions/processors/params.js +22 -0
  168. package/libraries/pbsExtensions/processors/pbs.js +99 -0
  169. package/libraries/pbsExtensions/processors/requestExtPrebid.js +30 -0
  170. package/libraries/pbsExtensions/processors/video.js +23 -0
  171. package/libraries/video/constants/enums.js +5 -0
  172. package/libraries/video/constants/events.js +97 -0
  173. package/libraries/video/constants/ortb.js +169 -0
  174. package/libraries/video/constants/vendorCodes.js +6 -0
  175. package/libraries/video/shared/eventHandler.js +18 -0
  176. package/libraries/video/shared/parentModule.js +82 -0
  177. package/libraries/video/shared/state.js +47 -0
  178. package/libraries/video/shared/vastXmlBuilder.js +77 -0
  179. package/libraries/video/shared/vastXmlEditor.js +115 -0
  180. package/modules/.submodules.json +6 -1
  181. package/modules/aaxBlockmeterRtdProvider.js +59 -0
  182. package/modules/aaxBlockmeterRtdProvider.md +48 -0
  183. package/modules/appnexusBidAdapter.js +38 -1
  184. package/modules/chtnwBidAdapter.js +110 -0
  185. package/modules/chtnwBidAdapter.md +31 -0
  186. package/modules/concertBidAdapter.js +44 -2
  187. package/modules/consentManagement.js +22 -1
  188. package/modules/consentManagementUsp.js +29 -7
  189. package/modules/criteoBidAdapter.js +25 -5
  190. package/modules/currency.js +9 -0
  191. package/modules/dgkeywordRtdProvider.js +3 -3
  192. package/modules/gridNMBidAdapter.js +10 -14
  193. package/modules/improvedigitalBidAdapter.js +191 -470
  194. package/modules/ixBidAdapter.js +24 -64
  195. package/modules/jwplayerVideoProvider.js +929 -0
  196. package/modules/jwplayerVideoProvider.md +25 -0
  197. package/modules/kargoBidAdapter.js +1 -1
  198. package/modules/multibid/index.js +12 -0
  199. package/modules/openxOrtbBidAdapter.js +120 -275
  200. package/modules/oxxionRtdProvider.js +119 -0
  201. package/modules/oxxionRtdProvider.md +48 -0
  202. package/modules/prebidServerBidAdapter/index.js +19 -716
  203. package/modules/prebidServerBidAdapter/ortbConverter.js +274 -0
  204. package/modules/priceFloors.js +73 -1
  205. package/modules/rtdModule/index.js +22 -1
  206. package/modules/schain.js +24 -1
  207. package/modules/spotxBidAdapter.js +16 -15
  208. package/modules/synacormediaBidAdapter.js +1 -1
  209. package/modules/teadsIdSystem.js +5 -0
  210. package/modules/userId/index.js +64 -6
  211. package/modules/videoModule/addingSubmodule.md +521 -0
  212. package/modules/videoModule/coreVideo.js +234 -0
  213. package/modules/videoModule/gamAdServerSubmodule.js +27 -0
  214. package/modules/videoModule/index.js +244 -0
  215. package/modules/videoModule/videoImpressionVerifier.js +206 -0
  216. package/modules/videojsVideoProvider.js +854 -0
  217. package/modules/videojsVideoProvider.md +17 -0
  218. package/package.json +5 -1
  219. package/src/adapterManager.js +56 -7
  220. package/src/adloader.js +2 -1
  221. package/src/auction.js +5 -0
  222. package/src/events.js +5 -1
  223. package/src/pbjsORTB.js +35 -0
  224. package/src/prebid.js +137 -112
  225. package/src/targeting.js +10 -2
  226. package/src/utils/currency.js +16 -0
  227. package/src/utils.js +21 -0
  228. package/test/spec/auctionmanager_spec.js +6 -0
  229. package/test/spec/modules/aaxBlockmeter_spec.js +58 -0
  230. package/test/spec/modules/chtnwBidAdapter_spec.js +105 -0
  231. package/test/spec/modules/concertBidAdapter_spec.js +56 -0
  232. package/test/spec/modules/consentManagementUsp_spec.js +64 -18
  233. package/test/spec/modules/criteoBidAdapter_spec.js +28 -0
  234. package/test/spec/modules/dgkeywordRtdProvider_spec.js +3 -3
  235. package/test/spec/modules/improvedigitalBidAdapter_spec.js +231 -211
  236. package/test/spec/modules/ixBidAdapter_spec.js +230 -371
  237. package/test/spec/modules/openxOrtbBidAdapter_spec.js +77 -49
  238. package/test/spec/modules/oxxionRtdProvider_spec.js +142 -0
  239. package/test/spec/modules/prebidServerBidAdapter_spec.js +139 -137
  240. package/test/spec/modules/realTimeDataModule_spec.js +65 -0
  241. package/test/spec/modules/userId_spec.js +67 -1
  242. package/test/spec/modules/videoModule/coreVideo_spec.js +98 -0
  243. package/test/spec/modules/videoModule/pbVideo_spec.js +362 -0
  244. package/test/spec/modules/videoModule/shared/parentModule_spec.js +73 -0
  245. package/test/spec/modules/videoModule/shared/state_spec.js +26 -0
  246. package/test/spec/modules/videoModule/shared/vastXmlBuilder_spec.js +103 -0
  247. package/test/spec/modules/videoModule/shared/vastXmlEditor_spec.js +209 -0
  248. package/test/spec/modules/videoModule/submodules/jwplayerVideoProvider_spec.js +846 -0
  249. package/test/spec/modules/videoModule/submodules/videojsVideoProvider_spec.js +391 -0
  250. package/test/spec/modules/videoModule/videoImpressionVerifier_spec.js +112 -0
  251. package/test/spec/ortbConverter/banner_spec.js +203 -0
  252. package/test/spec/ortbConverter/composer_spec.js +69 -0
  253. package/test/spec/ortbConverter/converter_spec.js +283 -0
  254. package/test/spec/ortbConverter/currency_spec.js +40 -0
  255. package/test/spec/ortbConverter/default_processors_spec.js +61 -0
  256. package/test/spec/ortbConverter/gdpr_spec.js +38 -0
  257. package/test/spec/ortbConverter/mediaTypes_spec.js +67 -0
  258. package/test/spec/ortbConverter/mergeProcessors_spec.js +59 -0
  259. package/test/spec/ortbConverter/multibid_spec.js +35 -0
  260. package/test/spec/ortbConverter/native_spec.js +95 -0
  261. package/test/spec/ortbConverter/pbjsORTB_spec.js +67 -0
  262. package/test/spec/ortbConverter/pbsExtensions/aliases_spec.js +57 -0
  263. package/test/spec/ortbConverter/pbsExtensions/params_spec.js +96 -0
  264. package/test/spec/ortbConverter/pbsExtensions/video_spec.js +52 -0
  265. package/test/spec/ortbConverter/priceFloors_spec.js +143 -0
  266. package/test/spec/ortbConverter/schain_spec.js +33 -0
  267. package/test/spec/ortbConverter/userId_spec.js +21 -0
  268. package/test/spec/ortbConverter/usp_spec.js +15 -0
  269. package/test/spec/ortbConverter/video_spec.js +189 -0
  270. package/test/spec/unit/core/adapterManager_spec.js +102 -0
  271. package/test/spec/unit/core/targeting_spec.js +34 -0
  272. package/test/spec/unit/pbjs_api_spec.js +124 -45
  273. package/test/spec/utils_spec.js +45 -1
@@ -0,0 +1,25 @@
1
+ # Overview
2
+
3
+ Module Name: JW Player Video Provider
4
+ Module Type: Video Submodule
5
+ Video Player: JW player
6
+ Player website: https://www.jwplayer.com/html5-video-player/
7
+ Maintainer: karim@jwplayer.com
8
+
9
+ # Description
10
+
11
+ Video provider to connect the Prebid Video Module to JW Player.
12
+
13
+ # Requirements
14
+
15
+ Your page must embed a build of JW Player.
16
+ i.e.
17
+ ```html
18
+ <head>
19
+ <script src="https://cdn.jwplayer.com/players/UVQWMA4o-kGWxh33Q.js"></script>
20
+ </head>
21
+ ```
22
+
23
+ [Additional embed instructions](https://docs.jwplayer.com/platform/docs/players-get-started)
24
+
25
+ [Obtaining a license](https://info.jwplayer.com/contact-us/)
@@ -225,7 +225,7 @@ export const spec = {
225
225
  _getAllMetadata(bidderRequest, tdid) {
226
226
  return {
227
227
  userIDs: spec._getUserIds(tdid, bidderRequest.uspConsent, bidderRequest.gdprConsent),
228
- pageURL: bidderRequest.refererInfo && bidderRequest.refererInfo.page,
228
+ pageURL: bidderRequest?.refererInfo?.topmostLocation || bidderRequest?.refererInfo?.page,
229
229
  rawCRB: storage.getCookie('krg_crb'),
230
230
  rawCRBLocalStorage: spec._getLocalStorageSafely('krg_crb')
231
231
  };
@@ -12,6 +12,7 @@ import * as events from '../../src/events.js';
12
12
  import CONSTANTS from '../../src/constants.json';
13
13
  import {addBidderRequests} from '../../src/auction.js';
14
14
  import {getHighestCpmBidsFromBidPool, sortByDealAndPriceBucketOrCpm} from '../../src/targeting.js';
15
+ import {PBS, registerOrtbProcessor, REQUEST} from '../../src/pbjsORTB.js';
15
16
  import {timedBidResponseHook} from '../../src/utils/perfMetrics.js';
16
17
 
17
18
  const MODULE_NAME = 'multibid';
@@ -236,3 +237,14 @@ function init() {
236
237
  }
237
238
 
238
239
  init();
240
+
241
+ export function setOrtbExtPrebidMultibid(ortbRequest) {
242
+ const multibid = config.getConfig('multibid');
243
+ if (multibid) {
244
+ deepSetValue(ortbRequest, 'ext.prebid.multibid', multibid.map(o =>
245
+ Object.fromEntries(Object.entries(o).map(([k, v]) => [k.toLowerCase(), v])))
246
+ )
247
+ }
248
+ }
249
+
250
+ registerOrtbProcessor({type: REQUEST, name: 'extPrebidMultibid', fn: setOrtbExtPrebidMultibid, dialects: [PBS]});
@@ -1,14 +1,12 @@
1
1
  import {config} from '../src/config.js';
2
2
  import {registerBidder} from '../src/adapters/bidderFactory.js';
3
3
  import * as utils from '../src/utils.js';
4
+ import {mergeDeep} from '../src/utils.js';
4
5
  import {BANNER, VIDEO} from '../src/mediaTypes.js';
5
- import {includes} from '../src/polyfill.js';
6
+ import {ortbConverter} from '../libraries/ortbConverter/converter.js';
6
7
 
7
8
  const bidderConfig = 'hb_pb_ortb';
8
9
  const bidderVersion = '1.0';
9
- const VIDEO_TARGETING = ['startdelay', 'mimes', 'minduration', 'maxduration', 'delivery',
10
- 'startdelay', 'skip', 'playbackmethod', 'api', 'protocol', 'boxingallowed', 'maxextended',
11
- 'linearity', 'delivery', 'protocols', 'placement', 'minbitrate', 'maxbitrate', 'battr', 'ext'];
12
10
  export const REQUEST_URL = 'https://rtb.openx.net/openrtbb/prebidjs';
13
11
  export const SYNC_URL = 'https://u.openx.net/w/1.0/pd';
14
12
  export const DEFAULT_PH = '2d1251ae-7f3a-47cf-bd2a-2f288854a0ba';
@@ -24,6 +22,118 @@ export const spec = {
24
22
 
25
23
  registerBidder(spec);
26
24
 
25
+ const converter = ortbConverter({
26
+ context: {
27
+ netRevenue: true,
28
+ ttl: 300
29
+ },
30
+ imp(buildImp, bidRequest, context) {
31
+ const imp = buildImp(bidRequest, context);
32
+ if (bidRequest.mediaTypes[VIDEO]?.context === 'outstream') {
33
+ imp.video.placement = imp.video.placement || 4;
34
+ }
35
+ if (imp.ext?.ae && !context.bidderRequest.fledgeEnabled) {
36
+ // TODO: we may want to standardize this and move fledge logic to ortbConverter
37
+ delete imp.ext.ae;
38
+ }
39
+ mergeDeep(imp, {
40
+ tagid: bidRequest.params.unit,
41
+ ext: {
42
+ divid: bidRequest.adUnitCode
43
+ }
44
+ });
45
+ if (bidRequest.params.customParams) {
46
+ utils.deepSetValue(imp, 'ext.customParams', bidRequest.params.customParams);
47
+ }
48
+ if (bidRequest.params.customFloor && !imp.bidfloor) {
49
+ imp.bidfloor = bidRequest.params.customFloor;
50
+ }
51
+ return imp;
52
+ },
53
+ request(buildRequest, imps, bidderRequest, context) {
54
+ const req = buildRequest(imps, bidderRequest, context);
55
+ mergeDeep(req, {
56
+ at: 1,
57
+ ext: {
58
+ bc: `${bidderConfig}_${bidderVersion}`
59
+ }
60
+ })
61
+ const bid = context.bidRequests[0];
62
+ if (bid.params.doNotTrack) {
63
+ utils.deepSetValue(req, 'device.dnt', 1);
64
+ }
65
+ if (bid.params.platform) {
66
+ utils.deepSetValue(req, 'ext.platform', bid.params.platform);
67
+ }
68
+ if (bid.params.delDomain) {
69
+ utils.deepSetValue(req, 'ext.delDomain', bid.params.delDomain);
70
+ }
71
+ if (bid.params.response_template_name) {
72
+ utils.deepSetValue(req, 'ext.response_template_name', bid.params.response_template_name);
73
+ }
74
+ if (bid.params.test) {
75
+ req.test = 1
76
+ }
77
+ return req;
78
+ },
79
+ bidResponse(buildBidResponse, bid, context) {
80
+ const bidResponse = buildBidResponse(bid, context);
81
+ if (bid.ext) {
82
+ bidResponse.meta.networkId = bid.ext.dsp_id;
83
+ bidResponse.meta.advertiserId = bid.ext.buyer_id;
84
+ bidResponse.meta.brandId = bid.ext.brand_id;
85
+ }
86
+ const {ortbResponse} = context;
87
+ if (ortbResponse.ext && ortbResponse.ext.paf) {
88
+ bidResponse.meta.paf = Object.assign({}, ortbResponse.ext.paf);
89
+ bidResponse.meta.paf.content_id = utils.deepAccess(bid, 'ext.paf.content_id');
90
+ }
91
+ return bidResponse;
92
+ },
93
+ response(buildResponse, bidResponses, ortbResponse, context) {
94
+ // pass these from request to the responses for use in userSync
95
+ const {ortbRequest} = context;
96
+ if (ortbRequest.ext) {
97
+ if (ortbRequest.ext.delDomain) {
98
+ utils.deepSetValue(ortbResponse, 'ext.delDomain', ortbRequest.ext.delDomain);
99
+ }
100
+ if (ortbRequest.ext.platform) {
101
+ utils.deepSetValue(ortbResponse, 'ext.platform', ortbRequest.ext.platform);
102
+ }
103
+ }
104
+ const response = buildResponse(bidResponses, ortbResponse, context);
105
+ // TODO: we may want to standardize this and move fledge logic to ortbConverter
106
+ let fledgeAuctionConfigs = utils.deepAccess(ortbResponse, 'ext.fledge_auction_configs');
107
+ if (fledgeAuctionConfigs) {
108
+ fledgeAuctionConfigs = Object.entries(fledgeAuctionConfigs).map(([bidId, cfg]) => {
109
+ return Object.assign({
110
+ bidId,
111
+ auctionSignals: {}
112
+ }, cfg);
113
+ });
114
+ return {
115
+ bids: response.bids,
116
+ fledgeAuctionConfigs,
117
+ }
118
+ } else {
119
+ return response.bids
120
+ }
121
+ },
122
+ overrides: {
123
+ imp: {
124
+ bidfloor(setBidFloor, imp, bidRequest, context) {
125
+ // enforce floors should always be in USD
126
+ // TODO: does it make sense that request.cur can be any currency, but request.imp[].bidfloorcur must be USD?
127
+ const floor = {};
128
+ setBidFloor(floor, bidRequest, {...context, currency: 'USD'});
129
+ if (floor.bidfloorcur === 'USD') {
130
+ Object.assign(imp, floor);
131
+ }
132
+ }
133
+ }
134
+ }
135
+ });
136
+
27
137
  function transformBidParams(params, isOpenRtb) {
28
138
  return utils.convertTypes({
29
139
  'unit': 'string',
@@ -47,190 +157,21 @@ function isBidRequestValid(bidRequest) {
47
157
  function buildRequests(bids, bidderRequest) {
48
158
  let videoBids = bids.filter(bid => isVideoBid(bid));
49
159
  let bannerBids = bids.filter(bid => isBannerBid(bid));
50
- let requests = bannerBids.length ? [createBannerRequest(bannerBids, bidderRequest)] : [];
160
+ let requests = bannerBids.length ? [createRequest(bannerBids, bidderRequest, BANNER)] : [];
51
161
  videoBids.forEach(bid => {
52
- requests.push(createVideoRequest(bid, bidderRequest));
162
+ requests.push(createRequest([bid], bidderRequest, VIDEO));
53
163
  });
54
164
  return requests;
55
165
  }
56
166
 
57
- function createBannerRequest(bids, bidderRequest) {
58
- let data = getBaseRequest(bids[0], bidderRequest);
59
- data.imp = bids.map(bid => {
60
- const floor = getFloor(bid, BANNER);
61
- let imp = {
62
- id: bid.bidId,
63
- tagid: bid.params.unit,
64
- banner: {
65
- format: toFormat(bid.mediaTypes.banner.sizes),
66
- topframe: utils.inIframe() ? 0 : 1
67
- },
68
- ext: {divid: bid.adUnitCode}
69
- };
70
-
71
- if (bidderRequest.fledgeEnabled) {
72
- imp.ext.ae = bid?.ortb2Imp?.ext?.ae
73
- }
74
-
75
- enrichImp(imp, bid, floor);
76
- return imp;
77
- });
167
+ function createRequest(bidRequests, bidderRequest, mediaType) {
78
168
  return {
79
169
  method: 'POST',
80
170
  url: config.getConfig('openxOrtbUrl') || REQUEST_URL,
81
- data: data
82
- }
83
- }
84
-
85
- function toFormat(sizes) {
86
- return sizes.map((s) => {
87
- return { w: s[0], h: s[1] };
88
- });
89
- }
90
-
91
- function enrichImp(imp, bid, floor) {
92
- if (bid.params.customParams) {
93
- utils.deepSetValue(imp, 'ext.customParams', bid.params.customParams);
94
- }
95
- if (floor > 0) {
96
- imp.bidfloor = floor;
97
- imp.bidfloorcur = 'USD';
98
- } else if (bid.params.customFloor) {
99
- imp.bidfloor = bid.params.customFloor;
100
- }
101
- if (bid.ortb2Imp && bid.ortb2Imp.ext && bid.ortb2Imp.ext.data) {
102
- imp.ext.data = bid.ortb2Imp.ext.data;
171
+ data: converter.toORTB({bidRequests, bidderRequest, context: {mediaType}})
103
172
  }
104
173
  }
105
174
 
106
- function createVideoRequest(bid, bidderRequest) {
107
- let width;
108
- let height;
109
- const videoMediaType = utils.deepAccess(bid, `mediaTypes.video`);
110
- const playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize');
111
- const context = utils.deepAccess(bid, 'mediaTypes.video.context');
112
- const floor = getFloor(bid, VIDEO);
113
-
114
- // normalize config for video size
115
- if (utils.isArray(bid.sizes) && bid.sizes.length === 2 && !utils.isArray(bid.sizes[0])) {
116
- width = parseInt(bid.sizes[0], 10);
117
- height = parseInt(bid.sizes[1], 10);
118
- } else if (utils.isArray(bid.sizes) && utils.isArray(bid.sizes[0]) && bid.sizes[0].length === 2) {
119
- width = parseInt(bid.sizes[0][0], 10);
120
- height = parseInt(bid.sizes[0][1], 10);
121
- } else if (utils.isArray(playerSize) && playerSize.length === 2) {
122
- width = parseInt(playerSize[0], 10);
123
- height = parseInt(playerSize[1], 10);
124
- }
125
-
126
- let data = getBaseRequest(bid, bidderRequest);
127
- data.imp = [{
128
- id: bid.bidId,
129
- tagid: bid.params.unit,
130
- video: {
131
- w: width,
132
- h: height,
133
- topframe: utils.inIframe() ? 0 : 1
134
- },
135
- ext: {divid: bid.adUnitCode}
136
- }];
137
-
138
- enrichImp(data.imp[0], bid, floor);
139
-
140
- if (context) {
141
- if (context === 'instream') {
142
- data.imp[0].video.placement = 1;
143
- } else if (context === 'outstream') {
144
- data.imp[0].video.placement = 4;
145
- }
146
- }
147
-
148
- // backward compatability for video params
149
- let videoParams = bid.params.video || bid.params.openrtb || {};
150
- if (utils.isArray(videoParams.imp)) {
151
- videoParams = videoParams[0].video;
152
- }
153
-
154
- Object.keys(videoParams)
155
- .filter(param => includes(VIDEO_TARGETING, param))
156
- .forEach(param => data.imp[0].video[param] = videoParams[param]);
157
- Object.keys(videoMediaType)
158
- .filter(param => includes(VIDEO_TARGETING, param))
159
- .forEach(param => data.imp[0].video[param] = videoMediaType[param]);
160
-
161
- return {
162
- method: 'POST',
163
- url: REQUEST_URL,
164
- data: data
165
- };
166
- }
167
-
168
- function getBaseRequest(bid, bidderRequest) {
169
- let req = {
170
- id: bidderRequest.auctionId,
171
- cur: [config.getConfig('currency.adServerCurrency') || 'USD'],
172
- at: 1,
173
- tmax: config.getConfig('bidderTimeout'),
174
- site: {
175
- page: config.getConfig('pageUrl') || bidderRequest.refererInfo.referer
176
- },
177
- regs: {
178
- coppa: (config.getConfig('coppa') === true || bid.params.coppa) ? 1 : 0,
179
- },
180
- device: {
181
- dnt: (utils.getDNT() || bid.params.doNotTrack) ? 1 : 0,
182
- h: screen.height,
183
- w: screen.width,
184
- ua: window.navigator.userAgent,
185
- language: window.navigator.language.split('-').shift()
186
- },
187
- ext: {
188
- bc: `${bidderConfig}_${bidderVersion}`
189
- }
190
- };
191
-
192
- if (bid.params.platform) {
193
- utils.deepSetValue(req, 'ext.platform', bid.params.platform);
194
- }
195
- if (bid.params.delDomain) {
196
- utils.deepSetValue(req, 'ext.delDomain', bid.params.delDomain);
197
- }
198
- if (bid.params.response_template_name) {
199
- utils.deepSetValue(req, 'ext.response_template_name', bid.params.response_template_name);
200
- }
201
- if (bid.params.test) {
202
- req.test = 1;
203
- }
204
- if (bidderRequest.gdprConsent) {
205
- if (bidderRequest.gdprConsent.gdprApplies !== undefined) {
206
- utils.deepSetValue(req, 'regs.ext.gdpr', bidderRequest.gdprConsent.gdprApplies === true ? 1 : 0);
207
- }
208
- if (bidderRequest.gdprConsent.consentString !== undefined) {
209
- utils.deepSetValue(req, 'user.ext.consent', bidderRequest.gdprConsent.consentString);
210
- }
211
- if (bidderRequest.gdprConsent.addtlConsent !== undefined) {
212
- utils.deepSetValue(req, 'user.ext.ConsentedProvidersSettings.consented_providers', bidderRequest.gdprConsent.addtlConsent);
213
- }
214
- }
215
- if (bidderRequest.uspConsent) {
216
- utils.deepSetValue(req, 'regs.ext.us_privacy', bidderRequest.uspConsent);
217
- }
218
- if (bid.schain) {
219
- utils.deepSetValue(req, 'source.ext.schain', bid.schain);
220
- }
221
- if (bid.userIdAsEids) {
222
- utils.deepSetValue(req, 'user.ext.eids', bid.userIdAsEids);
223
- }
224
- const commonFpd = bidderRequest.ortb2 || {};
225
- if (commonFpd.site) {
226
- utils.mergeDeep(req, {site: commonFpd.site});
227
- }
228
- if (commonFpd.user) {
229
- utils.mergeDeep(req, {user: commonFpd.user});
230
- }
231
- return req;
232
- }
233
-
234
175
  function isVideoBid(bid) {
235
176
  return utils.deepAccess(bid, 'mediaTypes.video');
236
177
  }
@@ -239,107 +180,11 @@ function isBannerBid(bid) {
239
180
  return utils.deepAccess(bid, 'mediaTypes.banner') || !isVideoBid(bid);
240
181
  }
241
182
 
242
- function getFloor(bid, mediaType) {
243
- let floor = 0;
244
-
245
- if (typeof bid.getFloor === 'function') {
246
- const floorInfo = bid.getFloor({
247
- currency: 'USD',
248
- mediaType: mediaType,
249
- size: '*'
250
- });
251
-
252
- if (typeof floorInfo === 'object' &&
253
- floorInfo.currency === 'USD' &&
254
- !isNaN(parseFloat(floorInfo.floor))) {
255
- floor = Math.max(floor, parseFloat(floorInfo.floor));
256
- }
257
- }
258
-
259
- return floor;
260
- }
261
-
262
- function interpretOrtbResponse(resp, req) {
183
+ function interpretResponse(resp, req) {
263
184
  if (!resp.body) {
264
185
  resp.body = {nbr: 0};
265
186
  }
266
-
267
- // pass these from request to the responses for use in userSync
268
- if (req.data.ext) {
269
- if (req.data.ext.delDomain) {
270
- utils.deepSetValue(resp, 'body.ext.delDomain', req.data.ext.delDomain);
271
- }
272
- if (req.data.ext.platform) {
273
- utils.deepSetValue(resp, 'body.ext.platform', req.data.ext.platform);
274
- }
275
- }
276
-
277
- const respBody = resp.body;
278
- if (!respBody || 'nbr' in respBody || !Array.isArray(respBody.seatbid)) {
279
- return [];
280
- }
281
-
282
- let bids = [];
283
- respBody.seatbid.forEach(seatbid => {
284
- bids = [...bids, ...seatbid.bid.map(bid => {
285
- let response = {
286
- requestId: bid.impid,
287
- cpm: bid.price,
288
- width: bid.w,
289
- height: bid.h,
290
- creativeId: bid.crid,
291
- dealId: bid.dealid,
292
- currency: respBody.cur || 'USD',
293
- netRevenue: true,
294
- ttl: 300,
295
- mediaType: 'banner' in req.data.imp[0] ? BANNER : VIDEO,
296
- meta: { advertiserDomains: bid.adomain }
297
- };
298
-
299
- if (response.mediaType === VIDEO) {
300
- if (bid.nurl) {
301
- response.vastUrl = bid.nurl;
302
- } else {
303
- response.vastXml = bid.adm;
304
- }
305
- } else {
306
- response.ad = bid.adm;
307
- }
308
-
309
- if (bid.ext) {
310
- response.meta.networkId = bid.ext.dsp_id;
311
- response.meta.advertiserId = bid.ext.buyer_id;
312
- response.meta.brandId = bid.ext.brand_id;
313
- }
314
-
315
- if (respBody.ext && respBody.ext.paf) {
316
- response.meta.paf = Object.assign({}, respBody.ext.paf);
317
- response.meta.paf.content_id = utils.deepAccess(bid, 'ext.paf.content_id');
318
- }
319
-
320
- return response;
321
- })];
322
- });
323
-
324
- return bids;
325
- }
326
-
327
- function interpretResponse(resp, req) {
328
- const bids = interpretOrtbResponse(resp, req);
329
- let fledgeAuctionConfigs = utils.deepAccess(resp, 'body.ext.fledge_auction_configs');
330
- if (fledgeAuctionConfigs) {
331
- fledgeAuctionConfigs = Object.entries(fledgeAuctionConfigs).map(([bidId, cfg]) => {
332
- return Object.assign({
333
- bidId,
334
- auctionSignals: {}
335
- }, cfg);
336
- });
337
- return {
338
- bids,
339
- fledgeAuctionConfigs,
340
- }
341
- }
342
- return bids;
187
+ return converter.fromORTB({request: req.data, response: resp.body});
343
188
  }
344
189
 
345
190
  /**
@@ -0,0 +1,119 @@
1
+ import { submodule } from '../src/hook.js'
2
+ import { deepAccess, logInfo } from '../src/utils.js'
3
+
4
+ const oxxionRtdSearchFor = [ 'adUnitCode', 'auctionId', 'bidder', 'bidderCode', 'bidId', 'cpm', 'creativeId', 'currency', 'width', 'height', 'mediaType', 'netRevenue', 'originalCpm', 'originalCurrency', 'requestId', 'size', 'source', 'status', 'timeToRespond', 'transactionId', 'ttl', 'sizes', 'mediaTypes', 'src', 'userId', 'labelAny', 'adId' ];
5
+ const LOG_PREFIX = 'oxxionRtdProvider submodule: ';
6
+
7
+ const allAdUnits = [];
8
+
9
+ /** @type {RtdSubmodule} */
10
+ export const oxxionSubmodule = {
11
+ name: 'oxxionRtd',
12
+ init: init,
13
+ onAuctionEndEvent: onAuctionEnd,
14
+ getBidRequestData: getAdUnits,
15
+ };
16
+
17
+ function init(config, userConsent) {
18
+ if (!config.params || !config.params.domain || !config.params.contexts || !Array.isArray(config.params.contexts) || config.params.contexts.length == 0) {
19
+ return false
20
+ }
21
+ return true;
22
+ }
23
+
24
+ function getAdUnits(reqBidsConfigObj, callback, config, userConsent) {
25
+ const reqAdUnits = reqBidsConfigObj.adUnits;
26
+ if (Array.isArray(reqAdUnits)) {
27
+ reqAdUnits.forEach(adunit => {
28
+ if (config.params.contexts.includes(deepAccess(adunit, 'mediaTypes.video.context'))) {
29
+ allAdUnits.push(adunit);
30
+ }
31
+ });
32
+ }
33
+ }
34
+
35
+ function insertVideoTracking(bidResponse, config, maxCpm) {
36
+ if (bidResponse.mediaType === 'video') {
37
+ const trackingUrl = getImpUrl(config, bidResponse, maxCpm);
38
+ if (!trackingUrl) {
39
+ return;
40
+ }
41
+ // Vast Impression URL
42
+ if (bidResponse.vastUrl) {
43
+ bidResponse.vastImpUrl = bidResponse.vastImpUrl
44
+ ? trackingUrl + '&url=' + encodeURI(bidResponse.vastImpUrl)
45
+ : trackingUrl
46
+ }
47
+ // Vast XML document
48
+ if (bidResponse.vastXml !== undefined) {
49
+ const doc = new DOMParser().parseFromString(bidResponse.vastXml, 'text/xml');
50
+ const wrappers = doc.querySelectorAll('VAST Ad Wrapper, VAST Ad InLine');
51
+ let hasAltered = false;
52
+ if (wrappers.length) {
53
+ wrappers.forEach(wrapper => {
54
+ const impression = doc.createElement('Impression');
55
+ impression.appendChild(doc.createCDATASection(trackingUrl));
56
+ wrapper.appendChild(impression)
57
+ });
58
+ bidResponse.vastXml = new XMLSerializer().serializeToString(doc);
59
+ hasAltered = true;
60
+ }
61
+ if (hasAltered) {
62
+ logInfo(LOG_PREFIX + 'insert into vastXml for adId ' + bidResponse.adId);
63
+ }
64
+ }
65
+ }
66
+ }
67
+
68
+ function getImpUrl(config, data, maxCpm) {
69
+ const adUnitCode = data.adUnitCode;
70
+ const adUnits = allAdUnits.find(adunit => adunit.code === adUnitCode &&
71
+ 'mediaTypes' in adunit &&
72
+ 'video' in adunit.mediaTypes &&
73
+ typeof adunit.mediaTypes.video.context === 'string');
74
+ const context = adUnits !== undefined
75
+ ? adUnits.mediaTypes.video.context
76
+ : 'unknown';
77
+ if (!config.params.contexts.includes(context)) {
78
+ return false;
79
+ }
80
+ let trackingImpUrl = 'https://' + config.params.domain + '.oxxion.io/analytics/vast_imp?';
81
+ trackingImpUrl += oxxionRtdSearchFor.reduce((acc, param) => {
82
+ switch (typeof data[param]) {
83
+ case 'string':
84
+ case 'number':
85
+ acc += param + '=' + data[param] + '&'
86
+ break;
87
+ }
88
+ return acc;
89
+ }, '');
90
+ const cpmIncrement = Math.round(100000 * (data.cpm - maxCpm)) / 100000;
91
+ return trackingImpUrl + 'cpmIncrement=' + cpmIncrement + '&context=' + context;
92
+ }
93
+
94
+ function onAuctionEnd(auctionDetails, config, userConsent) {
95
+ const transactionsToCheck = {}
96
+ auctionDetails.adUnits.forEach(adunit => {
97
+ if (config.params.contexts.includes(deepAccess(adunit, 'mediaTypes.video.context'))) {
98
+ transactionsToCheck[adunit.transactionId] = {'bids': {}, 'maxCpm': 0.0, 'secondMaxCpm': 0.0};
99
+ }
100
+ });
101
+ for (const key in auctionDetails.bidsReceived) {
102
+ if (auctionDetails.bidsReceived[key].transactionId in transactionsToCheck) {
103
+ transactionsToCheck[auctionDetails.bidsReceived[key].transactionId]['bids'][auctionDetails.bidsReceived[key].adId] = {'key': key, 'cpm': auctionDetails.bidsReceived[key].cpm};
104
+ if (auctionDetails.bidsReceived[key].cpm > transactionsToCheck[auctionDetails.bidsReceived[key].transactionId]['maxCpm']) {
105
+ transactionsToCheck[auctionDetails.bidsReceived[key].transactionId]['secondMaxCpm'] = transactionsToCheck[auctionDetails.bidsReceived[key].transactionId]['maxCpm'];
106
+ transactionsToCheck[auctionDetails.bidsReceived[key].transactionId]['maxCpm'] = auctionDetails.bidsReceived[key].cpm;
107
+ } else if (auctionDetails.bidsReceived[key].cpm > transactionsToCheck[auctionDetails.bidsReceived[key].transactionId]['secondMaxCpm']) {
108
+ transactionsToCheck[auctionDetails.bidsReceived[key].transactionId]['secondMaxCpm'] = auctionDetails.bidsReceived[key].cpm;
109
+ }
110
+ }
111
+ };
112
+ Object.keys(transactionsToCheck).forEach(transaction => {
113
+ Object.keys(transactionsToCheck[transaction]['bids']).forEach(bid => {
114
+ insertVideoTracking(auctionDetails.bidsReceived[transactionsToCheck[transaction]['bids'][bid].key], config, transactionsToCheck[transaction].secondMaxCpm);
115
+ });
116
+ });
117
+ }
118
+
119
+ submodule('realTimeData', oxxionSubmodule);
@@ -0,0 +1,48 @@
1
+ # Overview
2
+
3
+ Module Name: Oxxion Rtd Provider
4
+ Module Type: Rtd Provider
5
+ Maintainer: tech@oxxion.io
6
+
7
+ # Oxxion Real-Time-Data submodule
8
+
9
+ Oxxion helps you to understand how your prebid stack performs.
10
+ This Rtd module is to use in order to improve video events tracking.
11
+
12
+ # Integration
13
+
14
+ Make sure to have the following modules listed while building prebid : `rtdModule,oxxionRtdProvider`
15
+ `rtbModule` is required to activate real-time-data submodules.
16
+ For example :
17
+ ```
18
+ gulp build --modules=schain,priceFloors,currency,consentManagement,appnexusBidAdapter,rubiconBidAdapter,rtdModule,oxxionRtdProvider
19
+ ```
20
+
21
+ Then add the oxxion Rtd module to your prebid configuration :
22
+ ```
23
+ pbjs.setConfig(
24
+ ...
25
+ realTimeData: {
26
+ auctionDelay: 200,
27
+ dataProviders: [
28
+ {
29
+ name: "oxxionRtd",
30
+ waitForIt: true,
31
+ params: {
32
+ domain: "test.endpoint",
33
+ contexts: ["instream"],
34
+ }
35
+ }
36
+ ]
37
+ }
38
+ ...
39
+ )
40
+ ```
41
+
42
+ # setConfig Parameters
43
+
44
+ | Name | Type | Description |
45
+ |:---------------------------------|:---------|:------------------------------------------------------------------------------------------------------------|
46
+ | domain | String | This string identifies yourself in Oxxion's systems and is provided to you by your Oxxion representative. |
47
+ | contexts | Array | Array defining which video contexts to add tracking events into. Values can be instream and/or outstream. |
48
+