prebid.js 7.18.0 → 7.20.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 (313) hide show
  1. package/dist/33acrossBidAdapter.js +1 -1
  2. package/dist/33acrossIdSystem.js +1 -1
  3. package/dist/adWMGAnalyticsAdapter.js +1 -1
  4. package/dist/adagioAnalyticsAdapter.js +1 -1
  5. package/dist/adagioBidAdapter.js +1 -1
  6. package/dist/adbookpspBidAdapter.js +1 -1
  7. package/dist/adfBidAdapter.js +1 -1
  8. package/dist/adgenerationBidAdapter.js +1 -1
  9. package/dist/adkernelAdnAnalyticsAdapter.js +1 -1
  10. package/dist/adkernelBidAdapter.js +1 -1
  11. package/dist/adlooxAdServerVideo.js +1 -1
  12. package/dist/adlooxAnalyticsAdapter.js +1 -1
  13. package/dist/adlooxRtdProvider.js +1 -1
  14. package/dist/adomikAnalyticsAdapter.js +1 -1
  15. package/dist/adqueryIdSystem.js +1 -1
  16. package/dist/adrelevantisBidAdapter.js +1 -1
  17. package/dist/adtrgtmeBidAdapter.js +1 -1
  18. package/dist/adxcgAnalyticsAdapter.js +1 -1
  19. package/dist/adxcgBidAdapter.js +1 -1
  20. package/dist/adxpremiumAnalyticsAdapter.js +1 -1
  21. package/dist/ajaBidAdapter.js +1 -1
  22. package/dist/amxBidAdapter.js +1 -1
  23. package/dist/amxIdSystem.js +1 -1
  24. package/dist/aolBidAdapter.js +1 -1
  25. package/dist/appierAnalyticsAdapter.js +1 -1
  26. package/dist/appnexusBidAdapter.js +1 -1
  27. package/dist/asoBidAdapter.js +1 -1
  28. package/dist/atsAnalyticsAdapter.js +1 -1
  29. package/dist/axonixBidAdapter.js +1 -1
  30. package/dist/{andBeyondMediaBidAdapter.js → beyondmediaBidAdapter.js} +1 -1
  31. package/dist/bidViewability.js +1 -1
  32. package/dist/bidglassBidAdapter.js +1 -1
  33. package/dist/bidwatchAnalyticsAdapter.js +1 -1
  34. package/dist/big-richmediaBidAdapter.js +1 -1
  35. package/dist/bridgewellBidAdapter.js +1 -1
  36. package/dist/brightMountainMediaBidAdapter.js +1 -1
  37. package/dist/byDataAnalyticsAdapter.js +1 -1
  38. package/dist/carodaBidAdapter.js +1 -1
  39. package/dist/categoryTranslation.js +1 -1
  40. package/dist/cleanioRtdProvider.js +1 -1
  41. package/dist/colossussspBidAdapter.js +1 -1
  42. package/dist/concertAnalyticsAdapter.js +1 -1
  43. package/dist/concertBidAdapter.js +1 -1
  44. package/dist/connectIdSystem.js +1 -1
  45. package/dist/connectadBidAdapter.js +1 -1
  46. package/dist/consentManagement.js +1 -1
  47. package/dist/consentManagementUsp.js +1 -1
  48. package/dist/consumableBidAdapter.js +1 -1
  49. package/dist/conversantAnalyticsAdapter.js +1 -0
  50. package/dist/conversantBidAdapter.js +1 -1
  51. package/dist/craftBidAdapter.js +1 -1
  52. package/dist/criteoBidAdapter.js +1 -1
  53. package/dist/currency.js +1 -1
  54. package/dist/datablocksAnalyticsAdapter.js +1 -1
  55. package/dist/dchain.js +1 -1
  56. package/dist/debugging-standalone.js +1 -1
  57. package/dist/debugging.js +1 -1
  58. package/dist/dependencies.json +9 -0
  59. package/dist/dfpAdServerVideo.js +1 -1
  60. package/dist/dgkeywordRtdProvider.js +1 -1
  61. package/dist/dianomiBidAdapter.js +1 -1
  62. package/dist/dspxBidAdapter.js +1 -1
  63. package/dist/enrichmentFpdModule.js +1 -1
  64. package/dist/eplanningAnalyticsAdapter.js +1 -1
  65. package/dist/eplanningBidAdapter.js +1 -1
  66. package/dist/finativeBidAdapter.js +1 -1
  67. package/dist/fintezaAnalyticsAdapter.js +1 -1
  68. package/dist/fpd.js +1 -0
  69. package/dist/ftrackIdSystem.js +1 -1
  70. package/dist/gdprEnforcement.js +1 -1
  71. package/dist/glimpseBidAdapter.js +1 -1
  72. package/dist/gmosspBidAdapter.js +1 -1
  73. package/dist/goldbachBidAdapter.js +1 -1
  74. package/dist/googleAnalyticsAdapter.js +1 -1
  75. package/dist/gridBidAdapter.js +1 -1
  76. package/dist/gridNMBidAdapter.js +1 -1
  77. package/dist/gumgumBidAdapter.js +1 -1
  78. package/dist/h12mediaBidAdapter.js +1 -1
  79. package/dist/hadronAnalyticsAdapter.js +1 -1
  80. package/dist/id5AnalyticsAdapter.js +1 -1
  81. package/dist/id5IdSystem.js +1 -1
  82. package/dist/improvedigitalBidAdapter.js +1 -1
  83. package/dist/inmarBidAdapter.js +1 -1
  84. package/dist/insticatorBidAdapter.js +1 -1
  85. package/dist/invisiblyAnalyticsAdapter.js +1 -1
  86. package/dist/ixBidAdapter.js +1 -1
  87. package/dist/justpremiumBidAdapter.js +1 -1
  88. package/dist/kargoAnalyticsAdapter.js +1 -1
  89. package/dist/kinessoIdSystem.js +1 -1
  90. package/dist/konduitAnalyticsAdapter.js +1 -1
  91. package/dist/kueezBidAdapter.js +1 -1
  92. package/dist/lassoBidAdapter.js +1 -1
  93. package/dist/lifestreetBidAdapter.js +1 -1
  94. package/dist/liveIntentAnalyticsAdapter.js +1 -1
  95. package/dist/liveIntentIdSystem.js +1 -1
  96. package/dist/livewrappedAnalyticsAdapter.js +1 -1
  97. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  98. package/dist/logicadBidAdapter.js +1 -1
  99. package/dist/loglyliftBidAdapter.js +1 -1
  100. package/dist/lotamePanoramaIdSystem.js +1 -1
  101. package/dist/magniteAnalyticsAdapter.js +1 -0
  102. package/dist/malltvAnalyticsAdapter.js +1 -1
  103. package/dist/marsmediaAnalyticsAdapter.js +1 -1
  104. package/dist/marsmediaBidAdapter.js +1 -1
  105. package/dist/mass.js +1 -1
  106. package/dist/mediafuseBidAdapter.js +1 -1
  107. package/dist/mediakeysBidAdapter.js +1 -1
  108. package/dist/medianetAnalyticsAdapter.js +1 -1
  109. package/dist/mediasquareBidAdapter.js +1 -1
  110. package/dist/mgidBidAdapter.js +1 -1
  111. package/dist/minutemediaBidAdapter.js +1 -1
  112. package/dist/multibid.js +1 -1
  113. package/dist/nativoBidAdapter.js +1 -1
  114. package/dist/not-for-prod/prebid.js +198 -194
  115. package/dist/oguryBidAdapter.js +1 -1
  116. package/dist/onetagBidAdapter.js +1 -1
  117. package/dist/ooloAnalyticsAdapter.js +1 -1
  118. package/dist/openxAnalyticsAdapter.js +1 -1
  119. package/dist/optimonAnalyticsAdapter.js +1 -1
  120. package/dist/outbrainBidAdapter.js +1 -1
  121. package/dist/parrableIdSystem.js +1 -1
  122. package/dist/pianoDmpAnalyticsAdapter.js +1 -1
  123. package/dist/pixfutureBidAdapter.js +1 -1
  124. package/dist/prebid-core.js +2 -2
  125. package/dist/prebidServerBidAdapter.js +1 -1
  126. package/dist/prebidmanagerAnalyticsAdapter.js +1 -1
  127. package/dist/priceFloors.js +1 -1
  128. package/dist/publinkIdSystem.js +1 -1
  129. package/dist/pubmaticAnalyticsAdapter.js +1 -1
  130. package/dist/pubmaticBidAdapter.js +1 -1
  131. package/dist/pubperfAnalyticsAdapter.js +1 -1
  132. package/dist/pubstackAnalyticsAdapter.js +1 -1
  133. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  134. package/dist/pubxaiAnalyticsAdapter.js +1 -1
  135. package/dist/pulsepointAnalyticsAdapter.js +1 -1
  136. package/dist/pxyzBidAdapter.js +1 -1
  137. package/dist/quantcastBidAdapter.js +1 -1
  138. package/dist/quantcastIdSystem.js +1 -1
  139. package/dist/readpeakBidAdapter.js +1 -1
  140. package/dist/realvuAnalyticsAdapter.js +1 -1
  141. package/dist/relaidoBidAdapter.js +1 -1
  142. package/dist/relevantAnalyticsAdapter.js +1 -1
  143. package/dist/rhythmoneBidAdapter.js +1 -1
  144. package/dist/riseBidAdapter.js +1 -1
  145. package/dist/rivrAnalyticsAdapter.js +1 -1
  146. package/dist/roxotAnalyticsAdapter.js +1 -1
  147. package/dist/rtdModule.js +1 -1
  148. package/dist/rubiconAnalyticsAdapter.js +1 -1
  149. package/dist/rubiconBidAdapter.js +1 -1
  150. package/dist/s2sTesting.js +1 -1
  151. package/dist/scaleableAnalyticsAdapter.js +1 -1
  152. package/dist/schain.js +1 -1
  153. package/dist/seedingAllianceBidAdapter.js +1 -1
  154. package/dist/seedtagBidAdapter.js +1 -1
  155. package/dist/sharedIdSystem.js +1 -1
  156. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  157. package/dist/sharethroughBidAdapter.js +1 -1
  158. package/dist/shinezBidAdapter.js +1 -1
  159. package/dist/sigmoidAnalyticsAdapter.js +1 -1
  160. package/dist/smaatoBidAdapter.js +1 -1
  161. package/dist/smartadserverBidAdapter.js +1 -1
  162. package/dist/smartxBidAdapter.js +1 -1
  163. package/dist/smilewantedBidAdapter.js +1 -1
  164. package/dist/sonobiAnalyticsAdapter.js +1 -1
  165. package/dist/sonobiBidAdapter.js +1 -1
  166. package/dist/sovrnAnalyticsAdapter.js +1 -1
  167. package/dist/sovrnBidAdapter.js +1 -1
  168. package/dist/sspBCBidAdapter.js +1 -1
  169. package/dist/staqAnalyticsAdapter.js +1 -1
  170. package/dist/sublimeBidAdapter.js +1 -1
  171. package/dist/synacormediaBidAdapter.js +1 -1
  172. package/dist/taboolaBidAdapter.js +1 -1
  173. package/dist/tapadIdSystem.js +1 -1
  174. package/dist/targetVideoBidAdapter.js +1 -1
  175. package/dist/teadsBidAdapter.js +1 -1
  176. package/dist/teadsIdSystem.js +1 -0
  177. package/dist/terceptAnalyticsAdapter.js +1 -1
  178. package/dist/trionBidAdapter.js +1 -1
  179. package/dist/tripleliftBidAdapter.js +1 -1
  180. package/dist/ttdBidAdapter.js +1 -1
  181. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  182. package/dist/underdogmediaBidAdapter.js +1 -1
  183. package/dist/undertoneBidAdapter.js +1 -1
  184. package/dist/userId.js +1 -1
  185. package/dist/vidazooBidAdapter.js +1 -1
  186. package/dist/videobyteBidAdapter.js +1 -1
  187. package/dist/visxBidAdapter.js +1 -1
  188. package/dist/vrtcalBidAdapter.js +1 -1
  189. package/dist/vuukleBidAdapter.js +1 -1
  190. package/dist/weboramaRtdProvider.js +1 -1
  191. package/dist/widespaceBidAdapter.js +1 -1
  192. package/dist/winrBidAdapter.js +1 -1
  193. package/dist/yahoosspBidAdapter.js +1 -1
  194. package/dist/yandexBidAdapter.js +1 -1
  195. package/dist/yieldmoBidAdapter.js +1 -1
  196. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  197. package/dist/yuktamediaAnalyticsAdapter.js +1 -1
  198. package/dist/zeta_global_sspAnalyticsAdapter.js +1 -1
  199. package/libraries/fpd/sua.js +98 -0
  200. package/modules/.submodules.json +1 -0
  201. package/modules/adfBidAdapter.js +1 -1
  202. package/modules/adkernelAdnBidAdapter.js +1 -0
  203. package/modules/adkernelBidAdapter.js +2 -2
  204. package/modules/adqueryIdSystem.js +8 -8
  205. package/modules/adxcgBidAdapter.js +1 -1
  206. package/modules/amxBidAdapter.js +1 -1
  207. package/modules/aolBidAdapter.js +25 -2
  208. package/modules/appnexusBidAdapter.js +19 -2
  209. package/modules/{andBeyondMediaBidAdapter.js → beyondmediaBidAdapter.js} +0 -0
  210. package/modules/{andBeyondMediaBidAdapter.md → beyondmediaBidAdapter.md} +1 -1
  211. package/modules/categoryTranslation.js +4 -4
  212. package/modules/cleanioRtdProvider.js +3 -4
  213. package/modules/colossussspBidAdapter.js +2 -1
  214. package/modules/connectIdSystem.js +16 -1
  215. package/modules/conversantAnalyticsAdapter.js +560 -0
  216. package/modules/conversantAnalyticsAdapter.md +47 -0
  217. package/modules/criteoBidAdapter.js +1 -1
  218. package/modules/currency.js +11 -11
  219. package/modules/dchain.js +2 -2
  220. package/modules/debugging/bidInterceptor.js +2 -2
  221. package/modules/debugging/debugging.js +10 -2
  222. package/modules/debugging/legacy.js +2 -2
  223. package/modules/dgkeywordRtdProvider.js +21 -3
  224. package/modules/dianomiBidAdapter.js +1 -1
  225. package/modules/enrichmentFpdModule.js +33 -14
  226. package/modules/eplanningBidAdapter.js +48 -2
  227. package/modules/finativeBidAdapter.js +1 -1
  228. package/modules/gridBidAdapter.js +187 -117
  229. package/modules/improvedigitalBidAdapter.js +2 -2
  230. package/modules/ixBidAdapter.js +94 -23
  231. package/modules/liveIntentIdSystem.js +39 -5
  232. package/modules/lotamePanoramaIdSystem.js +10 -6
  233. package/modules/magniteAnalyticsAdapter.js +902 -0
  234. package/modules/magniteAnalyticsAdapter.md +18 -0
  235. package/modules/mass.js +2 -2
  236. package/modules/mediakeysBidAdapter.js +6 -1
  237. package/modules/mediakeysBidAdapter.md +50 -40
  238. package/modules/multibid/index.js +5 -5
  239. package/modules/nativoBidAdapter.js +1 -1
  240. package/modules/pixfutureBidAdapter.js +46 -15
  241. package/modules/prebidServerBidAdapter/index.js +54 -19
  242. package/modules/priceFloors.js +8 -22
  243. package/modules/readpeakBidAdapter.js +1 -1
  244. package/modules/rubiconAnalyticsAdapter.js +14 -9
  245. package/modules/rubiconBidAdapter.js +2 -3
  246. package/modules/seedingAllianceBidAdapter.js +1 -1
  247. package/modules/sharethroughBidAdapter.js +1 -1
  248. package/modules/taboolaBidAdapter.js +5 -5
  249. package/modules/talkadsBidAdapter.js +1 -0
  250. package/modules/teadsIdSystem.js +234 -0
  251. package/modules/teadsIdSystem.md +22 -0
  252. package/modules/truereachBidAdapter.js +1 -0
  253. package/modules/ttdBidAdapter.js +1 -1
  254. package/modules/userId/index.js +21 -14
  255. package/modules/vrtcalBidAdapter.js +7 -1
  256. package/modules/vuukleBidAdapter.js +34 -3
  257. package/modules/yahoosspBidAdapter.js +4 -2
  258. package/modules/yandexBidAdapter.js +31 -8
  259. package/package.json +2 -2
  260. package/src/adapterManager.js +2 -4
  261. package/src/adapters/bidderFactory.js +13 -11
  262. package/src/auction.js +140 -69
  263. package/src/constants.json +8 -0
  264. package/src/cpmBucketManager.js +22 -3
  265. package/src/native.js +1 -5
  266. package/src/prebid.js +5 -6
  267. package/src/targeting.js +31 -14
  268. package/test/fixtures/fixtures.js +2 -1
  269. package/test/spec/auctionmanager_spec.js +109 -21
  270. package/test/spec/cpmBucketManager_spec.js +239 -177
  271. package/test/spec/fpd/sua_spec.js +244 -0
  272. package/test/spec/modules/adfBidAdapter_spec.js +2 -3
  273. package/test/spec/modules/adqueryIdSystem_spec.js +0 -2
  274. package/test/spec/modules/adxcgBidAdapter_spec.js +2 -3
  275. package/test/spec/modules/amxBidAdapter_spec.js +3 -2
  276. package/test/spec/modules/aolBidAdapter_spec.js +42 -9
  277. package/test/spec/modules/appnexusBidAdapter_spec.js +24 -0
  278. package/test/spec/modules/{andBeyondMediaBidAdapter_spec.js → beyondmediaBidAdapter_spec.js} +1 -1
  279. package/test/spec/modules/colossussspBidAdapter_spec.js +4 -2
  280. package/test/spec/modules/connectIdSystem_spec.js +20 -0
  281. package/test/spec/modules/conversantAnalyticsAdapter_spec.js +963 -0
  282. package/test/spec/modules/currency_spec.js +14 -6
  283. package/test/spec/modules/debugging_mod_spec.js +9 -0
  284. package/test/spec/modules/dgkeywordRtdProvider_spec.js +83 -1
  285. package/test/spec/modules/dianomiBidAdapter_spec.js +2 -3
  286. package/test/spec/modules/enrichmentFpdModule_spec.js +50 -7
  287. package/test/spec/modules/eplanningBidAdapter_spec.js +285 -1
  288. package/test/spec/modules/fpdModule_spec.js +9 -0
  289. package/test/spec/modules/gridBidAdapter_spec.js +87 -31
  290. package/test/spec/modules/ixBidAdapter_spec.js +221 -2
  291. package/test/spec/modules/liveIntentIdMinimalSystem_spec.js +62 -8
  292. package/test/spec/modules/liveIntentIdSystem_spec.js +62 -8
  293. package/test/spec/modules/lotamePanoramaIdSystem_spec.js +0 -1
  294. package/test/spec/modules/magniteAnalyticsAdapter_spec.js +1942 -0
  295. package/test/spec/modules/mediakeysBidAdapter_spec.js +20 -3
  296. package/test/spec/modules/nativoBidAdapter_spec.js +13 -2
  297. package/test/spec/modules/prebidServerBidAdapter_spec.js +202 -15
  298. package/test/spec/modules/priceFloors_spec.js +5 -5
  299. package/test/spec/modules/rubiconAnalyticsAdapter_spec.js +2 -3
  300. package/test/spec/modules/seedtagBidAdapter_spec.js +15 -18
  301. package/test/spec/modules/sharethroughBidAdapter_spec.js +2 -1
  302. package/test/spec/modules/taboolaBidAdapter_spec.js +112 -13
  303. package/test/spec/modules/teadsIdSystem_spec.js +271 -0
  304. package/test/spec/modules/ttdBidAdapter_spec.js +3 -3
  305. package/test/spec/modules/userId_spec.js +39 -4
  306. package/test/spec/modules/vrtcalBidAdapter_spec.js +12 -1
  307. package/test/spec/modules/vuukleBidAdapter_spec.js +87 -0
  308. package/test/spec/modules/yahoosspBidAdapter_spec.js +48 -1
  309. package/test/spec/modules/yandexBidAdapter_spec.js +8 -5
  310. package/test/spec/native_spec.js +5 -0
  311. package/test/spec/unit/core/bidderFactory_spec.js +66 -11
  312. package/test/spec/unit/core/targeting_spec.js +28 -9
  313. package/test/spec/unit/pbjs_api_spec.js +48 -2
@@ -0,0 +1,902 @@
1
+ import { generateUUID, mergeDeep, deepAccess, parseUrl, logError, pick, isEmpty, logWarn, debugTurnedOn, parseQS, getWindowLocation, isAdUnitCodeMatchingSlot, isNumber, deepSetValue, deepClone, logInfo, isGptPubadsDefined } from '../src/utils.js';
2
+ import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js';
3
+ import adapterManager from '../src/adapterManager.js';
4
+ import CONSTANTS from '../src/constants.json';
5
+ import { ajax } from '../src/ajax.js';
6
+ import { config } from '../src/config.js';
7
+ import { getGlobal } from '../src/prebidGlobal.js';
8
+ import { getStorageManager } from '../src/storageManager.js';
9
+
10
+ const RUBICON_GVL_ID = 52;
11
+ export const storage = getStorageManager({ gvlid: RUBICON_GVL_ID, moduleName: 'magnite' });
12
+ const COOKIE_NAME = 'mgniSession';
13
+ const LAST_SEEN_EXPIRE_TIME = 1800000; // 30 mins
14
+ const END_EXPIRE_TIME = 21600000; // 6 hours
15
+ const MODULE_NAME = 'Magnite Analytics';
16
+ const BID_REJECTED_IPF = 'rejected-ipf';
17
+
18
+ // List of known rubicon aliases
19
+ // This gets updated on auction init to account for any custom aliases present
20
+ let rubiconAliases = ['rubicon'];
21
+
22
+ const pbsErrorMap = {
23
+ 1: 'timeout-error',
24
+ 2: 'input-error',
25
+ 3: 'connect-error',
26
+ 4: 'request-error',
27
+ 999: 'generic-error'
28
+ }
29
+
30
+ let prebidGlobal = getGlobal();
31
+ const {
32
+ EVENTS: {
33
+ AUCTION_INIT,
34
+ AUCTION_END,
35
+ BID_REQUESTED,
36
+ BID_RESPONSE,
37
+ BIDDER_DONE,
38
+ BID_TIMEOUT,
39
+ BID_WON,
40
+ BILLABLE_EVENT
41
+ },
42
+ STATUS: {
43
+ GOOD,
44
+ NO_BID
45
+ },
46
+ BID_STATUS: {
47
+ BID_REJECTED
48
+ }
49
+ } = CONSTANTS;
50
+
51
+ // The saved state of rubicon specific setConfig controls
52
+ export let rubiConf;
53
+ // Saving state of all our data we want
54
+ let cache;
55
+ const resetConfs = () => {
56
+ cache = {
57
+ auctions: {},
58
+ auctionOrder: [],
59
+ timeouts: {},
60
+ billing: {},
61
+ pendingEvents: {},
62
+ eventPending: false,
63
+ elementIdMap: {},
64
+ sessionData: {}
65
+ }
66
+ rubiConf = {
67
+ pvid: generateUUID().slice(0, 8),
68
+ analyticsEventDelay: 500,
69
+ analyticsBatchTimeout: 5000,
70
+ analyticsProcessDelay: 1,
71
+ dmBilling: {
72
+ enabled: false,
73
+ vendors: [],
74
+ waitForAuction: true
75
+ }
76
+ }
77
+ }
78
+ resetConfs();
79
+
80
+ config.getConfig('rubicon', config => {
81
+ mergeDeep(rubiConf, config.rubicon);
82
+ if (deepAccess(config, 'rubicon.updatePageView') === true) {
83
+ rubiConf.pvid = generateUUID().slice(0, 8)
84
+ }
85
+ });
86
+
87
+ // pbs confs
88
+ let serverConfig;
89
+ config.getConfig('s2sConfig', ({ s2sConfig }) => {
90
+ serverConfig = s2sConfig;
91
+ });
92
+
93
+ const DEFAULT_INTEGRATION = 'pbjs';
94
+
95
+ const adUnitIsOnlyInstream = adUnit => {
96
+ return adUnit.mediaTypes && Object.keys(adUnit.mediaTypes).length === 1 && deepAccess(adUnit, 'mediaTypes.video.context') === 'instream';
97
+ }
98
+
99
+ const sendPendingEvents = () => {
100
+ cache.pendingEvents.trigger = `batched-${Object.keys(cache.pendingEvents).sort().join('-')}`;
101
+ sendEvent(cache.pendingEvents);
102
+ cache.pendingEvents = {};
103
+ cache.eventPending = false;
104
+ }
105
+
106
+ const addEventToQueue = (event, auctionId, eventName) => {
107
+ // If it's auction has not left yet, add it there
108
+ if (cache.auctions[auctionId] && !cache.auctions[auctionId].sent) {
109
+ cache.auctions[auctionId].pendingEvents = mergeDeep(cache.auctions[auctionId].pendingEvents, event);
110
+ } else if (rubiConf.analyticsEventDelay > 0) {
111
+ // else if we are trying to batch stuff up, add it to pending events to be fired
112
+ cache.pendingEvents = mergeDeep(cache.pendingEvents, event);
113
+
114
+ // If no event is pending yet, start a timer for them to be sent and attempted to be gathered together
115
+ if (!cache.eventPending) {
116
+ setTimeout(sendPendingEvents, rubiConf.analyticsEventDelay);
117
+ cache.eventPending = true;
118
+ }
119
+ } else {
120
+ // else - send it solo
121
+ event.trigger = `solo-${eventName}`;
122
+ sendEvent(event);
123
+ }
124
+ }
125
+
126
+ const sendEvent = payload => {
127
+ const event = {
128
+ ...getTopLevelDetails(),
129
+ ...payload
130
+ }
131
+ ajax(
132
+ endpoint,
133
+ null,
134
+ JSON.stringify(event),
135
+ {
136
+ contentType: 'application/json'
137
+ }
138
+ );
139
+ }
140
+
141
+ const sendAuctionEvent = (auctionId, trigger) => {
142
+ let auctionCache = cache.auctions[auctionId];
143
+ const auctionEvent = formatAuction(auctionCache.auction);
144
+
145
+ auctionCache.sent = true;
146
+ sendEvent({
147
+ auctions: [auctionEvent],
148
+ ...(auctionCache.pendingEvents || {}), // if any pending events were attached
149
+ trigger
150
+ });
151
+ }
152
+
153
+ const formatAuction = auction => {
154
+ const auctionEvent = deepClone(auction);
155
+
156
+ auctionEvent.samplingFactor = 1;
157
+
158
+ // We stored adUnits and bids as objects for quick lookups, now they are mapped into arrays for PBA
159
+ auctionEvent.adUnits = Object.entries(auctionEvent.adUnits).map(([tid, adUnit]) => {
160
+ adUnit.bids = Object.entries(adUnit.bids).map(([bidId, bid]) => {
161
+ // determine adUnit.status from its bid statuses. Use priority below to determine, higher index is better
162
+ let statusPriority = ['error', 'no-bid', 'success'];
163
+ if (statusPriority.indexOf(bid.status) > statusPriority.indexOf(adUnit.status)) {
164
+ adUnit.status = bid.status;
165
+ }
166
+
167
+ // If PBS told us to overwrite the bid ID, do so
168
+ if (bid.pbsBidId) {
169
+ bid.oldBidId = bid.bidId;
170
+ bid.bidId = bid.pbsBidId;
171
+ delete bid.pbsBidId;
172
+ }
173
+ return bid;
174
+ });
175
+ return adUnit;
176
+ });
177
+ return auctionEvent;
178
+ }
179
+
180
+ const isBillingEventValid = event => {
181
+ // vendor is whitelisted
182
+ const isWhitelistedVendor = rubiConf.dmBilling.vendors.includes(event.vendor);
183
+ // event is not duplicated
184
+ const isNotDuplicate = typeof deepAccess(cache.billing, `${event.vendor}.${event.billingId}`) !== 'boolean';
185
+ // billingId is defined and a string
186
+ return typeof event.billingId === 'string' && isWhitelistedVendor && isNotDuplicate;
187
+ }
188
+
189
+ const formatBillingEvent = event => {
190
+ let billingEvent = deepClone(event);
191
+ // Pass along type if is string and not empty else general
192
+ billingEvent.type = (typeof event.type === 'string' && event.type) || 'general';
193
+ billingEvent.accountId = accountId;
194
+ // mark as sent
195
+ deepSetValue(cache.billing, `${event.vendor}.${event.billingId}`, true);
196
+ return billingEvent;
197
+ }
198
+
199
+ const getBidPrice = bid => {
200
+ // get the cpm from bidResponse
201
+ let cpm;
202
+ let currency;
203
+ if (bid.status === BID_REJECTED && typeof deepAccess(bid, 'floorData.cpmAfterAdjustments') === 'number') {
204
+ // if bid was rejected and bid.floorData.cpmAfterAdjustments use it
205
+ cpm = bid.floorData.cpmAfterAdjustments;
206
+ currency = bid.floorData.floorCurrency;
207
+ } else if (typeof bid.currency === 'string' && bid.currency.toUpperCase() === 'USD') {
208
+ // bid is in USD use it
209
+ return Number(bid.cpm);
210
+ } else {
211
+ // else grab cpm
212
+ cpm = bid.cpm;
213
+ currency = bid.currency;
214
+ }
215
+ // if after this it is still going and is USD then return it.
216
+ if (currency === 'USD') {
217
+ return Number(cpm);
218
+ }
219
+ // otherwise we convert and return
220
+ try {
221
+ return Number(prebidGlobal.convertCurrency(cpm, currency, 'USD'));
222
+ } catch (err) {
223
+ logWarn(`${MODULE_NAME}: Could not determine the bidPriceUSD of the bid `, bid);
224
+ bid.conversionError = true;
225
+ bid.ogCurrency = currency;
226
+ bid.ogPrice = cpm;
227
+ return 0;
228
+ }
229
+ }
230
+
231
+ export const parseBidResponse = (bid, previousBidResponse) => {
232
+ // The current bidResponse for this matching requestId/bidRequestId
233
+ let responsePrice = getBidPrice(bid)
234
+ // we need to compare it with the previous one (if there was one) log highest only
235
+ // THIS WILL CHANGE WITH ALLOWING MULTIBID BETTER
236
+ if (previousBidResponse && previousBidResponse.bidPriceUSD > responsePrice) {
237
+ return previousBidResponse;
238
+ }
239
+
240
+ return pick(bid, [
241
+ 'bidPriceUSD', () => responsePrice,
242
+ 'dealId', dealId => dealId || undefined,
243
+ 'mediaType',
244
+ 'dimensions', () => {
245
+ const width = bid.width || bid.playerWidth;
246
+ const height = bid.height || bid.playerHeight;
247
+ return (width && height) ? { width, height } : undefined;
248
+ },
249
+ 'floorValue', () => deepAccess(bid, 'floorData.floorValue'),
250
+ 'floorRuleValue', () => deepAccess(bid, 'floorData.floorRuleValue'),
251
+ 'floorRule', () => debugTurnedOn() ? deepAccess(bid, 'floorData.floorRule') : undefined,
252
+ 'adomains', () => {
253
+ const adomains = deepAccess(bid, 'meta.advertiserDomains');
254
+ const validAdomains = Array.isArray(adomains) && adomains.filter(domain => typeof domain === 'string');
255
+ return validAdomains && validAdomains.length > 0 ? validAdomains.slice(0, 10) : undefined
256
+ },
257
+ 'conversionError', conversionError => conversionError === true || undefined, // only pass if exactly true
258
+ 'ogCurrency',
259
+ 'ogPrice'
260
+ ]);
261
+ }
262
+
263
+ const addFloorData = floorData => {
264
+ if (floorData.location === 'noData') {
265
+ return pick(floorData, [
266
+ 'location',
267
+ 'fetchStatus',
268
+ 'floorProvider as provider'
269
+ ]);
270
+ } else {
271
+ return pick(floorData, [
272
+ 'location',
273
+ 'modelVersion as modelName',
274
+ 'modelWeight',
275
+ 'modelTimestamp',
276
+ 'skipped',
277
+ 'enforcement', () => deepAccess(floorData, 'enforcements.enforceJS'),
278
+ 'dealsEnforced', () => deepAccess(floorData, 'enforcements.floorDeals'),
279
+ 'skipRate',
280
+ 'fetchStatus',
281
+ 'floorMin',
282
+ 'floorProvider as provider'
283
+ ]);
284
+ }
285
+ }
286
+
287
+ let pageReferer;
288
+
289
+ const getTopLevelDetails = () => {
290
+ let payload = {
291
+ channel: 'web',
292
+ integration: rubiConf.int_type || DEFAULT_INTEGRATION,
293
+ referrerUri: pageReferer,
294
+ version: '$prebid.version$',
295
+ referrerHostname: magniteAdapter.referrerHostname || getHostNameFromReferer(pageReferer),
296
+ timestamps: {
297
+ timeSincePageLoad: performance.now(),
298
+ eventTime: Date.now(),
299
+ prebidLoaded: magniteAdapter.MODULE_INITIALIZED_TIME
300
+ }
301
+ }
302
+
303
+ // Add DM wrapper details
304
+ if (rubiConf.wrapperName) {
305
+ payload.wrapper = {
306
+ name: rubiConf.wrapperName,
307
+ family: rubiConf.wrapperFamily,
308
+ rule: rubiConf.rule_name
309
+ }
310
+ }
311
+
312
+ if (cache.sessionData) {
313
+ // gather session info
314
+ payload.session = pick(cache.sessionData, [
315
+ 'id',
316
+ 'pvid',
317
+ 'start',
318
+ 'expires'
319
+ ]);
320
+ // Any FPKVS set?
321
+ if (!isEmpty(cache.sessionData.fpkvs)) {
322
+ payload.fpkvs = Object.keys(cache.sessionData.fpkvs).map(key => {
323
+ return { key, value: cache.sessionData.fpkvs[key] };
324
+ });
325
+ }
326
+ }
327
+ return payload;
328
+ }
329
+
330
+ export const getHostNameFromReferer = referer => {
331
+ try {
332
+ magniteAdapter.referrerHostname = parseUrl(referer, { noDecodeWholeURL: true }).hostname;
333
+ } catch (e) {
334
+ logError(`${MODULE_NAME}: Unable to parse hostname from supplied url: `, referer, e);
335
+ magniteAdapter.referrerHostname = '';
336
+ }
337
+ return magniteAdapter.referrerHostname
338
+ };
339
+
340
+ const getRpaCookie = () => {
341
+ let encodedCookie = storage.getDataFromLocalStorage(COOKIE_NAME);
342
+ if (encodedCookie) {
343
+ try {
344
+ return JSON.parse(window.atob(encodedCookie));
345
+ } catch (e) {
346
+ logError(`${MODULE_NAME}: Unable to decode ${COOKIE_NAME} value: `, e);
347
+ }
348
+ }
349
+ return {};
350
+ }
351
+
352
+ const setRpaCookie = (decodedCookie) => {
353
+ try {
354
+ storage.setDataInLocalStorage(COOKIE_NAME, window.btoa(JSON.stringify(decodedCookie)));
355
+ } catch (e) {
356
+ logError(`${MODULE_NAME}: Unable to encode ${COOKIE_NAME} value: `, e);
357
+ }
358
+ }
359
+
360
+ const updateRpaCookie = () => {
361
+ const currentTime = Date.now();
362
+ let decodedRpaCookie = getRpaCookie();
363
+ if (
364
+ !Object.keys(decodedRpaCookie).length ||
365
+ (currentTime - decodedRpaCookie.lastSeen) > LAST_SEEN_EXPIRE_TIME ||
366
+ decodedRpaCookie.expires < currentTime
367
+ ) {
368
+ decodedRpaCookie = {
369
+ id: generateUUID(),
370
+ start: currentTime,
371
+ expires: currentTime + END_EXPIRE_TIME, // six hours later,
372
+ }
373
+ }
374
+ // possible that decodedRpaCookie is undefined, and if it is, we probably are blocked by storage or some other exception
375
+ if (Object.keys(decodedRpaCookie).length) {
376
+ decodedRpaCookie.lastSeen = currentTime;
377
+ decodedRpaCookie.fpkvs = { ...decodedRpaCookie.fpkvs, ...getFpkvs() };
378
+ decodedRpaCookie.pvid = rubiConf.pvid;
379
+ setRpaCookie(decodedRpaCookie)
380
+ }
381
+ return decodedRpaCookie;
382
+ }
383
+
384
+ /*
385
+ Filters and converts URL Params into an object and returns only KVs that match the 'utm_KEY' format
386
+ */
387
+ const getUtmParams = () => {
388
+ let search;
389
+
390
+ try {
391
+ search = parseQS(getWindowLocation().search);
392
+ } catch (e) {
393
+ search = {};
394
+ }
395
+
396
+ return Object.keys(search).reduce((accum, param) => {
397
+ if (param.match(/utm_/)) {
398
+ accum[param.replace(/utm_/, '')] = search[param];
399
+ }
400
+ return accum;
401
+ }, {});
402
+ }
403
+
404
+ const getFpkvs = () => {
405
+ rubiConf.fpkvs = Object.assign((rubiConf.fpkvs || {}), getUtmParams());
406
+
407
+ // convert all values to strings
408
+ Object.keys(rubiConf.fpkvs).forEach(key => {
409
+ rubiConf.fpkvs[key] = rubiConf.fpkvs[key] + '';
410
+ });
411
+
412
+ return rubiConf.fpkvs;
413
+ }
414
+
415
+ /*
416
+ Checks the alias registry for any entries of the rubicon bid adapter.
417
+ adds to the rubiconAliases list if found
418
+ */
419
+ const setRubiconAliases = (aliasRegistry) => {
420
+ const otherAliases = Object.keys(aliasRegistry).filter(alias => aliasRegistry[alias] === 'rubicon');
421
+ rubiconAliases.push(...otherAliases);
422
+ }
423
+
424
+ const sizeToDimensions = size => {
425
+ return {
426
+ width: size.w || size[0],
427
+ height: size.h || size[1]
428
+ };
429
+ }
430
+
431
+ const findMatchingAdUnitFromAuctions = (matchesFunction, returnFirstMatch) => {
432
+ // finding matching adUnit / auction
433
+ let matches = {};
434
+
435
+ // loop through auctions in order and adunits
436
+ for (const auctionId of cache.auctionOrder) {
437
+ const auction = cache.auctions[auctionId].auction;
438
+ for (const transactionId in auction.adUnits) {
439
+ const adUnit = auction.adUnits[transactionId];
440
+
441
+ // check if this matches
442
+ let doesMatch;
443
+ try {
444
+ doesMatch = matchesFunction(adUnit, auction);
445
+ } catch (error) {
446
+ logWarn(`${MODULE_NAME}: Error running matches function: ${returnFirstMatch}`, error);
447
+ doesMatch = false;
448
+ }
449
+ if (doesMatch) {
450
+ matches = { adUnit, auction };
451
+
452
+ // we either return first match or we want last one matching so go to end
453
+ if (returnFirstMatch) return matches;
454
+ }
455
+ }
456
+ }
457
+ return matches;
458
+ }
459
+
460
+ const getRenderingIds = bidWonData => {
461
+ // if bid caching off -> return the bidWon auction id
462
+ if (!config.getConfig('useBidCache')) {
463
+ return {
464
+ renderTransactionId: bidWonData.transactionId,
465
+ renderAuctionId: bidWonData.auctionId
466
+ };
467
+ }
468
+
469
+ // a rendering auction id is the LATEST auction / adunit which contains GAM ID's
470
+ const matchingFunction = (adUnit, auction) => {
471
+ // does adUnit match our bidWon and gam id's are present
472
+ const gamHasRendered = deepAccess(cache, `auctions.${auction.auctionId}.gamRenders.${adUnit.transactionId}`);
473
+ return adUnit.adUnitCode === bidWonData.adUnitCode && gamHasRendered;
474
+ }
475
+ let { adUnit, auction } = findMatchingAdUnitFromAuctions(matchingFunction, false);
476
+ // If no match was found, we will use the actual bid won auction id
477
+ return {
478
+ renderTransactionId: (adUnit && adUnit.transactionId) || bidWonData.transactionId,
479
+ renderAuctionId: (auction && auction.auctionId) || bidWonData.auctionId
480
+ }
481
+ }
482
+
483
+ const formatBidWon = bidWonData => {
484
+ // get transaction and auction id of where this "rendered"
485
+ const { renderTransactionId, renderAuctionId } = getRenderingIds(bidWonData);
486
+
487
+ const isCachedBid = renderTransactionId !== bidWonData.transactionId;
488
+ logInfo(`${MODULE_NAME}: Bid Won : `, {
489
+ isCachedBid,
490
+ renderAuctionId,
491
+ renderTransactionId,
492
+ sourceAuctionId: bidWonData.auctionId,
493
+ sourceTransactionId: bidWonData.transactionId,
494
+ });
495
+
496
+ // get the bid from the source auction id
497
+ let bid = deepAccess(cache, `auctions.${bidWonData.auctionId}.auction.adUnits.${bidWonData.transactionId}.bids.${bidWonData.requestId}`);
498
+ let adUnit = deepAccess(cache, `auctions.${bidWonData.auctionId}.auction.adUnits.${bidWonData.transactionId}`);
499
+ let bidWon = {
500
+ ...bid,
501
+ sourceAuctionId: bidWonData.auctionId,
502
+ renderAuctionId,
503
+ transactionId: bidWonData.transactionId,
504
+ sourceTransactionId: bidWonData.transactionId,
505
+ bidId: bid.pbsBidId || bidWonData.bidId || bidWonData.requestId, // if PBS had us overwrite bidId, use that as signal
506
+ renderTransactionId,
507
+ accountId,
508
+ siteId: adUnit.siteId,
509
+ zoneId: adUnit.zoneId,
510
+ mediaTypes: adUnit.mediaTypes,
511
+ adUnitCode: adUnit.adUnitCode,
512
+ isCachedBid: isCachedBid || undefined // only send if it is true (save some space)
513
+ }
514
+ delete bidWon.pbsBidId; // if pbsBidId is there delete it (no need to pass it)
515
+ return bidWon;
516
+ }
517
+
518
+ const formatGamEvent = (slotEvent, adUnit, auction) => {
519
+ const gamEvent = pick(slotEvent, [
520
+ // these come in as `null` from Gpt, which when stringified does not get removed
521
+ // so set explicitly to undefined when not a number
522
+ 'advertiserId', advertiserId => isNumber(advertiserId) ? advertiserId : undefined,
523
+ 'creativeId', creativeId => isNumber(slotEvent.sourceAgnosticCreativeId) ? slotEvent.sourceAgnosticCreativeId : isNumber(creativeId) ? creativeId : undefined,
524
+ 'lineItemId', lineItemId => isNumber(slotEvent.sourceAgnosticLineItemId) ? slotEvent.sourceAgnosticLineItemId : isNumber(lineItemId) ? lineItemId : undefined,
525
+ 'adSlot', () => slotEvent.slot.getAdUnitPath(),
526
+ 'isSlotEmpty', () => slotEvent.isEmpty || undefined
527
+ ]);
528
+ gamEvent.auctionId = auction.auctionId;
529
+ gamEvent.transactionId = adUnit.transactionId;
530
+ return gamEvent;
531
+ }
532
+
533
+ const subscribeToGamSlots = () => {
534
+ window.googletag.pubads().addEventListener('slotRenderEnded', event => {
535
+ const isMatchingAdSlot = isAdUnitCodeMatchingSlot(event.slot);
536
+
537
+ // We want to find the FIRST auction - adUnit that matches and does not have gam data yet
538
+ const matchingFunction = (adUnit, auction) => {
539
+ // first it has to match the slot
540
+ // if the code is present in the elementIdMap then we use the matched id as code here
541
+ const elementIds = cache.elementIdMap[adUnit.adUnitCode] || [adUnit.adUnitCode];
542
+ const matchesSlot = elementIds.some(isMatchingAdSlot);
543
+
544
+ // next it has to have NOT already been counted as gam rendered
545
+ const gamHasRendered = deepAccess(cache, `auctions.${auction.auctionId}.gamRenders.${adUnit.transactionId}`);
546
+ return matchesSlot && !gamHasRendered;
547
+ }
548
+ let { adUnit, auction } = findMatchingAdUnitFromAuctions(matchingFunction, true);
549
+
550
+ const slotName = `${event.slot.getAdUnitPath()} - ${event.slot.getSlotElementId()}`;
551
+
552
+ if (!adUnit || !auction) {
553
+ logInfo(`${MODULE_NAME}: Could not find matching adUnit for Gam Render: `, {
554
+ slotName
555
+ });
556
+ return;
557
+ }
558
+ const auctionId = auction.auctionId;
559
+
560
+ logInfo(`${MODULE_NAME}: Gam Render: `, {
561
+ slotName,
562
+ transactionId: adUnit.transactionId,
563
+ auctionId: auctionId,
564
+ adUnit: adUnit,
565
+ });
566
+
567
+ // if we have an adunit, then we need to make a gam event
568
+ const gamEvent = formatGamEvent(event, adUnit, auction);
569
+
570
+ // marking that this prebid adunit has had its matching gam render found
571
+ deepSetValue(cache, `auctions.${auctionId}.gamRenders.${adUnit.transactionId}`, true);
572
+
573
+ addEventToQueue({ gamRenders: [gamEvent] }, auctionId, 'gam');
574
+
575
+ // If this auction now has all gam slots rendered, fire the payload
576
+ if (!cache.auctions[auctionId].sent && Object.keys(cache.auctions[auctionId].gamRenders).every(tid => cache.auctions[auctionId].gamRenders[tid])) {
577
+ // clear the auction end timeout
578
+ clearTimeout(cache.timeouts[auctionId]);
579
+ delete cache.timeouts[auctionId];
580
+
581
+ // wait for bid wons a bit or send right away
582
+ if (rubiConf.analyticsEventDelay > 0) {
583
+ setTimeout(() => {
584
+ sendAuctionEvent(auctionId, 'gam-delayed');
585
+ }, rubiConf.analyticsEventDelay);
586
+ } else {
587
+ sendAuctionEvent(auctionId, 'gam');
588
+ }
589
+ }
590
+ });
591
+ }
592
+
593
+ let accountId;
594
+ let endpoint;
595
+
596
+ let magniteAdapter = adapter({ analyticsType: 'endpoint' });
597
+
598
+ magniteAdapter.originEnableAnalytics = magniteAdapter.enableAnalytics;
599
+ function enableMgniAnalytics(config = {}) {
600
+ let error = false;
601
+ // endpoint
602
+ endpoint = deepAccess(config, 'options.endpoint');
603
+ if (!endpoint) {
604
+ logError(`${MODULE_NAME}: required endpoint missing`);
605
+ error = true;
606
+ }
607
+ // accountId
608
+ accountId = Number(deepAccess(config, 'options.accountId'));
609
+ if (!accountId) {
610
+ logError(`${MODULE_NAME}: required accountId missing`);
611
+ error = true;
612
+ }
613
+ if (!error) {
614
+ magniteAdapter.originEnableAnalytics(config);
615
+ }
616
+ // listen to gam slot renders!
617
+ if (isGptPubadsDefined()) {
618
+ subscribeToGamSlots();
619
+ } else {
620
+ window.googletag = window.googletag || {};
621
+ window.googletag.cmd = window.googletag.cmd || [];
622
+ window.googletag.cmd.push(() => subscribeToGamSlots());
623
+ }
624
+ };
625
+
626
+ const handleBidWon = args => {
627
+ const bidWon = formatBidWon(args);
628
+ addEventToQueue({ bidsWon: [bidWon] }, bidWon.renderAuctionId, 'bidWon');
629
+ }
630
+
631
+ magniteAdapter.enableAnalytics = enableMgniAnalytics;
632
+
633
+ magniteAdapter.originDisableAnalytics = magniteAdapter.disableAnalytics;
634
+ magniteAdapter.disableAnalytics = function () {
635
+ // trick analytics module to register our enable back as main one
636
+ magniteAdapter._oldEnable = enableMgniAnalytics;
637
+ endpoint = undefined;
638
+ accountId = undefined;
639
+ resetConfs();
640
+ magniteAdapter.originDisableAnalytics();
641
+ }
642
+
643
+ magniteAdapter.MODULE_INITIALIZED_TIME = Date.now();
644
+ magniteAdapter.referrerHostname = '';
645
+
646
+ magniteAdapter.track = ({ eventType, args }) => {
647
+ switch (eventType) {
648
+ case AUCTION_INIT:
649
+ // Update session
650
+ cache.sessionData = storage.localStorageIsEnabled() && updateRpaCookie();
651
+ // set the rubicon aliases
652
+ setRubiconAliases(adapterManager.aliasRegistry);
653
+
654
+ // latest page "referer"
655
+ pageReferer = deepAccess(args, 'bidderRequests.0.refererInfo.page');
656
+
657
+ // set auction level data
658
+ let auctionData = pick(args, [
659
+ 'auctionId',
660
+ 'timestamp as auctionStart',
661
+ 'timeout as clientTimeoutMillis',
662
+ ]);
663
+ auctionData.accountId = accountId;
664
+
665
+ // Order bidders were called
666
+ auctionData.bidderOrder = args.bidderRequests.map(bidderRequest => bidderRequest.bidderCode);
667
+
668
+ // Price Floors information
669
+ const floorData = deepAccess(args, 'bidderRequests.0.bids.0.floorData');
670
+ if (floorData) {
671
+ auctionData.floors = addFloorData(floorData);
672
+ }
673
+
674
+ // GDPR info
675
+ const gdprData = deepAccess(args, 'bidderRequests.0.gdprConsent');
676
+ if (gdprData) {
677
+ auctionData.gdpr = pick(gdprData, [
678
+ 'gdprApplies as applies',
679
+ 'consentString',
680
+ 'apiVersion as version'
681
+ ]);
682
+ }
683
+
684
+ // User ID Data included in auction
685
+ const userIds = Object.keys(deepAccess(args, 'bidderRequests.0.bids.0.userId', {})).map(id => {
686
+ return { provider: id, hasId: true }
687
+ });
688
+ if (userIds.length) {
689
+ auctionData.user = { ids: userIds };
690
+ }
691
+
692
+ if (serverConfig) {
693
+ auctionData.serverTimeoutMillis = serverConfig.timeout;
694
+ }
695
+
696
+ // lets us keep a map of adunit and wether it had a gam or bid won render yet, used to track when to send events
697
+ let gamRenders = {};
698
+ // adunits saved as map of transactionIds
699
+ auctionData.adUnits = args.adUnits.reduce((adMap, adUnit) => {
700
+ let ad = pick(adUnit, [
701
+ 'code as adUnitCode',
702
+ 'transactionId',
703
+ 'mediaTypes', mediaTypes => Object.keys(mediaTypes),
704
+ 'sizes as dimensions', sizes => sizes.map(sizeToDimensions),
705
+ ]);
706
+ ad.pbAdSlot = deepAccess(adUnit, 'ortb2Imp.ext.data.pbadslot');
707
+ ad.pattern = deepAccess(adUnit, 'ortb2Imp.ext.data.aupname');
708
+ ad.gpid = deepAccess(adUnit, 'ortb2Imp.ext.gpid');
709
+ ad.bids = {};
710
+ adMap[adUnit.transactionId] = ad;
711
+ gamRenders[adUnit.transactionId] = false;
712
+
713
+ // Handle case elementId's (div Id's) are set on adUnit - PPI
714
+ const elementIds = deepAccess(adUnit, 'ortb2Imp.ext.data.elementid');
715
+ if (elementIds) {
716
+ cache.elementIdMap[adUnit.code] = cache.elementIdMap[adUnit.code] || [];
717
+ // set it to array if set to string to be careful (should be array of strings)
718
+ const newIds = typeof elementIds === 'string' ? [elementIds] : elementIds;
719
+ newIds.forEach(id => {
720
+ if (!cache.elementIdMap[adUnit.code].includes(id)) {
721
+ cache.elementIdMap[adUnit.code].push(id);
722
+ }
723
+ });
724
+ }
725
+ return adMap;
726
+ }, {});
727
+
728
+ // holding our pba data to send
729
+ cache.auctions[args.auctionId] = {
730
+ auction: auctionData,
731
+ gamRenders,
732
+ pendingEvents: {}
733
+ }
734
+ break;
735
+ case BID_REQUESTED:
736
+ args.bids.forEach(bid => {
737
+ const adUnit = deepAccess(cache, `auctions.${args.auctionId}.auction.adUnits.${bid.transactionId}`);
738
+ adUnit.bids[bid.bidId] = pick(bid, [
739
+ 'bidder',
740
+ 'bidId',
741
+ 'source', () => bid.src === 's2s' ? 'server' : 'client',
742
+ 'status', () => 'no-bid'
743
+ ]);
744
+ // set acct site zone id on adunit
745
+ if ((!adUnit.siteId || !adUnit.zoneId) && rubiconAliases.indexOf(bid.bidder) !== -1) {
746
+ if (deepAccess(bid, 'params.accountId') == accountId) {
747
+ adUnit.accountId = parseInt(accountId);
748
+ adUnit.siteId = parseInt(deepAccess(bid, 'params.siteId'));
749
+ adUnit.zoneId = parseInt(deepAccess(bid, 'params.zoneId'));
750
+ }
751
+ }
752
+ });
753
+ break;
754
+ case BID_RESPONSE:
755
+ const auctionEntry = deepAccess(cache, `auctions.${args.auctionId}.auction`);
756
+ const adUnit = deepAccess(auctionEntry, `adUnits.${args.transactionId}`);
757
+ let bid = adUnit.bids[args.requestId];
758
+
759
+ // if this came from multibid, there might now be matching bid, so check
760
+ // THIS logic will change when we support multibid per bid request
761
+ if (!bid && args.originalRequestId) {
762
+ let ogBid = adUnit.bids[args.originalRequestId];
763
+ // create new bid
764
+ adUnit.bids[args.requestId] = {
765
+ ...ogBid,
766
+ bidId: args.requestId,
767
+ bidderDetail: args.targetingBidder
768
+ };
769
+ bid = adUnit.bids[args.requestId];
770
+ }
771
+
772
+ // if we have not set enforcements yet set it (This is hidden from bidders until now so we have to get from here)
773
+ if (typeof deepAccess(auctionEntry, 'floors.enforcement') !== 'boolean' && deepAccess(args, 'floorData.enforcements')) {
774
+ auctionEntry.floors.enforcement = args.floorData.enforcements.enforceJS;
775
+ auctionEntry.floors.dealsEnforced = args.floorData.enforcements.floorDeals;
776
+ }
777
+
778
+ // Log error if no matching bid!
779
+ if (!bid) {
780
+ logError(`${MODULE_NAME}: Could not find associated bid request for bid response with requestId: `, args.requestId);
781
+ break;
782
+ }
783
+
784
+ // set bid status
785
+ switch (args.getStatusCode()) {
786
+ case GOOD:
787
+ bid.status = 'success';
788
+ delete bid.error; // it's possible for this to be set by a previous timeout
789
+ break;
790
+ case NO_BID:
791
+ bid.status = args.status === BID_REJECTED ? BID_REJECTED_IPF : 'no-bid';
792
+ delete bid.error;
793
+ break;
794
+ default:
795
+ bid.status = 'error';
796
+ bid.error = {
797
+ code: 'request-error'
798
+ };
799
+ }
800
+ bid.clientLatencyMillis = args.timeToRespond || Date.now() - cache.auctions[args.auctionId].auction.auctionStart;
801
+ bid.bidResponse = parseBidResponse(args, bid.bidResponse);
802
+
803
+ // if pbs gave us back a bidId, we need to use it and update our bidId to PBA
804
+ const pbsBidId = (args.pbsBidId == 0 ? generateUUID() : args.pbsBidId) || (args.seatBidId == 0 ? generateUUID() : args.seatBidId);
805
+ if (pbsBidId) {
806
+ bid.pbsBidId = pbsBidId;
807
+ }
808
+ break;
809
+ case BIDDER_DONE:
810
+ const serverError = deepAccess(args, 'serverErrors.0');
811
+ const serverResponseTimeMs = args.serverResponseTimeMs;
812
+ args.bids.forEach(bid => {
813
+ let cachedBid = deepAccess(cache, `auctions.${bid.auctionId}.auction.adUnits.${bid.transactionId}.bids.${bid.bidId}`);
814
+ if (typeof bid.serverResponseTimeMs !== 'undefined') {
815
+ cachedBid.serverLatencyMillis = bid.serverResponseTimeMs;
816
+ } else if (serverResponseTimeMs && bid.source === 's2s') {
817
+ cachedBid.serverLatencyMillis = serverResponseTimeMs;
818
+ }
819
+ // if PBS said we had an error, and this bid has not been processed by BID_RESPONSE YET
820
+ if (serverError && (!cachedBid.status || ['no-bid', 'error'].indexOf(cachedBid.status) !== -1)) {
821
+ cachedBid.status = 'error';
822
+ cachedBid.error = {
823
+ code: pbsErrorMap[serverError.code] || pbsErrorMap[999],
824
+ description: serverError.message
825
+ }
826
+ }
827
+
828
+ // set client latency if not done yet
829
+ if (!cachedBid.clientLatencyMillis) {
830
+ cachedBid.clientLatencyMillis = Date.now() - cache.auctions[args.auctionId].auction.auctionStart;
831
+ }
832
+ });
833
+ break;
834
+ case BID_WON:
835
+ // Allowing us to delay bidWon handling so it happens at right time
836
+ // we expect it to happen after gpt slotRenderEnded, but have seen it happen before when testing
837
+ // this will ensure it happens after if set
838
+ if (rubiConf.analyticsProcessDelay > 0) {
839
+ setTimeout(() => {
840
+ handleBidWon(args);
841
+ }, rubiConf.analyticsProcessDelay);
842
+ } else {
843
+ handleBidWon(args);
844
+ }
845
+ break;
846
+ case AUCTION_END:
847
+ let auctionCache = cache.auctions[args.auctionId];
848
+ // if for some reason the auction did not do its normal thing, this could be undefied so bail
849
+ if (!auctionCache) {
850
+ break;
851
+ }
852
+ // Set this auction as being done
853
+ auctionCache.auction.auctionEnd = args.auctionEnd;
854
+
855
+ // keeping order of auctions and if the payload has been sent or not
856
+ cache.auctionOrder.push(args.auctionId);
857
+
858
+ const isOnlyInstreamAuction = args.adUnits && args.adUnits.every(adUnit => adUnitIsOnlyInstream(adUnit));
859
+
860
+ // if we are not waiting OR it is instream only auction
861
+ if (isOnlyInstreamAuction || rubiConf.analyticsBatchTimeout === 0) {
862
+ sendAuctionEvent(args.auctionId, 'solo-auction');
863
+ } else {
864
+ // start timer to send batched payload just in case we don't hear any BID_WON events
865
+ cache.timeouts[args.auctionId] = setTimeout(() => {
866
+ sendAuctionEvent(args.auctionId, 'auctionEnd');
867
+ }, rubiConf.analyticsBatchTimeout);
868
+ }
869
+ break;
870
+ case BID_TIMEOUT:
871
+ args.forEach(badBid => {
872
+ let bid = deepAccess(cache, `auctions.${badBid.auctionId}.auction.adUnits.${badBid.transactionId}.bids.${badBid.bidId}`, {});
873
+ // might be set already by bidder-done, so do not overwrite
874
+ if (bid.status !== 'error') {
875
+ bid.status = 'error';
876
+ bid.error = {
877
+ code: 'timeout-error',
878
+ description: 'prebid.js timeout' // will help us diff if timeout was set by PBS or PBJS
879
+ };
880
+ }
881
+ });
882
+ break;
883
+ case BILLABLE_EVENT:
884
+ if (rubiConf.dmBilling.enabled && isBillingEventValid(args)) {
885
+ // add to the map indicating it has not been sent yet
886
+ deepSetValue(cache.billing, `${args.vendor}.${args.billingId}`, false);
887
+ const billingEvent = formatBillingEvent(args);
888
+ addEventToQueue({ billableEvents: [billingEvent] }, args.auctionId, 'billing');
889
+ } else {
890
+ logInfo(`${MODULE_NAME}: Billing event ignored`, args);
891
+ }
892
+ break;
893
+ }
894
+ };
895
+
896
+ adapterManager.registerAnalyticsAdapter({
897
+ adapter: magniteAdapter,
898
+ code: 'magnite',
899
+ gvlid: RUBICON_GVL_ID
900
+ });
901
+
902
+ export default magniteAdapter;