prebid.js 7.22.0 → 7.24.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 (314) 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/admaticBidAdapter.js +1 -0
  7. package/dist/adrelevantisBidAdapter.js +1 -1
  8. package/dist/adtrgtmeBidAdapter.js +1 -1
  9. package/dist/adxcgBidAdapter.js +1 -1
  10. package/dist/adyoulikeBidAdapter.js +1 -1
  11. package/dist/ajaBidAdapter.js +1 -1
  12. package/dist/amxBidAdapter.js +1 -1
  13. package/dist/amxIdSystem.js +1 -1
  14. package/dist/analyticsAdapter.js +1 -1
  15. package/dist/appierAnalyticsAdapter.js +1 -1
  16. package/dist/appnexusBidAdapter.js +1 -1
  17. package/dist/asoBidAdapter.js +1 -1
  18. package/dist/audiencerunBidAdapter.js +1 -1
  19. package/dist/axonixBidAdapter.js +1 -1
  20. package/dist/bidViewability.js +1 -1
  21. package/dist/bidViewabilityIO.js +1 -1
  22. package/dist/bidglassBidAdapter.js +1 -1
  23. package/dist/big-richmediaBidAdapter.js +1 -1
  24. package/dist/bluebillywigBidAdapter.js +1 -1
  25. package/dist/bridgewellBidAdapter.js +1 -1
  26. package/dist/brightMountainMediaBidAdapter.js +1 -1
  27. package/dist/browsiRtdProvider.js +1 -1
  28. package/dist/carodaBidAdapter.js +1 -1
  29. package/dist/chtnwBidAdapter.js +1 -0
  30. package/dist/cleanioRtdProvider.js +1 -1
  31. package/dist/concertBidAdapter.js +1 -1
  32. package/dist/connectIdSystem.js +1 -1
  33. package/dist/connectadBidAdapter.js +1 -1
  34. package/dist/consentManagement.js +1 -1
  35. package/dist/consentManagementUsp.js +1 -1
  36. package/dist/consumableBidAdapter.js +1 -1
  37. package/dist/conversantBidAdapter.js +1 -1
  38. package/dist/craftBidAdapter.js +1 -1
  39. package/dist/criteoBidAdapter.js +1 -1
  40. package/dist/currency.js +1 -1
  41. package/dist/dependencies.json +19 -0
  42. package/dist/dfpAdServerVideo.js +1 -1
  43. package/dist/dgkeywordRtdProvider.js +1 -1
  44. package/dist/dspxBidAdapter.js +1 -1
  45. package/dist/eplanningBidAdapter.js +1 -1
  46. package/dist/finativeBidAdapter.js +1 -1
  47. package/dist/gdprEnforcement.js +1 -1
  48. package/dist/glimpseBidAdapter.js +1 -1
  49. package/dist/gmosspBidAdapter.js +1 -1
  50. package/dist/goldbachBidAdapter.js +1 -1
  51. package/dist/googleAnalyticsAdapter.js +1 -1
  52. package/dist/gridBidAdapter.js +1 -1
  53. package/dist/gridNMBidAdapter.js +1 -1
  54. package/dist/growthCodeIdSystem.js +1 -1
  55. package/dist/gumgumBidAdapter.js +1 -1
  56. package/dist/h12mediaBidAdapter.js +1 -1
  57. package/dist/id5AnalyticsAdapter.js +1 -1
  58. package/dist/id5IdSystem.js +1 -1
  59. package/dist/impactifyBidAdapter.js +1 -1
  60. package/dist/improvedigitalBidAdapter.js +1 -1
  61. package/dist/inmarBidAdapter.js +1 -1
  62. package/dist/insticatorBidAdapter.js +1 -1
  63. package/dist/instreamTracking.js +1 -1
  64. package/dist/ixBidAdapter.js +1 -1
  65. package/dist/jixieBidAdapter.js +1 -1
  66. package/dist/justpremiumBidAdapter.js +1 -1
  67. package/dist/jwplayerVideoProvider.js +1 -0
  68. package/dist/kargoBidAdapter.js +1 -1
  69. package/dist/konduitAnalyticsAdapter.js +1 -1
  70. package/dist/kueezBidAdapter.js +1 -1
  71. package/dist/kueezRtbBidAdapter.js +1 -0
  72. package/dist/lassoBidAdapter.js +1 -1
  73. package/dist/lifestreetBidAdapter.js +1 -1
  74. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  75. package/dist/logicadBidAdapter.js +1 -1
  76. package/dist/loglyliftBidAdapter.js +1 -1
  77. package/dist/magniteAnalyticsAdapter.js +1 -1
  78. package/dist/malltvAnalyticsAdapter.js +1 -1
  79. package/dist/marsmediaBidAdapter.js +1 -1
  80. package/dist/mediafuseBidAdapter.js +1 -1
  81. package/dist/mediakeysBidAdapter.js +1 -1
  82. package/dist/mediasquareBidAdapter.js +1 -1
  83. package/dist/mgidBidAdapter.js +1 -1
  84. package/dist/mgidRtdProvider.js +1 -0
  85. package/dist/minutemediaBidAdapter.js +1 -1
  86. package/dist/multibid.js +1 -1
  87. package/dist/not-for-prod/prebid.js +153 -141
  88. package/dist/oguryBidAdapter.js +1 -1
  89. package/dist/onetagBidAdapter.js +1 -1
  90. package/dist/ooloAnalyticsAdapter.js +1 -1
  91. package/dist/openxOrtbBidAdapter.js +1 -1
  92. package/dist/ortbConverter.js +1 -0
  93. package/dist/outbrainBidAdapter.js +1 -1
  94. package/dist/oxxionRtdProvider.js +1 -0
  95. package/dist/parrableIdSystem.js +1 -1
  96. package/dist/pbsExtensions.js +1 -0
  97. package/dist/permutiveRtdProvider.js +1 -1
  98. package/dist/pixfutureBidAdapter.js +1 -1
  99. package/dist/prebid-core.js +1 -1
  100. package/dist/prebidServerBidAdapter.js +1 -1
  101. package/dist/priceFloors.js +1 -1
  102. package/dist/pubCommonId.js +1 -1
  103. package/dist/publinkIdSystem.js +1 -1
  104. package/dist/pubmaticBidAdapter.js +1 -1
  105. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  106. package/dist/pxyzBidAdapter.js +1 -1
  107. package/dist/quantcastBidAdapter.js +1 -1
  108. package/dist/readpeakBidAdapter.js +1 -1
  109. package/dist/relaidoBidAdapter.js +1 -1
  110. package/dist/rhythmoneBidAdapter.js +1 -1
  111. package/dist/riseBidAdapter.js +1 -1
  112. package/dist/rtdModule.js +1 -1
  113. package/dist/rubiconAnalyticsAdapter.js +1 -1
  114. package/dist/rubiconBidAdapter.js +1 -1
  115. package/dist/schain.js +1 -1
  116. package/dist/seedingAllianceBidAdapter.js +1 -1
  117. package/dist/seedtagBidAdapter.js +1 -1
  118. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  119. package/dist/sharethroughBidAdapter.js +1 -1
  120. package/dist/shinezBidAdapter.js +1 -1
  121. package/dist/smaatoBidAdapter.js +1 -1
  122. package/dist/smartadserverBidAdapter.js +1 -1
  123. package/dist/smartxBidAdapter.js +1 -1
  124. package/dist/smilewantedBidAdapter.js +1 -1
  125. package/dist/sonobiBidAdapter.js +1 -1
  126. package/dist/sovrnAnalyticsAdapter.js +1 -1
  127. package/dist/sovrnBidAdapter.js +1 -1
  128. package/dist/spotxBidAdapter.js +1 -1
  129. package/dist/sspBCBidAdapter.js +1 -1
  130. package/dist/sublimeBidAdapter.js +1 -1
  131. package/dist/synacormediaBidAdapter.js +1 -1
  132. package/dist/targetVideoBidAdapter.js +1 -1
  133. package/dist/teadsBidAdapter.js +1 -1
  134. package/dist/teadsIdSystem.js +1 -1
  135. package/dist/trionBidAdapter.js +1 -1
  136. package/dist/tripleliftBidAdapter.js +1 -1
  137. package/dist/ttdBidAdapter.js +1 -1
  138. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  139. package/dist/underdogmediaBidAdapter.js +1 -1
  140. package/dist/undertoneBidAdapter.js +1 -1
  141. package/dist/userId.js +1 -1
  142. package/dist/vidazooBidAdapter.js +1 -1
  143. package/dist/video.js +1 -0
  144. package/dist/videoModule.js +1 -0
  145. package/dist/videobyteBidAdapter.js +1 -1
  146. package/dist/videojsVideoProvider.js +1 -0
  147. package/dist/visxBidAdapter.js +1 -1
  148. package/dist/vuukleBidAdapter.js +1 -1
  149. package/dist/widespaceBidAdapter.js +1 -1
  150. package/dist/winrBidAdapter.js +1 -1
  151. package/dist/yahoosspBidAdapter.js +1 -1
  152. package/dist/yieldmoBidAdapter.js +1 -1
  153. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  154. package/integrationExamples/gpt/mgidRtdProvider_example.html +143 -0
  155. package/integrationExamples/videoModule/jwplayer/bidMarkedAsUsed.html +98 -0
  156. package/integrationExamples/videoModule/jwplayer/bidRequestScheduling.html +89 -0
  157. package/integrationExamples/videoModule/jwplayer/eventListeners.html +244 -0
  158. package/integrationExamples/videoModule/jwplayer/gamAdServerMediation.html +122 -0
  159. package/integrationExamples/videoModule/jwplayer/mediaMetadata.html +80 -0
  160. package/integrationExamples/videoModule/jwplayer/playlist.html +122 -0
  161. package/integrationExamples/videoModule/videojs/bidMarkedAsUsed.html +126 -0
  162. package/integrationExamples/videoModule/videojs/bidRequestScheduling.html +132 -0
  163. package/integrationExamples/videoModule/videojs/eventListeners.html +238 -0
  164. package/integrationExamples/videoModule/videojs/gamAdServerMediation.html +138 -0
  165. package/integrationExamples/videoModule/videojs/mediaMetadata.html +103 -0
  166. package/integrationExamples/videoModule/videojs/playlist.html +151 -0
  167. package/libraries/ortbConverter/README.md +378 -0
  168. package/libraries/ortbConverter/converter.js +135 -0
  169. package/libraries/ortbConverter/lib/composer.js +43 -0
  170. package/libraries/ortbConverter/lib/mergeProcessors.js +9 -0
  171. package/libraries/ortbConverter/lib/sizes.js +14 -0
  172. package/libraries/ortbConverter/processors/banner.js +40 -0
  173. package/libraries/ortbConverter/processors/default.js +167 -0
  174. package/libraries/ortbConverter/processors/mediaType.js +21 -0
  175. package/libraries/ortbConverter/processors/native.js +37 -0
  176. package/libraries/ortbConverter/processors/video.js +66 -0
  177. package/libraries/pbsExtensions/pbsExtensions.js +12 -0
  178. package/libraries/pbsExtensions/processors/aliases.js +17 -0
  179. package/libraries/pbsExtensions/processors/mediaType.js +23 -0
  180. package/libraries/pbsExtensions/processors/params.js +22 -0
  181. package/libraries/pbsExtensions/processors/pbs.js +99 -0
  182. package/libraries/pbsExtensions/processors/requestExtPrebid.js +30 -0
  183. package/libraries/pbsExtensions/processors/video.js +23 -0
  184. package/libraries/video/constants/enums.js +5 -0
  185. package/libraries/video/constants/events.js +97 -0
  186. package/libraries/video/constants/ortb.js +169 -0
  187. package/libraries/video/constants/vendorCodes.js +6 -0
  188. package/libraries/video/shared/eventHandler.js +18 -0
  189. package/libraries/video/shared/parentModule.js +82 -0
  190. package/libraries/video/shared/state.js +47 -0
  191. package/libraries/video/shared/vastXmlBuilder.js +77 -0
  192. package/libraries/video/shared/vastXmlEditor.js +115 -0
  193. package/modules/.submodules.json +7 -1
  194. package/modules/aaxBlockmeterRtdProvider.js +59 -0
  195. package/modules/aaxBlockmeterRtdProvider.md +48 -0
  196. package/modules/admaticBidAdapter.js +147 -0
  197. package/modules/admaticBidAdapter.md +48 -0
  198. package/modules/amxBidAdapter.js +1 -0
  199. package/modules/appnexusBidAdapter.js +38 -1
  200. package/modules/chtnwBidAdapter.js +110 -0
  201. package/modules/chtnwBidAdapter.md +31 -0
  202. package/modules/concertBidAdapter.js +44 -2
  203. package/modules/connectIdSystem.js +36 -23
  204. package/modules/connectIdSystem.md +3 -2
  205. package/modules/consentManagement.js +22 -1
  206. package/modules/consentManagementUsp.js +29 -7
  207. package/modules/criteoBidAdapter.js +25 -5
  208. package/modules/currency.js +9 -0
  209. package/modules/dgkeywordRtdProvider.js +3 -3
  210. package/modules/gridNMBidAdapter.js +10 -14
  211. package/modules/growthCodeIdSystem.js +9 -5
  212. package/modules/gumgumBidAdapter.js +4 -0
  213. package/modules/improvedigitalBidAdapter.js +191 -470
  214. package/modules/ixBidAdapter.js +54 -71
  215. package/modules/jwplayerVideoProvider.js +929 -0
  216. package/modules/jwplayerVideoProvider.md +25 -0
  217. package/modules/kargoBidAdapter.js +1 -1
  218. package/modules/kueezRtbBidAdapter.js +278 -0
  219. package/modules/kueezRtbBidAdapter.md +35 -0
  220. package/modules/magniteAnalyticsAdapter.js +6 -1
  221. package/modules/mgidRtdProvider.js +190 -0
  222. package/modules/mgidRtdProvider.md +51 -0
  223. package/modules/multibid/index.js +12 -0
  224. package/modules/openxOrtbBidAdapter.js +120 -275
  225. package/modules/oxxionRtdProvider.js +119 -0
  226. package/modules/oxxionRtdProvider.md +48 -0
  227. package/modules/permutiveRtdProvider.js +2 -1
  228. package/modules/permutiveRtdProvider.md +36 -1
  229. package/modules/prebidServerBidAdapter/index.js +19 -716
  230. package/modules/prebidServerBidAdapter/ortbConverter.js +274 -0
  231. package/modules/priceFloors.js +73 -1
  232. package/modules/pubmaticBidAdapter.js +21 -29
  233. package/modules/rtdModule/index.js +22 -1
  234. package/modules/schain.js +24 -1
  235. package/modules/spotxBidAdapter.js +16 -15
  236. package/modules/synacormediaBidAdapter.js +1 -1
  237. package/modules/teadsIdSystem.js +5 -0
  238. package/modules/tripleliftBidAdapter.js +1 -1
  239. package/modules/userId/eids.js +3 -10
  240. package/modules/userId/index.js +64 -6
  241. package/modules/videoModule/addingSubmodule.md +521 -0
  242. package/modules/videoModule/coreVideo.js +234 -0
  243. package/modules/videoModule/gamAdServerSubmodule.js +27 -0
  244. package/modules/videoModule/index.js +244 -0
  245. package/modules/videoModule/videoImpressionVerifier.js +206 -0
  246. package/modules/videojsVideoProvider.js +854 -0
  247. package/modules/videojsVideoProvider.md +17 -0
  248. package/package.json +12 -8
  249. package/src/adRendering.js +1 -1
  250. package/src/adapterManager.js +56 -7
  251. package/src/adloader.js +3 -1
  252. package/src/auction.js +6 -1
  253. package/src/events.js +5 -1
  254. package/src/pbjsORTB.js +35 -0
  255. package/src/prebid.js +137 -112
  256. package/src/targeting.js +10 -2
  257. package/src/utils/currency.js +16 -0
  258. package/src/utils.js +21 -0
  259. package/test/spec/auctionmanager_spec.js +15 -0
  260. package/test/spec/modules/aaxBlockmeter_spec.js +58 -0
  261. package/test/spec/modules/admaticBidAdapter_spec.js +46 -0
  262. package/test/spec/modules/chtnwBidAdapter_spec.js +105 -0
  263. package/test/spec/modules/concertBidAdapter_spec.js +56 -0
  264. package/test/spec/modules/connectIdSystem_spec.js +175 -5
  265. package/test/spec/modules/consentManagementUsp_spec.js +64 -18
  266. package/test/spec/modules/criteoBidAdapter_spec.js +28 -0
  267. package/test/spec/modules/dgkeywordRtdProvider_spec.js +3 -3
  268. package/test/spec/modules/eids_spec.js +10 -7
  269. package/test/spec/modules/ftrackIdSystem_spec.js +34 -22
  270. package/test/spec/modules/gumgumBidAdapter_spec.js +15 -0
  271. package/test/spec/modules/improvedigitalBidAdapter_spec.js +231 -211
  272. package/test/spec/modules/ixBidAdapter_spec.js +412 -350
  273. package/test/spec/modules/kueezRtbBidAdapter_spec.js +396 -0
  274. package/test/spec/modules/magniteAnalyticsAdapter_spec.js +26 -0
  275. package/test/spec/modules/mgidRtdProvider_spec.js +366 -0
  276. package/test/spec/modules/openxOrtbBidAdapter_spec.js +77 -49
  277. package/test/spec/modules/oxxionRtdProvider_spec.js +142 -0
  278. package/test/spec/modules/permutiveRtdProvider_spec.js +64 -5
  279. package/test/spec/modules/prebidServerBidAdapter_spec.js +139 -137
  280. package/test/spec/modules/realTimeDataModule_spec.js +65 -0
  281. package/test/spec/modules/tripleliftBidAdapter_spec.js +14 -0
  282. package/test/spec/modules/userId_spec.js +67 -1
  283. package/test/spec/modules/videoModule/coreVideo_spec.js +98 -0
  284. package/test/spec/modules/videoModule/pbVideo_spec.js +362 -0
  285. package/test/spec/modules/videoModule/shared/parentModule_spec.js +73 -0
  286. package/test/spec/modules/videoModule/shared/state_spec.js +26 -0
  287. package/test/spec/modules/videoModule/shared/vastXmlBuilder_spec.js +103 -0
  288. package/test/spec/modules/videoModule/shared/vastXmlEditor_spec.js +209 -0
  289. package/test/spec/modules/videoModule/submodules/jwplayerVideoProvider_spec.js +846 -0
  290. package/test/spec/modules/videoModule/submodules/videojsVideoProvider_spec.js +391 -0
  291. package/test/spec/modules/videoModule/videoImpressionVerifier_spec.js +112 -0
  292. package/test/spec/ortbConverter/banner_spec.js +203 -0
  293. package/test/spec/ortbConverter/composer_spec.js +69 -0
  294. package/test/spec/ortbConverter/converter_spec.js +283 -0
  295. package/test/spec/ortbConverter/currency_spec.js +40 -0
  296. package/test/spec/ortbConverter/default_processors_spec.js +61 -0
  297. package/test/spec/ortbConverter/gdpr_spec.js +38 -0
  298. package/test/spec/ortbConverter/mediaTypes_spec.js +67 -0
  299. package/test/spec/ortbConverter/mergeProcessors_spec.js +59 -0
  300. package/test/spec/ortbConverter/multibid_spec.js +35 -0
  301. package/test/spec/ortbConverter/native_spec.js +95 -0
  302. package/test/spec/ortbConverter/pbjsORTB_spec.js +67 -0
  303. package/test/spec/ortbConverter/pbsExtensions/aliases_spec.js +57 -0
  304. package/test/spec/ortbConverter/pbsExtensions/params_spec.js +96 -0
  305. package/test/spec/ortbConverter/pbsExtensions/video_spec.js +52 -0
  306. package/test/spec/ortbConverter/priceFloors_spec.js +143 -0
  307. package/test/spec/ortbConverter/schain_spec.js +33 -0
  308. package/test/spec/ortbConverter/userId_spec.js +21 -0
  309. package/test/spec/ortbConverter/usp_spec.js +15 -0
  310. package/test/spec/ortbConverter/video_spec.js +189 -0
  311. package/test/spec/unit/core/adapterManager_spec.js +102 -0
  312. package/test/spec/unit/core/targeting_spec.js +34 -0
  313. package/test/spec/unit/pbjs_api_spec.js +124 -45
  314. package/test/spec/utils_spec.js +45 -1
@@ -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
+
@@ -238,7 +238,8 @@ function getDefaultBidderFn (bidder) {
238
238
  deepSetValue(bid, 'params.visitor.p_standard', data.ac)
239
239
  }
240
240
  if (data.rubicon && data.rubicon.length) {
241
- deepSetValue(bid, 'params.visitor.permutive', data.rubicon)
241
+ const rubiconCohorts = deepAccess(bid, 'params.video') ? data.rubicon.map(String) : data.rubicon
242
+ deepSetValue(bid, 'params.visitor.permutive', rubiconCohorts)
242
243
  }
243
244
 
244
245
  return bid
@@ -45,17 +45,52 @@ as well as enabling settings for specific use cases mentioned above (e.g. acbidd
45
45
  | params.acBidders | String[] | An array of bidders which should receive AC cohorts. | `[]` |
46
46
  | params.maxSegs | Integer | Maximum number of cohorts to be included in either the `permutive` or `p_standard` key-value. | `500` |
47
47
  | params.transformations | Object[] | An array of configurations for ORTB2 user data transformations | |
48
+ | params.overwrites | Object | An object specifying functions for custom targeting logic for bidders. | - |
48
49
 
49
50
  ##### The `transformations` parameter
50
51
 
51
52
  This array contains configurations for transformations we'll apply to the Permutive object in the ORTB2 `user.data` array. The results of these transformations will be appended to the `user.data` array that's attached to ORTB2 bid requests.
52
53
 
53
- ##### Supported transformations
54
+ ###### Supported transformations
54
55
 
55
56
  | Name | ID | Config structure | Description |
56
57
  |----------------|-----|---------------------------------------------------|--------------------------------------------------------------------------------------|
57
58
  | IAB taxonomies | iab | { segtax: number, iabIds: Object<number, number>} | Transform segment IDs from Permutive to IAB (note: alpha version, subject to change) |
58
59
 
60
+ ##### The `overwrites` parameter
61
+
62
+ The keys for this object should match a bidder (e.g. `rubicon`), which then can define a function to overwrite the customer targeting logic.
63
+
64
+ ```javascript
65
+ {
66
+ params: {
67
+ overwrites: {
68
+ rubicon: function customTargeting(bid, data, acEnabled, utils, defaultFn) {
69
+ if (defaultFn) {
70
+ bid = defaultFn(bid, data, acEnabled)
71
+ }
72
+ if (data.gam && data.gam.length) {
73
+ utils.deepSetValue(bid, 'params.visitor.permutive', data.gam)
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
79
+ ```
80
+
81
+ ###### `customTargeting` function parameters
82
+
83
+ | Name | Description |
84
+ |--------------|--------------------------------------------------------------------------------|
85
+ | `bid` | The bid request object. |
86
+ | `data` | Permutive's targeting data read from localStorage. |
87
+ | `acEnabled` | Boolean stating whether Audience Connect is enabled via `acBidders`. |
88
+ | `utils` | An object of helpful utilities. `(deepSetValue, deepAccess, isFn, mergeDeep)`. |
89
+ | `defaultFn` | The default targeting function. |
90
+
91
+
92
+
93
+
59
94
  #### Context
60
95
 
61
96
  Permutive is not listed as a TCF vendor as all data collection is on behalf of the publisher and based on consent the publisher has received from the user.