prebid.js 9.4.0 → 9.5.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 (363) hide show
  1. package/.eslintrc.js +31 -5
  2. package/.github/workflows/jscpd.yml +2 -2
  3. package/.github/workflows/linter.yml +107 -0
  4. package/creative/crossDomain.js +6 -3
  5. package/dist/33acrossAnalyticsAdapter.js +1 -1
  6. package/dist/33acrossBidAdapter.js +1 -1
  7. package/dist/33acrossIdSystem.js +1 -1
  8. package/dist/BTBidAdapter.js +1 -1
  9. package/dist/adagioAnalyticsAdapter.js +1 -1
  10. package/dist/adagioBidAdapter.js +1 -1
  11. package/dist/adagioRtdProvider.js +1 -1
  12. package/dist/adagioUtils.js +1 -1
  13. package/dist/addefendBidAdapter.js +1 -1
  14. package/dist/adgenerationBidAdapter.js +1 -1
  15. package/dist/adkernelAdnBidAdapter.js +1 -1
  16. package/dist/adkernelBidAdapter.js +1 -1
  17. package/dist/adkernelUtils.js +1 -0
  18. package/dist/adlooxRtdProvider.js +1 -1
  19. package/dist/admixerBidAdapter.js +1 -1
  20. package/dist/adqueryBidAdapter.js +1 -1
  21. package/dist/adrelevantisBidAdapter.js +1 -1
  22. package/dist/adstirBidAdapter.js +1 -1
  23. package/dist/adtrgtmeBidAdapter.js +1 -1
  24. package/dist/advRedAnalyticsAdapter.js +1 -0
  25. package/dist/adxcgAnalyticsAdapter.js +1 -1
  26. package/dist/adxcgBidAdapter.js +1 -1
  27. package/dist/adyoulikeBidAdapter.js +1 -1
  28. package/dist/agmaAnalyticsAdapter.js +1 -1
  29. package/dist/ajaBidAdapter.js +1 -1
  30. package/dist/akamaiDapRtdProvider.js +1 -1
  31. package/dist/amxBidAdapter.js +1 -1
  32. package/dist/amxIdSystem.js +1 -1
  33. package/dist/anonymisedRtdProvider.js +1 -1
  34. package/dist/apacdexBidAdapter.js +1 -1
  35. package/dist/appierAnalyticsAdapter.js +1 -1
  36. package/dist/appnexusBidAdapter.js +1 -1
  37. package/dist/asoBidAdapter.js +1 -1
  38. package/dist/axonixBidAdapter.js +1 -1
  39. package/dist/azerionedgeRtdProvider.js +1 -1
  40. package/dist/bidglassBidAdapter.js +1 -1
  41. package/dist/big-richmediaBidAdapter.js +1 -1
  42. package/dist/bridBidAdapter.js +1 -1
  43. package/dist/bridgewellBidAdapter.js +1 -1
  44. package/dist/brightMountainMediaBidAdapter.js +1 -1
  45. package/dist/carodaBidAdapter.js +1 -1
  46. package/dist/chtnwBidAdapter.js +1 -1
  47. package/dist/chunk-core.js +1 -1
  48. package/dist/concertBidAdapter.js +1 -1
  49. package/dist/connatixBidAdapter.js +1 -1
  50. package/dist/connectadBidAdapter.js +1 -1
  51. package/dist/consumableBidAdapter.js +1 -1
  52. package/dist/contxtfulRtdProvider.js +1 -1
  53. package/dist/conversantAnalyticsAdapter.js +1 -1
  54. package/dist/conversantBidAdapter.js +1 -1
  55. package/dist/craftBidAdapter.js +1 -1
  56. package/dist/criteoBidAdapter.js +1 -1
  57. package/dist/currencyUtils.js +1 -1
  58. package/dist/cwireBidAdapter.js +1 -1
  59. package/dist/dailymotionBidAdapter.js +1 -1
  60. package/dist/debugging-standalone.js +1 -1
  61. package/dist/dependencies.json +43 -7
  62. package/dist/dfpAdServerVideo.js +1 -1
  63. package/dist/dfpAdpod.js +1 -1
  64. package/dist/dfpUtils.js +1 -1
  65. package/dist/discoveryBidAdapter.js +1 -1
  66. package/dist/dspxBidAdapter.js +1 -1
  67. package/dist/dxkultureBidAdapter.js +1 -1
  68. package/dist/eightPodAnalyticsAdapter.js +1 -1
  69. package/dist/eightPodBidAdapter.js +1 -1
  70. package/dist/eplanningBidAdapter.js +1 -1
  71. package/dist/euidIdSystem.js +1 -1
  72. package/dist/exadsBidAdapter.js +1 -1
  73. package/dist/feedadBidAdapter.js +1 -1
  74. package/dist/finativeBidAdapter.js +1 -1
  75. package/dist/fintezaAnalyticsAdapter.js +1 -1
  76. package/dist/fpdUtils.js +1 -0
  77. package/dist/freewheel-sspBidAdapter.js +1 -1
  78. package/dist/gmosspBidAdapter.js +1 -1
  79. package/dist/goldbachBidAdapter.js +1 -1
  80. package/dist/gptPreAuction.js +1 -1
  81. package/dist/gptUtils.js +1 -1
  82. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  83. package/dist/greenbidsRtdProvider.js +1 -1
  84. package/dist/gridBidAdapter.js +1 -1
  85. package/dist/growthCodeAnalyticsAdapter.js +1 -1
  86. package/dist/growthCodeRtdProvider.js +1 -1
  87. package/dist/gumgumBidAdapter.js +1 -1
  88. package/dist/h12mediaBidAdapter.js +1 -1
  89. package/dist/hypelabBidAdapter.js +1 -1
  90. package/dist/id5AnalyticsAdapter.js +1 -1
  91. package/dist/id5IdSystem.js +1 -1
  92. package/dist/imdsBidAdapter.js +1 -1
  93. package/dist/improvedigitalBidAdapter.js +1 -1
  94. package/dist/insticatorBidAdapter.js +1 -1
  95. package/dist/intentIqAnalyticsAdapter.js +1 -0
  96. package/dist/ixBidAdapter.js +1 -1
  97. package/dist/jixieBidAdapter.js +1 -1
  98. package/dist/justpremiumBidAdapter.js +1 -1
  99. package/dist/jwplayerBidAdapter.js +1 -1
  100. package/dist/jwplayerRtdProvider.js +1 -1
  101. package/dist/kargoBidAdapter.js +1 -1
  102. package/dist/kimberliteBidAdapter.js +1 -1
  103. package/dist/konduitAnalyticsAdapter.js +1 -1
  104. package/dist/kueezBidAdapter.js +1 -1
  105. package/dist/lassoBidAdapter.js +1 -1
  106. package/dist/lifestreetBidAdapter.js +1 -1
  107. package/dist/liveIntentIdSystem.js +1 -1
  108. package/dist/logicadBidAdapter.js +1 -1
  109. package/dist/loglyliftBidAdapter.js +1 -1
  110. package/dist/luceadBidAdapter.js +1 -1
  111. package/dist/mabidderBidAdapter.js +1 -1
  112. package/dist/magniteAnalyticsAdapter.js +1 -1
  113. package/dist/malltvAnalyticsAdapter.js +1 -1
  114. package/dist/marsmediaBidAdapter.js +1 -1
  115. package/dist/mediafuseBidAdapter.js +1 -1
  116. package/dist/mediagoBidAdapter.js +1 -1
  117. package/dist/medianetAnalyticsAdapter.js +1 -1
  118. package/dist/medianetBidAdapter.js +1 -1
  119. package/dist/mediasquareBidAdapter.js +1 -1
  120. package/dist/mgidBidAdapter.js +1 -1
  121. package/dist/minutemediaBidAdapter.js +1 -1
  122. package/dist/missenaBidAdapter.js +1 -1
  123. package/dist/mobianRtdProvider.js +1 -1
  124. package/dist/nextMillenniumBidAdapter.js +1 -1
  125. package/dist/nexx360BidAdapter.js +1 -1
  126. package/dist/nobidAnalyticsAdapter.js +1 -1
  127. package/dist/nobidBidAdapter.js +1 -1
  128. package/dist/not-for-prod/prebid.js +201 -193
  129. package/dist/oguryBidAdapter.js +1 -1
  130. package/dist/onetagBidAdapter.js +1 -1
  131. package/dist/ooloAnalyticsAdapter.js +1 -1
  132. package/dist/openwebBidAdapter.js +1 -1
  133. package/dist/openxBidAdapter.js +1 -1
  134. package/dist/optidigitalBidAdapter.js +1 -1
  135. package/dist/optoutBidAdapter.js +1 -1
  136. package/dist/orbidderBidAdapter.js +1 -1
  137. package/dist/outbrainBidAdapter.js +1 -1
  138. package/dist/paapi.js +1 -1
  139. package/dist/permutiveRtdProvider.js +1 -1
  140. package/dist/pixfutureBidAdapter.js +1 -1
  141. package/dist/playdigoBidAdapter.js +1 -1
  142. package/dist/prebidServerBidAdapter.js +1 -1
  143. package/dist/programmaticaBidAdapter.js +1 -1
  144. package/dist/publinkIdSystem.js +1 -1
  145. package/dist/publirBidAdapter.js +1 -1
  146. package/dist/pubmaticAnalyticsAdapter.js +1 -1
  147. package/dist/pubmaticBidAdapter.js +1 -1
  148. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  149. package/dist/pubxaiAnalyticsAdapter.js +1 -1
  150. package/dist/pxyzBidAdapter.js +1 -1
  151. package/dist/quantcastBidAdapter.js +1 -1
  152. package/dist/readpeakBidAdapter.js +1 -1
  153. package/dist/relaidoBidAdapter.js +1 -1
  154. package/dist/relevatehealthBidAdapter.js +1 -1
  155. package/dist/retailspotBidAdapter.js +1 -1
  156. package/dist/rhythmoneBidAdapter.js +1 -1
  157. package/dist/ringieraxelspringerBidAdapter.js +1 -1
  158. package/dist/riseBidAdapter.js +1 -1
  159. package/dist/rubiconBidAdapter.js +1 -1
  160. package/dist/schainSerializer.js +1 -0
  161. package/dist/seedingAllianceBidAdapter.js +1 -1
  162. package/dist/seedtagBidAdapter.js +1 -1
  163. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  164. package/dist/sharethroughBidAdapter.js +1 -1
  165. package/dist/shinezBidAdapter.js +1 -1
  166. package/dist/sizeMapping.js +1 -1
  167. package/dist/sizeUtils.js +1 -1
  168. package/dist/smaatoBidAdapter.js +1 -1
  169. package/dist/smartadserverBidAdapter.js +1 -1
  170. package/dist/smartxBidAdapter.js +1 -1
  171. package/dist/smilewantedBidAdapter.js +1 -1
  172. package/dist/snigelBidAdapter.js +1 -1
  173. package/dist/sonobiBidAdapter.js +1 -1
  174. package/dist/sovrnBidAdapter.js +1 -1
  175. package/dist/sspBCBidAdapter.js +1 -1
  176. package/dist/stnBidAdapter.js +1 -1
  177. package/dist/stvBidAdapter.js +1 -1
  178. package/dist/sublimeBidAdapter.js +1 -1
  179. package/dist/symitriDapRtdProvider.js +1 -0
  180. package/dist/taboolaBidAdapter.js +1 -1
  181. package/dist/tappxBidAdapter.js +1 -1
  182. package/dist/targetVideoBidAdapter.js +1 -1
  183. package/dist/targetVideoUtils.js +1 -0
  184. package/dist/teadsBidAdapter.js +1 -1
  185. package/dist/terceptAnalyticsAdapter.js +1 -1
  186. package/dist/themoneytizerBidAdapter.js +1 -1
  187. package/dist/trionBidAdapter.js +1 -1
  188. package/dist/tripleliftBidAdapter.js +1 -1
  189. package/dist/ttdBidAdapter.js +1 -1
  190. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  191. package/dist/uid2IdSystem.js +1 -1
  192. package/dist/underdogmediaBidAdapter.js +1 -1
  193. package/dist/undertoneBidAdapter.js +1 -1
  194. package/dist/unrulyBidAdapter.js +1 -1
  195. package/dist/userAgentUtils.js +1 -0
  196. package/dist/utiqIdSystem.js +1 -1
  197. package/dist/vidazooUtils.js +1 -1
  198. package/dist/videobyteBidAdapter.js +1 -1
  199. package/dist/visxBidAdapter.js +1 -1
  200. package/dist/vuukleBidAdapter.js +1 -1
  201. package/dist/widespaceBidAdapter.js +1 -1
  202. package/dist/winrBidAdapter.js +1 -1
  203. package/dist/yahooAdsBidAdapter.js +1 -1
  204. package/dist/yandexIdSystem.js +1 -1
  205. package/dist/yieldmoBidAdapter.js +1 -1
  206. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  207. package/integrationExamples/gpt/x-domain/creative.html +1 -1
  208. package/libraries/adkernelUtils/adkernelUtils.js +11 -0
  209. package/libraries/currencyUtils/floor.js +23 -0
  210. package/libraries/dfpUtils/dfpUtils.js +7 -0
  211. package/libraries/fpdUtils/deviceInfo.js +58 -0
  212. package/libraries/fpdUtils/pageInfo.js +73 -0
  213. package/libraries/gptUtils/gptUtils.js +23 -1
  214. package/libraries/schainSerializer/schainSerializer.js +24 -0
  215. package/libraries/sizeUtils/tranformSize.js +43 -0
  216. package/libraries/targetVideoUtils/bidderUtils.js +178 -0
  217. package/libraries/targetVideoUtils/constants.js +23 -0
  218. package/libraries/userAgentUtils/index.js +58 -0
  219. package/libraries/userAgentUtils/userAgentTypes.enums.js +22 -0
  220. package/modules/.submodules.json +1 -0
  221. package/modules/33acrossAnalyticsAdapter.js +2 -0
  222. package/modules/adagioBidAdapter.js +1 -1
  223. package/modules/adagioRtdProvider.js +18 -4
  224. package/modules/adkernelAdnBidAdapter.js +1 -12
  225. package/modules/adkernelBidAdapter.js +4 -13
  226. package/modules/adlooxAnalyticsAdapter.js +1 -0
  227. package/modules/admixerBidAdapter.js +10 -6
  228. package/modules/admixerBidAdapter.md +7 -10
  229. package/modules/adtrgtmeBidAdapter.js +1 -1
  230. package/modules/advRedAnalyticsAdapter.js +198 -0
  231. package/modules/advRedAnalyticsAdapter.md +30 -0
  232. package/modules/akamaiDapRtdProvider.js +19 -798
  233. package/modules/anonymisedRtdProvider.js +5 -1
  234. package/modules/anonymisedRtdProvider.md +1 -1
  235. package/modules/apacdexBidAdapter.js +1 -1
  236. package/modules/appnexusBidAdapter.js +56 -2
  237. package/modules/automatadAnalyticsAdapter.js +2 -0
  238. package/modules/azerionedgeRtdProvider.js +13 -3
  239. package/modules/azerionedgeRtdProvider.md +0 -17
  240. package/modules/bridBidAdapter.js +47 -47
  241. package/modules/cleanioRtdProvider.js +1 -0
  242. package/modules/concertBidAdapter.js +1 -1
  243. package/modules/connatixBidAdapter.js +36 -8
  244. package/modules/connectIdSystem.js +3 -1
  245. package/modules/contxtfulRtdProvider.js +20 -2
  246. package/modules/contxtfulRtdProvider.md +1 -0
  247. package/modules/craftBidAdapter.js +1 -1
  248. package/modules/criteoBidAdapter.js +1 -1
  249. package/modules/cwireBidAdapter.js +5 -1
  250. package/modules/dailymotionBidAdapter.js +85 -65
  251. package/modules/debugging/debugging.js +3 -0
  252. package/modules/dfpAdServerVideo.js +15 -33
  253. package/modules/dfpAdpod.js +2 -6
  254. package/modules/dgkeywordRtdProvider.js +2 -0
  255. package/modules/discoveryBidAdapter.js +26 -210
  256. package/modules/dspxBidAdapter.js +176 -54
  257. package/modules/eightPodAnalyticsAdapter.js +28 -34
  258. package/modules/eightPodBidAdapter.js +113 -57
  259. package/modules/fintezaAnalyticsAdapter.js +9 -4
  260. package/modules/goldbachBidAdapter.js +1 -1
  261. package/modules/gptPreAuction.js +63 -4
  262. package/modules/growthCodeAnalyticsAdapter.js +1 -1
  263. package/modules/growthCodeRtdProvider.js +1 -1
  264. package/modules/gumgumBidAdapter.js +14 -10
  265. package/modules/improvedigitalBidAdapter.js +1 -1
  266. package/modules/intentIqAnalyticsAdapter.js +234 -0
  267. package/modules/intentIqAnalyticsAdapter.md +27 -0
  268. package/modules/intentIqIdSystem.md +0 -0
  269. package/modules/jwplayerBidAdapter.js +1 -1
  270. package/modules/jwplayerRtdProvider.js +26 -6
  271. package/modules/jwplayerVideoProvider.js +6 -0
  272. package/modules/mediafuseBidAdapter.js +1 -1
  273. package/modules/mediagoBidAdapter.js +7 -176
  274. package/modules/medianetBidAdapter.js +101 -40
  275. package/modules/mgidBidAdapter.js +3 -1
  276. package/modules/mobianRtdProvider.js +16 -2
  277. package/modules/nextMillenniumBidAdapter.js +1 -27
  278. package/modules/nobidBidAdapter.js +1 -1
  279. package/modules/optoutBidAdapter.js +1 -1
  280. package/modules/paapi.js +48 -35
  281. package/modules/permutiveRtdProvider.js +72 -22
  282. package/modules/playdigoBidAdapter.js +4 -2
  283. package/modules/prebidServerBidAdapter/index.js +4 -2
  284. package/modules/prebidServerBidAdapter/ortbConverter.js +1 -0
  285. package/modules/programmaticaBidAdapter.js +1 -1
  286. package/modules/pubmaticBidAdapter.js +12 -0
  287. package/modules/pubxaiAnalyticsAdapter.js +306 -164
  288. package/modules/relevatehealthBidAdapter.js +2 -1
  289. package/modules/richaudienceBidAdapter.js +1 -1
  290. package/modules/rtdModule/index.js +5 -3
  291. package/modules/sirdataRtdProvider.js +2 -0
  292. package/modules/sizeMapping.js +2 -5
  293. package/modules/smaatoBidAdapter.js +18 -1
  294. package/modules/smilewantedBidAdapter.js +26 -22
  295. package/modules/snigelBidAdapter.js +1 -1
  296. package/modules/sonobiBidAdapter.js +5 -10
  297. package/modules/symitriDapRtdProvider.js +812 -0
  298. package/modules/symitriDapRtdProvider.md +49 -0
  299. package/modules/targetVideoBidAdapter.js +120 -152
  300. package/modules/targetVideoBidAdapter.md +20 -3
  301. package/modules/userId/eids.js +3 -0
  302. package/modules/utiqIdSystem.js +12 -10
  303. package/modules/validationFpdModule/index.js +22 -17
  304. package/modules/videojsVideoProvider.js +3 -0
  305. package/modules/visxBidAdapter.js +1 -1
  306. package/modules/winrBidAdapter.js +2 -27
  307. package/modules/yahooAdsBidAdapter.js +1 -1
  308. package/modules/yandexIdSystem.js +1 -1
  309. package/package.json +4 -4
  310. package/plugins/eslint/index.js +73 -45
  311. package/src/adRendering.js +7 -3
  312. package/src/adloader.js +1 -0
  313. package/src/ajax.js +15 -0
  314. package/src/config.js +0 -4
  315. package/src/debugging.js +1 -0
  316. package/src/secureCreatives.js +1 -1
  317. package/src/storageManager.js +62 -73
  318. package/src/targeting.js +26 -20
  319. package/src/utils.js +9 -0
  320. package/test/pages/banner_sync.html +97 -0
  321. package/test/pages/consent_mgt_gdpr.html +1 -1
  322. package/test/spec/ajax_spec.js +11 -0
  323. package/test/spec/creative/crossDomainCreative_spec.js +26 -9
  324. package/test/spec/e2e/banner/basic_banner_ad.spec.js +20 -14
  325. package/test/spec/fpd/gdpr_spec.js +1 -1
  326. package/test/spec/libraries/userAgentUtils_spec.js +109 -0
  327. package/test/spec/modules/adagioRtdProvider_spec.js +72 -0
  328. package/test/spec/modules/admixerBidAdapter_spec.js +21 -17
  329. package/test/spec/modules/advRedAnalyticsAdapter_spec.js +114 -0
  330. package/test/spec/modules/adxcgBidAdapter_spec.js +1 -1
  331. package/test/spec/modules/appnexusBidAdapter_spec.js +36 -0
  332. package/test/spec/modules/azerionedgeRtdProvider_spec.js +36 -21
  333. package/test/spec/modules/connatixBidAdapter_spec.js +55 -2
  334. package/test/spec/modules/consentManagement_spec.js +1 -1
  335. package/test/spec/modules/contxtfulRtdProvider_spec.js +6 -0
  336. package/test/spec/modules/dailymotionBidAdapter_spec.js +497 -4
  337. package/test/spec/modules/discoveryBidAdapter_spec.js +9 -6
  338. package/test/spec/modules/dspxBidAdapter_spec.js +188 -7
  339. package/test/spec/modules/eightPodAnalyticsAdapter_spec.js +22 -13
  340. package/test/spec/modules/gptPreAuction_spec.js +143 -1
  341. package/test/spec/modules/gumgumBidAdapter_spec.js +17 -0
  342. package/test/spec/modules/intentIqAnalyticsAdapter_spec.js +172 -0
  343. package/test/spec/modules/jwplayerRtdProvider_spec.js +61 -0
  344. package/test/spec/modules/mediagoBidAdapter_spec.js +34 -37
  345. package/test/spec/modules/medianetBidAdapter_spec.js +297 -16
  346. package/test/spec/modules/mgidBidAdapter_spec.js +15 -5
  347. package/test/spec/modules/mobianRtdProvider_spec.js +1 -3
  348. package/test/spec/modules/paapi_spec.js +177 -111
  349. package/test/spec/modules/permutiveRtdProvider_spec.js +42 -8
  350. package/test/spec/modules/prebidServerBidAdapter_spec.js +17 -3
  351. package/test/spec/modules/proxistoreBidAdapter_spec.js +1 -1
  352. package/test/spec/modules/pubmaticBidAdapter_spec.js +40 -0
  353. package/test/spec/modules/pubxaiAnalyticsAdapter_spec.js +970 -603
  354. package/test/spec/modules/pulsepointBidAdapter_spec.js +4 -4
  355. package/test/spec/modules/smaatoBidAdapter_spec.js +36 -1
  356. package/test/spec/modules/smilewantedBidAdapter_spec.js +57 -1
  357. package/test/spec/modules/symitriDapRtdProvider_spec.js +600 -0
  358. package/test/spec/modules/targetVideoBidAdapter_spec.js +112 -11
  359. package/test/spec/modules/yandexIdSystem_spec.js +6 -1
  360. package/test/spec/schainSerializer/schainSerializer_spec.js +138 -0
  361. package/test/spec/unit/core/storageManager_spec.js +68 -51
  362. package/test/spec/utils_spec.js +19 -0
  363. /package/src/utils/{gpdr.js → gdpr.js} +0 -0
@@ -1,4 +1,5 @@
1
- import {deepAccess, getBidIdParameter, isFn, logError, logMessage, logWarn} from '../src/utils.js';
1
+ import {deepAccess, getBidIdParameter, isFn, logError, logMessage, logWarn, isEmptyStr, isArray} from '../src/utils.js';
2
+
2
3
  import {registerBidder} from '../src/adapters/bidderFactory.js';
3
4
  import {BANNER, VIDEO} from '../src/mediaTypes.js';
4
5
  import {Renderer} from '../src/Renderer.js';
@@ -7,7 +8,6 @@ import {includes} from '../src/polyfill.js';
7
8
  /**
8
9
  * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest
9
10
  */
10
-
11
11
  const BIDDER_CODE = 'dspx';
12
12
  const ENDPOINT_URL = 'https://buyer.dspx.tv/request/';
13
13
  const ENDPOINT_URL_DEV = 'https://dcbuyer.dspx.tv/request/';
@@ -63,24 +63,18 @@ export const spec = {
63
63
  rnd: rnd,
64
64
  ref: referrer,
65
65
  bid_id: bidId,
66
- pbver: '$prebid.version$'
66
+ pbver: '$prebid.version$',
67
67
  };
68
68
 
69
+ payload.pfilter = {};
69
70
  if (params.pfilter !== undefined) {
70
71
  payload.pfilter = params.pfilter;
71
72
  }
72
73
 
73
74
  if (bidderRequest && bidderRequest.gdprConsent) {
74
- if (payload.pfilter !== undefined) {
75
- if (!payload.pfilter.gdpr_consent) {
76
- payload.pfilter.gdpr_consent = bidderRequest.gdprConsent.consentString;
77
- payload.pfilter.gdpr = bidderRequest.gdprConsent.gdprApplies;
78
- }
79
- } else {
80
- payload.pfilter = {
81
- 'gdpr_consent': bidderRequest.gdprConsent.consentString,
82
- 'gdpr': bidderRequest.gdprConsent.gdprApplies
83
- };
75
+ if (!payload.pfilter.gdpr_consent) {
76
+ payload.pfilter.gdpr_consent = bidderRequest.gdprConsent.consentString;
77
+ payload.pfilter.gdpr = bidderRequest.gdprConsent.gdprApplies;
84
78
  }
85
79
  }
86
80
 
@@ -94,48 +88,10 @@ export const spec = {
94
88
  payload.prebidDevMode = 1;
95
89
  }
96
90
 
97
- // fill userId params
98
- if (bidRequest.userId) {
99
- if (bidRequest.userId.netId) {
100
- payload.did_netid = bidRequest.userId.netId;
101
- }
102
- if (bidRequest.userId.id5id) {
103
- payload.did_id5 = bidRequest.userId.id5id.uid || '0';
104
- if (bidRequest.userId.id5id.ext.linkType !== undefined) {
105
- payload.did_id5_linktype = bidRequest.userId.id5id.ext.linkType;
106
- }
107
- }
108
- let uId2 = deepAccess(bidRequest, 'userId.uid2.id');
109
- if (uId2) {
110
- payload.did_uid2 = uId2;
111
- }
112
- let sharedId = deepAccess(bidRequest, 'userId.sharedid.id');
113
- if (sharedId) {
114
- payload.did_sharedid = sharedId;
115
- }
116
- let pubcId = deepAccess(bidRequest, 'userId.pubcid');
117
- if (pubcId) {
118
- payload.did_pubcid = pubcId;
119
- }
120
- let crumbsPubcid = deepAccess(bidRequest, 'crumbs.pubcid');
121
- if (crumbsPubcid) {
122
- payload.did_cpubcid = crumbsPubcid;
123
- }
124
- }
125
-
126
- if (bidRequest.schain) {
127
- payload.schain = bidRequest.schain;
128
- }
129
-
130
- if (payload.pfilter === undefined || !payload.pfilter.floorprice) {
91
+ if (!payload.pfilter.floorprice) {
131
92
  let bidFloor = getBidFloor(bidRequest);
132
93
  if (bidFloor > 0) {
133
- if (payload.pfilter !== undefined) {
134
- payload.pfilter.floorprice = bidFloor;
135
- } else {
136
- payload.pfilter = { 'floorprice': bidFloor };
137
- }
138
- // payload.bidFloor = bidFloor;
94
+ payload.pfilter.floorprice = bidFloor;
139
95
  }
140
96
  }
141
97
 
@@ -146,6 +102,7 @@ export const spec = {
146
102
  payload.pbcode = pbcode;
147
103
  }
148
104
 
105
+ // media types
149
106
  payload.media_types = convertMediaInfoForRequest(mediaTypesInfo);
150
107
  if (mediaTypesInfo[VIDEO] !== undefined) {
151
108
  payload.vctx = getVideoContext(bidRequest);
@@ -159,6 +116,33 @@ export const spec = {
159
116
  .forEach(key => payload.vpl[key] = videoParams[key]);
160
117
  }
161
118
 
119
+ // iab content
120
+ let content = deepAccess(bidderRequest, 'ortb2.site.content');
121
+ if (content) {
122
+ let stringContent = siteContentToString(content);
123
+ if (stringContent) {
124
+ payload.pfilter.iab_content = stringContent;
125
+ }
126
+ }
127
+
128
+ // Google Topics
129
+ const segments = extractUserSegments(bidderRequest);
130
+ if (segments) {
131
+ assignDefinedValues(payload, {
132
+ segtx: segments.segtax,
133
+ segcl: segments.segclass,
134
+ segs: segments.segments
135
+ });
136
+ }
137
+
138
+ // schain
139
+ if (bidRequest.schain) {
140
+ payload.schain = bidRequest.schain;
141
+ }
142
+
143
+ // fill userId params
144
+ fillUsersIds(bidRequest, payload);
145
+
162
146
  return {
163
147
  method: 'GET',
164
148
  url: endpoint,
@@ -257,6 +241,74 @@ export const spec = {
257
241
  }
258
242
  }
259
243
 
244
+ /**
245
+ * Adds userIds to payload
246
+ *
247
+ * @param bidRequest
248
+ * @param payload
249
+ */
250
+ function fillUsersIds(bidRequest, payload) {
251
+ if (bidRequest.hasOwnProperty('userId')) {
252
+ let didMapping = {
253
+ did_netid: 'userId.netId',
254
+ did_id5: 'userId.id5id.uid',
255
+ did_id5_linktype: 'userId.id5id.ext.linkType',
256
+ did_uid2: 'userId.uid2',
257
+ did_sharedid: 'userId.sharedid',
258
+ did_pubcid: 'userId.pubcid',
259
+ did_uqid: 'userId.utiq',
260
+ did_cruid: 'userId.criteoid',
261
+ did_euid: 'userId.euid',
262
+ // did_tdid: 'unifiedId',
263
+ did_tdid: 'userId.tdid',
264
+ did_ppuid: function() {
265
+ let path = 'userId.pubProvidedId';
266
+ let value = deepAccess(bidRequest, path);
267
+ if (isArray(value)) {
268
+ for (const rec of value) {
269
+ if (rec.uids && rec.uids.length > 0) {
270
+ for (let i = 0; i < rec.uids.length; i++) {
271
+ if ('id' in rec.uids[i] && deepAccess(rec.uids[i], 'ext.stype') === 'ppuid') {
272
+ return (rec.uids[i].atype ?? '') + ':' + rec.source + ':' + rec.uids[i].id;
273
+ }
274
+ }
275
+ }
276
+ }
277
+ }
278
+ return undefined;
279
+ },
280
+ did_cpubcid: 'crumbs.pubcid'
281
+ };
282
+ for (let paramName in didMapping) {
283
+ let path = didMapping[paramName];
284
+
285
+ // handle function
286
+ if (typeof path == 'function') {
287
+ let value = path(paramName);
288
+ if (value) {
289
+ payload[paramName] = value;
290
+ }
291
+ continue;
292
+ }
293
+ // direct access
294
+ let value = deepAccess(bidRequest, path);
295
+ if (typeof value == 'string' || typeof value == 'number') {
296
+ payload[paramName] = value;
297
+ } else if (typeof value == 'object') {
298
+ // trying to find string ID value
299
+ if (typeof deepAccess(bidRequest, path + '.id') == 'string') {
300
+ payload[paramName] = deepAccess(bidRequest, path + '.id');
301
+ } else {
302
+ if (Object.keys(value).length > 0) {
303
+ logError(`DSPx: WARNING: fillUserIds had to use first key in user object to get value for bid.userId key: ${path}.`);
304
+ payload[paramName] = value[Object.keys(value)[0]];
305
+ }
306
+ }
307
+ }
308
+ }
309
+ }
310
+ }
311
+
260
312
  function appendToUrl(url, what) {
261
313
  if (!what) {
262
314
  return url;
@@ -276,7 +328,7 @@ function objectToQueryString(obj, prefix) {
276
328
  : encodeURIComponent(k) + '=' + encodeURIComponent(v));
277
329
  }
278
330
  }
279
- return str.join('&');
331
+ return str.filter(n => n).join('&');
280
332
  }
281
333
 
282
334
  /**
@@ -508,4 +560,74 @@ function createOutstreamEmbedCode(bid) {
508
560
  return fragment;
509
561
  }
510
562
 
563
+ /**
564
+ * Convert site.content to string
565
+ * @param content
566
+ */
567
+ function siteContentToString(content) {
568
+ if (!content) {
569
+ return '';
570
+ }
571
+ let stringKeys = ['id', 'title', 'series', 'season', 'artist', 'genre', 'isrc', 'url', 'keywords'];
572
+ let intKeys = ['episode', 'context', 'livestream'];
573
+ let arrKeys = ['cat'];
574
+ let retArr = [];
575
+ arrKeys.forEach(k => {
576
+ let val = deepAccess(content, k);
577
+ if (val && Array.isArray(val)) {
578
+ retArr.push(k + ':' + val.join('|'));
579
+ }
580
+ });
581
+ intKeys.forEach(k => {
582
+ let val = deepAccess(content, k);
583
+ if (val && typeof val === 'number') {
584
+ retArr.push(k + ':' + val);
585
+ }
586
+ });
587
+ stringKeys.forEach(k => {
588
+ let val = deepAccess(content, k);
589
+ if (val && typeof val === 'string') {
590
+ retArr.push(k + ':' + encodeURIComponent(val));
591
+ }
592
+ });
593
+ return retArr.join(',');
594
+ }
595
+
596
+ /**
597
+ * Assigns multiple values to the specified keys on an object if the values are not undefined.
598
+ * @param {Object} target - The object to which the values will be assigned.
599
+ * @param {Object} values - An object containing key-value pairs to be assigned.
600
+ */
601
+ function assignDefinedValues(target, values) {
602
+ for (const key in values) {
603
+ if (values[key] !== undefined) {
604
+ target[key] = values[key];
605
+ }
606
+ }
607
+ }
608
+
609
+ /**
610
+ * Extracts user segments/topics from the bid request object
611
+ * @param {Object} bid - The bid request object
612
+ * @returns {{segclass: *, segtax: *, segments: *}|undefined} - User segments/topics or undefined if not found
613
+ */
614
+ function extractUserSegments(bid) {
615
+ const userData = deepAccess(bid, 'ortb2.user.data') || [];
616
+ for (const dataObj of userData) {
617
+ if (dataObj.segment && isArray(dataObj.segment) && dataObj.segment.length > 0) {
618
+ const segments = dataObj.segment
619
+ .filter(seg => seg.id && !isEmptyStr(seg.id) && isFinite(seg.id))
620
+ .map(seg => Number(seg.id));
621
+ if (segments.length > 0) {
622
+ return {
623
+ segtax: deepAccess(dataObj, 'ext.segtax'),
624
+ segclass: deepAccess(dataObj, 'ext.segclass'),
625
+ segments: segments.join(',')
626
+ };
627
+ }
628
+ }
629
+ }
630
+ return undefined;
631
+ }
632
+
511
633
  registerBidder(spec);
@@ -1,4 +1,4 @@
1
- import {logError, logInfo} from '../src/utils.js';
1
+ import {logError, logInfo, logMessage} from '../src/utils.js';
2
2
  import {ajax} from '../src/ajax.js';
3
3
  import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js';
4
4
  import { EVENTS } from '../src/constants.js';
@@ -9,13 +9,11 @@ import {getStorageManager} from '../src/storageManager.js';
9
9
  const analyticsType = 'endpoint';
10
10
  const MODULE_NAME = `eightPod`;
11
11
  const MODULE = `${MODULE_NAME}AnalyticProvider`;
12
- let interval;
13
12
 
14
13
  /**
15
14
  * Custom tracking server that gets internal events from EightPod's ad unit
16
15
  */
17
16
  const trackerUrl = 'https://demo.8pod.com/tracker/track';
18
-
19
17
  export const storage = getStorageManager({moduleType: MODULE_TYPE_ANALYTICS, moduleName: MODULE_NAME})
20
18
 
21
19
  const {
@@ -23,12 +21,12 @@ const {
23
21
  } = EVENTS;
24
22
 
25
23
  export let queue = [];
26
- export let context;
24
+ let context = {};
27
25
 
28
26
  /**
29
27
  * Create eightPod Analytic adapter
30
28
  */
31
- let eightPodAnalytics = Object.assign(adapter({ analyticsType }), {
29
+ let eightPodAnalytics = Object.assign(adapter({url: trackerUrl, analyticsType}), {
32
30
  /**
33
31
  * Execute on bid won - setup basic settings, save context about EightPod's bid. We will send it with our events later
34
32
  */
@@ -36,45 +34,47 @@ let eightPodAnalytics = Object.assign(adapter({ analyticsType }), {
36
34
  switch (eventType) {
37
35
  case BID_WON:
38
36
  if (args.bidder === 'eightPod') {
37
+ context[args.adUnitCode] = makeContext(args);
38
+
39
39
  eightPodAnalytics.setupPage(args);
40
- context = makeContext(args);
41
40
  break;
42
41
  }
43
42
  }
44
43
  },
45
44
 
46
45
  /**
47
- * Execute on bid won - subscribe on events from adUnit
46
+ * Execute on bid won upload events from local storage
48
47
  */
49
48
  setupPage() {
50
- eightPodAnalytics.eventSubscribe();
51
- queue = getEventFromLocalStorage();
49
+ queue = this.getEventFromLocalStorage();
52
50
  },
51
+
53
52
  /**
54
53
  * Subscribe on internal ad unit tracking events
55
54
  */
56
55
  eventSubscribe() {
57
56
  window.addEventListener('message', async (event) => {
58
- const data = event?.data;
57
+ const data = event.data;
59
58
 
60
- if (!data?.detail?.name) {
61
- return;
62
- }
59
+ const frameElement = event.source?.frameElement;
60
+ const parentElement = frameElement?.parentElement;
61
+ const adUnitCode = parentElement?.id;
63
62
 
64
- trackEvent(data);
63
+ trackEvent(data, adUnitCode);
65
64
  });
66
65
 
67
- // Send queue of event every 10 seconds
68
- if (!interval) {
69
- interval = setInterval(sendEvents, 10_000);
70
- }
66
+ setInterval(sendEvents, 10_000);
71
67
  },
72
68
  resetQueue() {
73
69
  queue = [];
74
70
  },
75
71
  getContext() {
76
72
  return context;
77
- }
73
+ },
74
+ resetContext() {
75
+ context = {};
76
+ },
77
+ getEventFromLocalStorage,
78
78
  });
79
79
 
80
80
  /**
@@ -84,8 +84,8 @@ function makeContext(args) {
84
84
  const params = args?.params?.[0];
85
85
  return {
86
86
  bidId: args.seatBidId,
87
- variantId: args.creativeId || 'variantId',
88
- campaignId: 'campaignId',
87
+ variantId: args.creativeId || '',
88
+ campaignId: args.cid || '',
89
89
  publisherId: params.publisherId,
90
90
  placementId: params.placementId,
91
91
  };
@@ -94,12 +94,13 @@ function makeContext(args) {
94
94
  /**
95
95
  * Create event, add context and push it to queue
96
96
  */
97
- export function trackEvent(event) {
97
+ export function trackEvent(event, adUnitCode) {
98
98
  if (!event.detail) {
99
99
  return;
100
100
  }
101
+
101
102
  const fullEvent = {
102
- context: eightPodAnalytics.getContext(),
103
+ context: eightPodAnalytics.getContext()[adUnitCode],
103
104
  eventType: event.detail.type,
104
105
  eventClass: 'adunit',
105
106
  timestamp: new Date().getTime(),
@@ -107,6 +108,7 @@ export function trackEvent(event) {
107
108
  payload: event.detail.payload
108
109
  };
109
110
 
111
+ logMessage(fullEvent);
110
112
  addEvent(fullEvent);
111
113
  }
112
114
 
@@ -158,7 +160,7 @@ function sendEvents() {
158
160
  * Send event to our custom tracking server
159
161
  */
160
162
  function sendEventsApi(eventList, callbacks) {
161
- ajax(trackerUrl, callbacks, JSON.stringify(eventList));
163
+ ajax(trackerUrl, callbacks, JSON.stringify(eventList), {keepalive: true});
162
164
  }
163
165
 
164
166
  /**
@@ -173,21 +175,13 @@ eightPodAnalytics.originEnableAnalytics = eightPodAnalytics.enableAnalytics;
173
175
  eightPodAnalytics.eventsStorage = [];
174
176
 
175
177
  // override enableAnalytics so we can get access to the config passed in from the page
178
+ // Subscribe on events from adUnit
176
179
  eightPodAnalytics.enableAnalytics = function (config) {
177
180
  eightPodAnalytics.originEnableAnalytics(config);
178
181
  logInfo(MODULE, 'init', config);
182
+ eightPodAnalytics.eventSubscribe();
179
183
  };
180
184
 
181
- eightPodAnalytics.disableAnalytics = (function (orig) {
182
- return function (...args) {
183
- if (interval) {
184
- clearInterval(interval);
185
- interval = null;
186
- }
187
- return orig.apply(this, args);
188
- };
189
- })(eightPodAnalytics.disableAnalytics);
190
-
191
185
  /**
192
186
  * Register Analytics Adapter
193
187
  */
@@ -4,7 +4,7 @@ import { BANNER } from '../src/mediaTypes.js'
4
4
  import * as utils from '../src/utils.js'
5
5
 
6
6
  export const BIDDER_CODE = 'eightPod'
7
- const url = 'https://demo.8pod.com/bidder/rtb/eightpod_exchange/bid?trace=true';
7
+ const url = 'https://demo.8pod.com/bidder/rtb/eightpod_exchange/bid';
8
8
 
9
9
  export const spec = {
10
10
  code: BIDDER_CODE,
@@ -49,8 +49,9 @@ function isBidRequestValid(bidRequest) {
49
49
  function buildRequests(bids, bidderRequest) {
50
50
  let bannerBids = bids.filter((bid) => isBannerBid(bid))
51
51
  let requests = bannerBids.length
52
- ? [createRequest(bannerBids, bidderRequest, BANNER)]
52
+ ? createRequest(bannerBids, bidderRequest, BANNER)
53
53
  : []
54
+
54
55
  return requests
55
56
  }
56
57
 
@@ -61,8 +62,10 @@ function bidResponse(buildBidResponse, bid, context) {
61
62
 
62
63
  bidResponse.height = context?.imp?.banner?.format?.[0].h;
63
64
  bidResponse.width = context?.imp?.banner?.format?.[0].w;
65
+ bidResponse.cid = bid.cid;
64
66
 
65
67
  bidResponse.burl = replacePriceInUrl(bid.burl, bidResponse.originalCpm || bidResponse.cpm);
68
+
66
69
  return bidResponse;
67
70
  }
68
71
 
@@ -119,64 +122,75 @@ export function getPageKeywords(win = window) {
119
122
  }
120
123
 
121
124
  function createRequest(bidRequests, bidderRequest, mediaType) {
122
- const data = converter.toORTB({
123
- bidRequests,
124
- bidderRequest,
125
- context: { mediaType },
126
- });
127
-
128
- data.adSlotPositionOnScreen = 'ABOVE_THE_FOLD';
129
- data.at = 1;
130
-
131
- const params = getBidderParams(bidRequests);
132
-
133
- data.device = {
134
- ...data.device,
135
- model: parseUserAgent().device,
136
- os: parseUserAgent().platform,
137
- osv: parseUserAgent().version,
138
- geo: {
139
- country: params.country || 'GRB'
140
- },
141
- language: params.language || data.device.language,
142
- }
143
- data.site = {
144
- ...data.site,
145
- keywords: getPageKeywords(window),
146
- }
147
- data.imp = [
148
- {
149
- ...data.imp?.[0],
150
- pmp: params.dealId
151
- ? {
152
- ...data.pmp,
153
- deals: [
154
- {
155
- bidfloor: 0.5,
156
- at: 2,
157
- id: params.dealId,
158
- },
159
- ],
160
- private_auction: 1,
161
- }
162
- : data.pmp,
125
+ const requests = bidRequests.map((bidRequest) => {
126
+ const data = converter.toORTB({
127
+ bidRequests: [bidRequest],
128
+ bidderRequest,
129
+ context: { mediaType },
130
+ });
131
+
132
+ data.adSlotPositionOnScreen = 'ABOVE_THE_FOLD';
133
+ data.at = 1;
134
+
135
+ const userId =
136
+ utils.deepAccess(bidRequest, 'userId.unifiedId.id') ||
137
+ utils.deepAccess(bidRequest, 'userId.id5id.uid') ||
138
+ utils.deepAccess(bidRequest, 'userId.idl_env');
139
+
140
+ const params = getBidderParams(bidRequest);
141
+ data.device = {
142
+ ...data.device,
143
+ devicetype: 4,
144
+ geo: {
145
+ country: params.country || 'GRB'
146
+ },
147
+ language: params.language || data.device.language,
148
+ }
149
+ data.site = {
150
+ ...data.site,
151
+ keywords: getPageKeywords(window),
152
+ publisher: {
153
+ id: params.publisherId
154
+ }
155
+ }
156
+ data.imp = [
157
+ {
158
+ ...data.imp?.[0],
159
+ secure: 1,
160
+ pmp: params.dealId
161
+ ? {
162
+ ...data.pmp,
163
+ deals: [
164
+ {
165
+ id: params.dealId,
166
+ },
167
+ ],
168
+ private_auction: 1,
169
+ }
170
+ : data.pmp,
171
+ }
172
+ ]
173
+ data.adSlotPlacementId = params.placementId;
174
+
175
+ if (userId) {
176
+ data.user = {
177
+ id: userId
178
+ }
163
179
  }
164
- ]
165
- data.adSlotPlacementId = params.placementId;
166
180
 
167
- const req = {
168
- method: 'POST',
169
- url,
170
- data
171
- }
172
- return req
173
- }
181
+ const req = {
182
+ method: 'POST',
183
+ url: url && params.trace ? url + '?trace=true' : url,
184
+ options: { withCredentials: false },
185
+ data
186
+ }
187
+ return req
188
+ })
174
189
 
175
- function getBidderParams(bidRequests) {
176
- const bid = bidRequests.find(bid => {
177
- return bid.bidder === BIDDER_CODE
178
- });
190
+ return requests;
191
+ }
179
192
 
193
+ function getBidderParams(bid) {
180
194
  return bid?.params ? bid.params : undefined;
181
195
  }
182
196
 
@@ -189,5 +203,47 @@ function isBannerBid(bid) {
189
203
  }
190
204
 
191
205
  function interpretResponse(resp, req) {
192
- return converter.fromORTB({ request: req.data, response: resp.body })
206
+ const impressionId = resp.body.seatbid[0].bid[0].impid;
207
+ const bidResponses = converter.fromORTB({ request: req.data, response: resp.body });
208
+ const ad = bidResponses[0].ad;
209
+ const trackingTag = `<script src="https://cdn.doubleverify.com/dvtp_src.js?ctx=818052&cmp=APAC_Cert_20&sid=se_a551&plc=240411845&adsrv=0&btreg=ad-unit-container&auevent=${impressionId}&btadsrv=&crt=01&tagtype=&dvtagver=6.1.src" type="text/javascript"></script>
210
+ <script type="text/javascript">
211
+ (function() {
212
+ /** CONFIGURATION START **/
213
+ var _sf_async_config = window._sf_async_config = (window._sf_async_config || {});
214
+ _sf_async_config.uid = 67171;
215
+ _sf_async_config.domain = 'demo.8pod.com';
216
+ _sf_async_config.flickerControl = false;
217
+ _sf_async_config.useCanonical = true;
218
+ _sf_async_config.useCanonicalDomain = true;
219
+ _sf_async_config.sections = '';
220
+ _sf_async_config.authors = '';
221
+ /** CONFIGURATION END **/
222
+ function loadChartbeat() {
223
+ var e = document.createElement('script');
224
+ var n = document.getElementsByTagName('script')[0];
225
+ e.type = 'text/javascript';
226
+ e.async = true;
227
+ e.src = '//static.chartbeat.com/js/chartbeat.js';
228
+ n.parentNode.insertBefore(e, n);
229
+ }
230
+ loadChartbeat();
231
+ })();
232
+ </script>
233
+ <script async src="//static.chartbeat.com/js/chartbeat_mab.js"></script>
234
+
235
+ <script type="text/javascript">
236
+ var utag_data = {
237
+ }
238
+ </script>
239
+ <script type="text/javascript">
240
+ (function(a,b,c,d){
241
+ a='https://tags.tiqcdn.com/utag/sales-richard-coghlan/8pod/prod/utag.js';
242
+ b=document;c='script';d=b.createElement(c);d.src=a;d.type='text/java'+c;d.async=true;
243
+ a=b.getElementsByTagName(c)[0];a.parentNode.insertBefore(d,a);
244
+ })();
245
+ </script>`
246
+
247
+ bidResponses[0].ad = ad.replace('</head>', trackingTag + '</head>');
248
+ return bidResponses;
193
249
  }