prebid.js 7.22.0 → 7.23.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 (273) hide show
  1. package/dist/33acrossBidAdapter.js +1 -1
  2. package/dist/aaxBlockmeterRtdProvider.js +1 -0
  3. package/dist/adagioBidAdapter.js +1 -1
  4. package/dist/adbookpspBidAdapter.js +1 -1
  5. package/dist/adgenerationBidAdapter.js +1 -1
  6. package/dist/adrelevantisBidAdapter.js +1 -1
  7. package/dist/adtrgtmeBidAdapter.js +1 -1
  8. package/dist/adxcgBidAdapter.js +1 -1
  9. package/dist/ajaBidAdapter.js +1 -1
  10. package/dist/amxBidAdapter.js +1 -1
  11. package/dist/amxIdSystem.js +1 -1
  12. package/dist/analyticsAdapter.js +1 -1
  13. package/dist/appierAnalyticsAdapter.js +1 -1
  14. package/dist/appnexusBidAdapter.js +1 -1
  15. package/dist/asoBidAdapter.js +1 -1
  16. package/dist/axonixBidAdapter.js +1 -1
  17. package/dist/bidViewability.js +1 -1
  18. package/dist/bidViewabilityIO.js +1 -1
  19. package/dist/bidglassBidAdapter.js +1 -1
  20. package/dist/big-richmediaBidAdapter.js +1 -1
  21. package/dist/bridgewellBidAdapter.js +1 -1
  22. package/dist/brightMountainMediaBidAdapter.js +1 -1
  23. package/dist/browsiRtdProvider.js +1 -1
  24. package/dist/carodaBidAdapter.js +1 -1
  25. package/dist/chtnwBidAdapter.js +1 -0
  26. package/dist/cleanioRtdProvider.js +1 -1
  27. package/dist/concertBidAdapter.js +1 -1
  28. package/dist/connectadBidAdapter.js +1 -1
  29. package/dist/consentManagement.js +1 -1
  30. package/dist/consentManagementUsp.js +1 -1
  31. package/dist/consumableBidAdapter.js +1 -1
  32. package/dist/conversantBidAdapter.js +1 -1
  33. package/dist/craftBidAdapter.js +1 -1
  34. package/dist/criteoBidAdapter.js +1 -1
  35. package/dist/currency.js +1 -1
  36. package/dist/dependencies.json +19 -0
  37. package/dist/dfpAdServerVideo.js +1 -1
  38. package/dist/dgkeywordRtdProvider.js +1 -1
  39. package/dist/dspxBidAdapter.js +1 -1
  40. package/dist/eplanningBidAdapter.js +1 -1
  41. package/dist/finativeBidAdapter.js +1 -1
  42. package/dist/gdprEnforcement.js +1 -1
  43. package/dist/glimpseBidAdapter.js +1 -1
  44. package/dist/gmosspBidAdapter.js +1 -1
  45. package/dist/goldbachBidAdapter.js +1 -1
  46. package/dist/googleAnalyticsAdapter.js +1 -1
  47. package/dist/gridBidAdapter.js +1 -1
  48. package/dist/gridNMBidAdapter.js +1 -1
  49. package/dist/gumgumBidAdapter.js +1 -1
  50. package/dist/h12mediaBidAdapter.js +1 -1
  51. package/dist/id5AnalyticsAdapter.js +1 -1
  52. package/dist/id5IdSystem.js +1 -1
  53. package/dist/improvedigitalBidAdapter.js +1 -1
  54. package/dist/inmarBidAdapter.js +1 -1
  55. package/dist/insticatorBidAdapter.js +1 -1
  56. package/dist/instreamTracking.js +1 -1
  57. package/dist/ixBidAdapter.js +1 -1
  58. package/dist/justpremiumBidAdapter.js +1 -1
  59. package/dist/jwplayerVideoProvider.js +1 -0
  60. package/dist/kargoBidAdapter.js +1 -1
  61. package/dist/konduitAnalyticsAdapter.js +1 -1
  62. package/dist/kueezBidAdapter.js +1 -1
  63. package/dist/lassoBidAdapter.js +1 -1
  64. package/dist/lifestreetBidAdapter.js +1 -1
  65. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  66. package/dist/logicadBidAdapter.js +1 -1
  67. package/dist/loglyliftBidAdapter.js +1 -1
  68. package/dist/magniteAnalyticsAdapter.js +1 -1
  69. package/dist/malltvAnalyticsAdapter.js +1 -1
  70. package/dist/marsmediaBidAdapter.js +1 -1
  71. package/dist/mediafuseBidAdapter.js +1 -1
  72. package/dist/mediasquareBidAdapter.js +1 -1
  73. package/dist/mgidBidAdapter.js +1 -1
  74. package/dist/minutemediaBidAdapter.js +1 -1
  75. package/dist/multibid.js +1 -1
  76. package/dist/not-for-prod/prebid.js +141 -132
  77. package/dist/oguryBidAdapter.js +1 -1
  78. package/dist/onetagBidAdapter.js +1 -1
  79. package/dist/ooloAnalyticsAdapter.js +1 -1
  80. package/dist/openxOrtbBidAdapter.js +1 -1
  81. package/dist/ortbConverter.js +1 -0
  82. package/dist/outbrainBidAdapter.js +1 -1
  83. package/dist/oxxionRtdProvider.js +1 -0
  84. package/dist/parrableIdSystem.js +1 -1
  85. package/dist/pbsExtensions.js +1 -0
  86. package/dist/pixfutureBidAdapter.js +1 -1
  87. package/dist/prebid-core.js +1 -1
  88. package/dist/prebidServerBidAdapter.js +1 -1
  89. package/dist/priceFloors.js +1 -1
  90. package/dist/pubCommonId.js +1 -1
  91. package/dist/publinkIdSystem.js +1 -1
  92. package/dist/pubmaticBidAdapter.js +1 -1
  93. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  94. package/dist/pxyzBidAdapter.js +1 -1
  95. package/dist/quantcastBidAdapter.js +1 -1
  96. package/dist/readpeakBidAdapter.js +1 -1
  97. package/dist/relaidoBidAdapter.js +1 -1
  98. package/dist/rhythmoneBidAdapter.js +1 -1
  99. package/dist/riseBidAdapter.js +1 -1
  100. package/dist/rtdModule.js +1 -1
  101. package/dist/rubiconAnalyticsAdapter.js +1 -1
  102. package/dist/rubiconBidAdapter.js +1 -1
  103. package/dist/schain.js +1 -1
  104. package/dist/seedingAllianceBidAdapter.js +1 -1
  105. package/dist/seedtagBidAdapter.js +1 -1
  106. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  107. package/dist/sharethroughBidAdapter.js +1 -1
  108. package/dist/shinezBidAdapter.js +1 -1
  109. package/dist/smaatoBidAdapter.js +1 -1
  110. package/dist/smartadserverBidAdapter.js +1 -1
  111. package/dist/smartxBidAdapter.js +1 -1
  112. package/dist/smilewantedBidAdapter.js +1 -1
  113. package/dist/sonobiBidAdapter.js +1 -1
  114. package/dist/sovrnAnalyticsAdapter.js +1 -1
  115. package/dist/sovrnBidAdapter.js +1 -1
  116. package/dist/spotxBidAdapter.js +1 -1
  117. package/dist/sspBCBidAdapter.js +1 -1
  118. package/dist/sublimeBidAdapter.js +1 -1
  119. package/dist/synacormediaBidAdapter.js +1 -1
  120. package/dist/targetVideoBidAdapter.js +1 -1
  121. package/dist/teadsBidAdapter.js +1 -1
  122. package/dist/teadsIdSystem.js +1 -1
  123. package/dist/trionBidAdapter.js +1 -1
  124. package/dist/tripleliftBidAdapter.js +1 -1
  125. package/dist/ttdBidAdapter.js +1 -1
  126. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  127. package/dist/underdogmediaBidAdapter.js +1 -1
  128. package/dist/undertoneBidAdapter.js +1 -1
  129. package/dist/userId.js +1 -1
  130. package/dist/vidazooBidAdapter.js +1 -1
  131. package/dist/video.js +1 -0
  132. package/dist/videoModule.js +1 -0
  133. package/dist/videobyteBidAdapter.js +1 -1
  134. package/dist/videojsVideoProvider.js +1 -0
  135. package/dist/visxBidAdapter.js +1 -1
  136. package/dist/vuukleBidAdapter.js +1 -1
  137. package/dist/widespaceBidAdapter.js +1 -1
  138. package/dist/winrBidAdapter.js +1 -1
  139. package/dist/yahoosspBidAdapter.js +1 -1
  140. package/dist/yieldmoBidAdapter.js +1 -1
  141. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  142. package/integrationExamples/videoModule/jwplayer/bidMarkedAsUsed.html +98 -0
  143. package/integrationExamples/videoModule/jwplayer/bidRequestScheduling.html +89 -0
  144. package/integrationExamples/videoModule/jwplayer/eventListeners.html +244 -0
  145. package/integrationExamples/videoModule/jwplayer/gamAdServerMediation.html +122 -0
  146. package/integrationExamples/videoModule/jwplayer/mediaMetadata.html +80 -0
  147. package/integrationExamples/videoModule/jwplayer/playlist.html +122 -0
  148. package/integrationExamples/videoModule/videojs/bidMarkedAsUsed.html +126 -0
  149. package/integrationExamples/videoModule/videojs/bidRequestScheduling.html +132 -0
  150. package/integrationExamples/videoModule/videojs/eventListeners.html +238 -0
  151. package/integrationExamples/videoModule/videojs/gamAdServerMediation.html +138 -0
  152. package/integrationExamples/videoModule/videojs/mediaMetadata.html +103 -0
  153. package/integrationExamples/videoModule/videojs/playlist.html +151 -0
  154. package/libraries/ortbConverter/README.md +378 -0
  155. package/libraries/ortbConverter/converter.js +135 -0
  156. package/libraries/ortbConverter/lib/composer.js +43 -0
  157. package/libraries/ortbConverter/lib/mergeProcessors.js +9 -0
  158. package/libraries/ortbConverter/lib/sizes.js +14 -0
  159. package/libraries/ortbConverter/processors/banner.js +40 -0
  160. package/libraries/ortbConverter/processors/default.js +167 -0
  161. package/libraries/ortbConverter/processors/mediaType.js +21 -0
  162. package/libraries/ortbConverter/processors/native.js +37 -0
  163. package/libraries/ortbConverter/processors/video.js +66 -0
  164. package/libraries/pbsExtensions/pbsExtensions.js +12 -0
  165. package/libraries/pbsExtensions/processors/aliases.js +17 -0
  166. package/libraries/pbsExtensions/processors/mediaType.js +23 -0
  167. package/libraries/pbsExtensions/processors/params.js +22 -0
  168. package/libraries/pbsExtensions/processors/pbs.js +99 -0
  169. package/libraries/pbsExtensions/processors/requestExtPrebid.js +30 -0
  170. package/libraries/pbsExtensions/processors/video.js +23 -0
  171. package/libraries/video/constants/enums.js +5 -0
  172. package/libraries/video/constants/events.js +97 -0
  173. package/libraries/video/constants/ortb.js +169 -0
  174. package/libraries/video/constants/vendorCodes.js +6 -0
  175. package/libraries/video/shared/eventHandler.js +18 -0
  176. package/libraries/video/shared/parentModule.js +82 -0
  177. package/libraries/video/shared/state.js +47 -0
  178. package/libraries/video/shared/vastXmlBuilder.js +77 -0
  179. package/libraries/video/shared/vastXmlEditor.js +115 -0
  180. package/modules/.submodules.json +6 -1
  181. package/modules/aaxBlockmeterRtdProvider.js +59 -0
  182. package/modules/aaxBlockmeterRtdProvider.md +48 -0
  183. package/modules/appnexusBidAdapter.js +38 -1
  184. package/modules/chtnwBidAdapter.js +110 -0
  185. package/modules/chtnwBidAdapter.md +31 -0
  186. package/modules/concertBidAdapter.js +44 -2
  187. package/modules/consentManagement.js +22 -1
  188. package/modules/consentManagementUsp.js +29 -7
  189. package/modules/criteoBidAdapter.js +25 -5
  190. package/modules/currency.js +9 -0
  191. package/modules/dgkeywordRtdProvider.js +3 -3
  192. package/modules/gridNMBidAdapter.js +10 -14
  193. package/modules/improvedigitalBidAdapter.js +191 -470
  194. package/modules/ixBidAdapter.js +24 -64
  195. package/modules/jwplayerVideoProvider.js +929 -0
  196. package/modules/jwplayerVideoProvider.md +25 -0
  197. package/modules/kargoBidAdapter.js +1 -1
  198. package/modules/multibid/index.js +12 -0
  199. package/modules/openxOrtbBidAdapter.js +120 -275
  200. package/modules/oxxionRtdProvider.js +119 -0
  201. package/modules/oxxionRtdProvider.md +48 -0
  202. package/modules/prebidServerBidAdapter/index.js +19 -716
  203. package/modules/prebidServerBidAdapter/ortbConverter.js +274 -0
  204. package/modules/priceFloors.js +73 -1
  205. package/modules/rtdModule/index.js +22 -1
  206. package/modules/schain.js +24 -1
  207. package/modules/spotxBidAdapter.js +16 -15
  208. package/modules/synacormediaBidAdapter.js +1 -1
  209. package/modules/teadsIdSystem.js +5 -0
  210. package/modules/userId/index.js +64 -6
  211. package/modules/videoModule/addingSubmodule.md +521 -0
  212. package/modules/videoModule/coreVideo.js +234 -0
  213. package/modules/videoModule/gamAdServerSubmodule.js +27 -0
  214. package/modules/videoModule/index.js +244 -0
  215. package/modules/videoModule/videoImpressionVerifier.js +206 -0
  216. package/modules/videojsVideoProvider.js +854 -0
  217. package/modules/videojsVideoProvider.md +17 -0
  218. package/package.json +5 -1
  219. package/src/adapterManager.js +56 -7
  220. package/src/adloader.js +2 -1
  221. package/src/auction.js +5 -0
  222. package/src/events.js +5 -1
  223. package/src/pbjsORTB.js +35 -0
  224. package/src/prebid.js +166 -145
  225. package/src/targeting.js +10 -2
  226. package/src/utils/currency.js +16 -0
  227. package/src/utils.js +21 -0
  228. package/test/spec/auctionmanager_spec.js +6 -0
  229. package/test/spec/modules/aaxBlockmeter_spec.js +58 -0
  230. package/test/spec/modules/chtnwBidAdapter_spec.js +105 -0
  231. package/test/spec/modules/concertBidAdapter_spec.js +56 -0
  232. package/test/spec/modules/consentManagementUsp_spec.js +64 -18
  233. package/test/spec/modules/criteoBidAdapter_spec.js +28 -0
  234. package/test/spec/modules/dgkeywordRtdProvider_spec.js +3 -3
  235. package/test/spec/modules/improvedigitalBidAdapter_spec.js +231 -211
  236. package/test/spec/modules/ixBidAdapter_spec.js +230 -371
  237. package/test/spec/modules/openxOrtbBidAdapter_spec.js +77 -49
  238. package/test/spec/modules/oxxionRtdProvider_spec.js +142 -0
  239. package/test/spec/modules/prebidServerBidAdapter_spec.js +139 -137
  240. package/test/spec/modules/realTimeDataModule_spec.js +65 -0
  241. package/test/spec/modules/userId_spec.js +67 -1
  242. package/test/spec/modules/videoModule/coreVideo_spec.js +98 -0
  243. package/test/spec/modules/videoModule/pbVideo_spec.js +362 -0
  244. package/test/spec/modules/videoModule/shared/parentModule_spec.js +73 -0
  245. package/test/spec/modules/videoModule/shared/state_spec.js +26 -0
  246. package/test/spec/modules/videoModule/shared/vastXmlBuilder_spec.js +103 -0
  247. package/test/spec/modules/videoModule/shared/vastXmlEditor_spec.js +209 -0
  248. package/test/spec/modules/videoModule/submodules/jwplayerVideoProvider_spec.js +846 -0
  249. package/test/spec/modules/videoModule/submodules/videojsVideoProvider_spec.js +391 -0
  250. package/test/spec/modules/videoModule/videoImpressionVerifier_spec.js +112 -0
  251. package/test/spec/ortbConverter/banner_spec.js +203 -0
  252. package/test/spec/ortbConverter/composer_spec.js +69 -0
  253. package/test/spec/ortbConverter/converter_spec.js +283 -0
  254. package/test/spec/ortbConverter/currency_spec.js +40 -0
  255. package/test/spec/ortbConverter/default_processors_spec.js +61 -0
  256. package/test/spec/ortbConverter/gdpr_spec.js +38 -0
  257. package/test/spec/ortbConverter/mediaTypes_spec.js +67 -0
  258. package/test/spec/ortbConverter/mergeProcessors_spec.js +59 -0
  259. package/test/spec/ortbConverter/multibid_spec.js +35 -0
  260. package/test/spec/ortbConverter/native_spec.js +95 -0
  261. package/test/spec/ortbConverter/pbjsORTB_spec.js +67 -0
  262. package/test/spec/ortbConverter/pbsExtensions/aliases_spec.js +57 -0
  263. package/test/spec/ortbConverter/pbsExtensions/params_spec.js +96 -0
  264. package/test/spec/ortbConverter/pbsExtensions/video_spec.js +52 -0
  265. package/test/spec/ortbConverter/priceFloors_spec.js +143 -0
  266. package/test/spec/ortbConverter/schain_spec.js +33 -0
  267. package/test/spec/ortbConverter/userId_spec.js +21 -0
  268. package/test/spec/ortbConverter/usp_spec.js +15 -0
  269. package/test/spec/ortbConverter/video_spec.js +189 -0
  270. package/test/spec/unit/core/adapterManager_spec.js +102 -0
  271. package/test/spec/unit/core/targeting_spec.js +34 -0
  272. package/test/spec/unit/pbjs_api_spec.js +108 -45
  273. package/test/spec/utils_spec.js +45 -1
@@ -0,0 +1,274 @@
1
+ import {ortbConverter} from '../../libraries/ortbConverter/converter.js';
2
+ import {
3
+ deepAccess,
4
+ deepSetValue,
5
+ getBidRequest,
6
+ getDefinedParams,
7
+ isArray,
8
+ logError,
9
+ logWarn,
10
+ mergeDeep,
11
+ timestamp
12
+ } from '../../src/utils.js';
13
+ import {config} from '../../src/config.js';
14
+ import CONSTANTS from '../../src/constants.json';
15
+ import {createBid} from '../../src/bidfactory.js';
16
+ import {pbsExtensions} from '../../libraries/pbsExtensions/pbsExtensions.js';
17
+ import {setImpBidParams} from '../../libraries/pbsExtensions/processors/params.js';
18
+ import {SUPPORTED_MEDIA_TYPES} from '../../libraries/pbsExtensions/processors/mediaType.js';
19
+ import {IMP, REQUEST, RESPONSE} from '../../src/pbjsORTB.js';
20
+ import {beConvertCurrency} from '../../src/utils/currency.js';
21
+
22
+ const DEFAULT_S2S_TTL = 60;
23
+ const DEFAULT_S2S_CURRENCY = 'USD';
24
+ const DEFAULT_S2S_NETREVENUE = true;
25
+ const BIDDER_SPECIFIC_REQUEST_PROPS = new Set(['bidderCode', 'bidderRequestId', 'uniquePbsTid', 'bids', 'timeout']);
26
+
27
+ const PBS_CONVERTER = ortbConverter({
28
+ processors: pbsExtensions,
29
+ context: {
30
+ netRevenue: DEFAULT_S2S_NETREVENUE,
31
+ },
32
+ imp(buildImp, proxyBidRequest, context) {
33
+ Object.assign(context, proxyBidRequest.pbsData);
34
+ const imp = buildImp(proxyBidRequest, context);
35
+ if (Object.values(SUPPORTED_MEDIA_TYPES).some(mtype => imp[mtype])) {
36
+ imp.secure = context.s2sBidRequest.s2sConfig.secure;
37
+ return imp;
38
+ }
39
+ },
40
+ request(buildRequest, imps, proxyBidderRequest, context) {
41
+ if (!imps.length) {
42
+ logError('Request to Prebid Server rejected due to invalid media type(s) in adUnit.');
43
+ } else {
44
+ let {s2sBidRequest, requestedBidders, eidPermissions} = context;
45
+ const request = buildRequest(imps, proxyBidderRequest, context);
46
+
47
+ request.tmax = s2sBidRequest.s2sConfig.timeout;
48
+ deepSetValue(request, 'source.tid', proxyBidderRequest.auctionId);
49
+
50
+ [request.app, request.site].forEach(section => {
51
+ if (section && !section.publisher?.id) {
52
+ deepSetValue(section, 'publisher.id', s2sBidRequest.s2sConfig.accountId);
53
+ }
54
+ })
55
+
56
+ if (isArray(eidPermissions) && eidPermissions.length > 0) {
57
+ if (requestedBidders && isArray(requestedBidders)) {
58
+ eidPermissions = eidPermissions.map(p => ({
59
+ ...p,
60
+ bidders: p.bidders.filter(bidder => requestedBidders.includes(bidder))
61
+ }))
62
+ }
63
+ deepSetValue(request, 'ext.prebid.data.eidpermissions', eidPermissions);
64
+ }
65
+
66
+ return request;
67
+ }
68
+ },
69
+ bidResponse(buildBidResponse, bid, context) {
70
+ // before sending the response throgh "stock" ortb conversion, here we need to:
71
+ // - filter out ones that come from an "unknown" bidder (if allowUnknownBidderCode is not set)
72
+ // - overwrite context.bidRequest with the actual bid request for this seat / imp combination
73
+
74
+ let bidRequest = context.actualBidRequests.get(context.seatbid.seat);
75
+ if (bidRequest == null) {
76
+ // for stored impressions, a request was made with bidder code `null`. Pick it up here so that NO_BID, BID_WON, etc events
77
+ // can work as expected (otherwise, the original request will always result in NO_BID).
78
+ bidRequest = context.actualBidRequests.get(null);
79
+ }
80
+
81
+ if (bidRequest) {
82
+ Object.assign(context, {
83
+ bidRequest,
84
+ bidderRequest: context.actualBidderRequests.find(req => req.bidderCode === bidRequest.bidder)
85
+ })
86
+ }
87
+
88
+ const bidResponse = buildBidResponse(bid, context);
89
+ bidResponse.requestBidder = bidRequest?.bidder;
90
+
91
+ if (bidResponse.native?.ortb) {
92
+ // TODO: do we need to set bidResponse.adm here?
93
+ // Any consumers can now get the same object from bidResponse.native.ortb;
94
+ // I could not find any, which raises the question - who is looking for this?
95
+ bidResponse.adm = bidResponse.native.ortb;
96
+ }
97
+
98
+ // because core has special treatment for PBS adapter responses, we need some additional processing
99
+ bidResponse.requestTimestamp = context.requestTimestamp;
100
+ const status = bid.price !== 0 ? CONSTANTS.STATUS.GOOD : CONSTANTS.STATUS.NO_BID;
101
+ return {
102
+ bid: Object.assign(createBid(status, {
103
+ src: CONSTANTS.S2S.SRC,
104
+ bidId: bidRequest ? (bidRequest.bidId || bidRequest.bid_Id) : null,
105
+ transactionId: context.adUnit.transactionId,
106
+ auctionId: context.bidderRequest.auctionId,
107
+ }), bidResponse),
108
+ adUnit: context.adUnit.code
109
+ };
110
+ },
111
+ overrides: {
112
+ [IMP]: {
113
+ id(orig, imp, proxyBidRequest, context) {
114
+ imp.id = context.impId;
115
+ },
116
+ params(orig, imp, proxyBidRequest, context) {
117
+ // override params processing to do it for each bidRequest in this imp;
118
+ // also, take overrides from s2sConfig.adapterOptions
119
+ const adapterOptions = context.s2sBidRequest.s2sConfig.adapterOptions;
120
+ for (const req of context.actualBidRequests.values()) {
121
+ setImpBidParams(imp, req, context, context);
122
+ if (adapterOptions && adapterOptions[req.bidder]) {
123
+ Object.assign(imp.ext.prebid.bidder[req.bidder], adapterOptions[req.bidder]);
124
+ }
125
+ }
126
+ },
127
+ bidfloor(orig, imp, proxyBidRequest, context) {
128
+ // for bid floors, we pass each bidRequest associated with this imp through normal bidfloor processing,
129
+ // and aggregate all of them into a single, minimum floor to put in the request
130
+ let min;
131
+ for (const req of context.actualBidRequests.values()) {
132
+ const floor = {};
133
+ orig(floor, req, context);
134
+ // if any bid does not have a valid floor, do not attempt to send any to PBS
135
+ if (floor.bidfloorcur == null || floor.bidfloor == null) {
136
+ min = null;
137
+ break;
138
+ } else if (min == null) {
139
+ min = floor;
140
+ } else {
141
+ const value = beConvertCurrency(floor.bidfloor, floor.bidfloorcur, min.bidfloorcur);
142
+ if (value != null && value < min.bidfloor) {
143
+ min = floor;
144
+ }
145
+ }
146
+ }
147
+ if (min != null) {
148
+ Object.assign(imp, min);
149
+ }
150
+ }
151
+ },
152
+ [REQUEST]: {
153
+ fpd(orig, ortbRequest, proxyBidderRequest, context) {
154
+ // FPD is handled different for PBS - the base request will only contain global FPD;
155
+ // bidder-specific values are set in ext.prebid.bidderconfig
156
+
157
+ mergeDeep(ortbRequest, context.s2sBidRequest.ortb2Fragments?.global);
158
+
159
+ // also merge in s2sConfig.extPrebid
160
+ if (context.s2sBidRequest.s2sConfig.extPrebid && typeof context.s2sBidRequest.s2sConfig.extPrebid === 'object') {
161
+ deepSetValue(ortbRequest, 'ext.prebid', mergeDeep(ortbRequest.ext?.prebid || {}, context.s2sBidRequest.s2sConfig.extPrebid));
162
+ }
163
+
164
+ const fpdConfigs = Object.entries(context.s2sBidRequest.ortb2Fragments?.bidder || {}).map(([bidder, ortb2]) => ({
165
+ bidders: [bidder],
166
+ config: {ortb2}
167
+ }));
168
+ if (fpdConfigs.length) {
169
+ deepSetValue(ortbRequest, 'ext.prebid.bidderconfig', fpdConfigs);
170
+ }
171
+ },
172
+ extPrebidAliases(orig, ortbRequest, proxyBidderRequest, context) {
173
+ // override alias processing to do it for each bidder in the request
174
+ context.actualBidderRequests.forEach(req => orig(ortbRequest, req, context));
175
+ },
176
+ sourceExtSchain(orig, ortbRequest, proxyBidderRequest, context) {
177
+ // pass schains in ext.prebid.schains, with the most commonly used one in source.ext.schain
178
+ let mainChain;
179
+
180
+ let chains = (deepAccess(ortbRequest, 'ext.prebid.schains') || []);
181
+ const chainBidders = new Set(chains.flatMap((item) => item.bidders));
182
+
183
+ chains = Object.values(
184
+ chains
185
+ .concat(context.actualBidderRequests
186
+ .filter((req) => !chainBidders.has(req.bidderCode)) // schain defined in s2sConfig.extPrebid takes precedence
187
+ .map((req) => ({
188
+ bidders: [req.bidderCode],
189
+ schain: deepAccess(req, 'bids.0.schain')
190
+ })))
191
+ .filter(({bidders, schain}) => bidders?.length > 0 && schain)
192
+ .reduce((chains, {bidders, schain}) => {
193
+ const key = JSON.stringify(schain);
194
+ if (!chains.hasOwnProperty(key)) {
195
+ chains[key] = {bidders: new Set(), schain};
196
+ }
197
+ bidders.forEach((bidder) => chains[key].bidders.add(bidder));
198
+ if (mainChain == null || chains[key].bidders.size > mainChain.bidders.size) {
199
+ mainChain = chains[key]
200
+ }
201
+ return chains;
202
+ }, {})
203
+ ).map(({bidders, schain}) => ({bidders: Array.from(bidders), schain}));
204
+
205
+ if (mainChain != null) {
206
+ deepSetValue(ortbRequest, 'source.ext.schain', mainChain.schain);
207
+ }
208
+
209
+ if (chains.length) {
210
+ deepSetValue(ortbRequest, 'ext.prebid.schains', chains);
211
+ }
212
+ }
213
+ },
214
+ [RESPONSE]: {
215
+ serverSideStats(orig, response, ortbResponse, context) {
216
+ // override to process each request
217
+ context.actualBidderRequests.forEach(req => orig(response, ortbResponse, {...context, bidderRequest: req, bidRequests: req.bids}));
218
+ }
219
+ }
220
+ },
221
+ });
222
+
223
+ export function buildPBSRequest(s2sBidRequest, bidderRequests, adUnits, requestedBidders, eidPermissions) {
224
+ const requestTimestamp = timestamp();
225
+ const impIds = new Set();
226
+ const proxyBidRequests = [];
227
+
228
+ adUnits.forEach(adUnit => {
229
+ const actualBidRequests = new Map();
230
+
231
+ adUnit.bids.forEach((bid) => {
232
+ if (bid.mediaTypes != null) {
233
+ // TODO: support labels / conditional bids
234
+ // for now, just warn about them
235
+ logWarn(`Prebid Server adapter does not (yet) support bidder-specific mediaTypes for the same adUnit. Size mapping configuration will be ignored for adUnit: ${adUnit.code}, bidder: ${bid.bidder}`);
236
+ }
237
+ actualBidRequests.set(bid.bidder, getBidRequest(bid.bid_id, bidderRequests));
238
+ });
239
+
240
+ let impId = adUnit.code;
241
+ let i = 1;
242
+ while (impIds.has(impId)) {
243
+ i++;
244
+ impId = `${adUnit.code}-${i}`;
245
+ }
246
+ impIds.add(impId)
247
+ proxyBidRequests.push({
248
+ ...adUnit,
249
+ ...getDefinedParams(actualBidRequests.values().next().value || {}, ['userId', 'userIdAsEids', 'schain']),
250
+ pbsData: {impId, actualBidRequests, adUnit}
251
+ });
252
+ });
253
+
254
+ const proxyBidderRequest = Object.fromEntries(Object.entries(bidderRequests[0]).filter(([k]) => !BIDDER_SPECIFIC_REQUEST_PROPS.has(k)))
255
+
256
+ return PBS_CONVERTER.toORTB({
257
+ bidderRequest: proxyBidderRequest,
258
+ bidRequests: proxyBidRequests,
259
+ context: {
260
+ currency: config.getConfig('currency.adServerCurrency') || DEFAULT_S2S_CURRENCY,
261
+ ttl: s2sBidRequest.s2sConfig.defaultTtl || DEFAULT_S2S_TTL,
262
+ requestTimestamp,
263
+ s2sBidRequest,
264
+ requestedBidders,
265
+ actualBidderRequests: bidderRequests,
266
+ eidPermissions,
267
+ nativeRequest: s2sBidRequest.s2sConfig.ortbNative,
268
+ }
269
+ });
270
+ }
271
+
272
+ export function interpretPBSResponse(response, request) {
273
+ return PBS_CONVERTER.fromORTB({response, request});
274
+ }
@@ -10,6 +10,7 @@ import {
10
10
  logError,
11
11
  logInfo,
12
12
  logWarn,
13
+ mergeDeep,
13
14
  parseGPTSingleSizeArray,
14
15
  parseUrl,
15
16
  pick
@@ -24,7 +25,9 @@ import {find} from '../src/polyfill.js';
24
25
  import {getRefererInfo} from '../src/refererDetection.js';
25
26
  import {bidderSettings} from '../src/bidderSettings.js';
26
27
  import {auctionManager} from '../src/auctionManager.js';
28
+ import {IMP, PBS, registerOrtbProcessor, REQUEST} from '../src/pbjsORTB.js';
27
29
  import {timedAuctionHook, timedBidResponseHook} from '../src/utils/perfMetrics.js';
30
+ import {beConvertCurrency} from '../src/utils/currency.js';
28
31
 
29
32
  /**
30
33
  * @summary This Module is intended to provide users with the ability to dynamically set and enforce price floors on a per auction basis.
@@ -79,7 +82,7 @@ const getHostname = (() => {
79
82
  let domain;
80
83
  return function() {
81
84
  if (domain == null) {
82
- domain = parseUrl(getRefererInfo().topmostLocation, {noDecodeWholeUrl: true}).hostname;
85
+ domain = parseUrl(getRefererInfo().topmostLocation, {noDecodeWholeURL: true}).hostname;
83
86
  }
84
87
  return domain;
85
88
  }
@@ -745,3 +748,72 @@ export const addBidResponseHook = timedBidResponseHook('priceFloors', function a
745
748
  });
746
749
 
747
750
  config.getConfig('floors', config => handleSetFloorsConfig(config.floors));
751
+
752
+ /**
753
+ * Sets bidfloor and bidfloorcur for ORTB imp objects
754
+ */
755
+ export function setOrtbImpBidFloor(imp, bidRequest, context) {
756
+ if (typeof bidRequest.getFloor === 'function') {
757
+ let currency, floor;
758
+ try {
759
+ ({currency, floor} = bidRequest.getFloor({
760
+ currency: context.currency || config.getConfig('currency.adServerCurrency') || 'USD',
761
+ mediaType: context.mediaType || '*',
762
+ size: '*'
763
+ }));
764
+ } catch (e) {
765
+ logWarn('Cannot compute floor for bid', bidRequest);
766
+ return;
767
+ }
768
+ floor = parseFloat(floor);
769
+ if (currency != null && floor != null && !isNaN(floor)) {
770
+ Object.assign(imp, {
771
+ bidfloor: floor,
772
+ bidfloorcur: currency
773
+ });
774
+ }
775
+ }
776
+ }
777
+
778
+ export function setImpExtPrebidFloors(imp, bidRequest, context) {
779
+ // logic below relates to https://github.com/prebid/Prebid.js/issues/8749 and does the following:
780
+ // 1. check client-side floors (ref bidfloor/bidfloorcur & ortb2Imp floorMin/floorMinCur (if present))
781
+ // 2. set pbs req wide floorMinCur to the first floor currency found when iterating over imp's
782
+ // (if currency conversion logic present, convert all imp floor values to this currency)
783
+ // 3. compare/store ref to lowest floorMin value as each imp is iterated over
784
+ // 4. set req wide floorMin and floorMinCur values for pbs after iterations are done
785
+
786
+ if (imp.bidfloor != null) {
787
+ let {floorMinCur, floorMin} = context.reqContext.floorMin || {};
788
+
789
+ if (floorMinCur == null) { floorMinCur = imp.bidfloorcur }
790
+ const ortb2ImpFloorCur = imp.ext?.prebid?.floors?.floorMinCur || imp.ext?.prebid?.floorMinCur || floorMinCur;
791
+ const ortb2ImpFloorMin = imp.ext?.prebid?.floors?.floorMin || imp.ext?.prebid?.floorMin;
792
+ const convertedFloorMinValue = beConvertCurrency(imp.bidfloor, imp.bidfloorcur, floorMinCur);
793
+ const convertedOrtb2ImpFloorMinValue = ortb2ImpFloorMin && ortb2ImpFloorCur ? beConvertCurrency(ortb2ImpFloorMin, ortb2ImpFloorCur, floorMinCur) : false;
794
+
795
+ const lowestImpFloorMin = convertedOrtb2ImpFloorMinValue && convertedOrtb2ImpFloorMinValue < convertedFloorMinValue
796
+ ? convertedOrtb2ImpFloorMinValue
797
+ : convertedFloorMinValue;
798
+
799
+ deepSetValue(imp, 'ext.prebid.floors.floorMin', lowestImpFloorMin);
800
+ if (floorMin == null || floorMin > lowestImpFloorMin) { floorMin = lowestImpFloorMin }
801
+ context.reqContext.floorMin = {floorMin, floorMinCur};
802
+ }
803
+ }
804
+
805
+ /**
806
+ * PBS specific extension: set ext.prebid.floors.enabled = false if floors are processed client-side
807
+ */
808
+ export function setOrtbExtPrebidFloors(ortbRequest, bidderRequest, context) {
809
+ if (addedFloorsHook) {
810
+ deepSetValue(ortbRequest, 'ext.prebid.floors.enabled', ortbRequest.ext?.prebid?.floors?.enabled || false);
811
+ }
812
+ if (context?.floorMin) {
813
+ mergeDeep(ortbRequest, {ext: {prebid: {floors: context.floorMin}}})
814
+ }
815
+ }
816
+
817
+ registerOrtbProcessor({type: IMP, name: 'bidfloor', fn: setOrtbImpBidFloor});
818
+ registerOrtbProcessor({type: IMP, name: 'extPrebidFloors', fn: setImpExtPrebidFloors, dialects: [PBS], priority: -1});
819
+ registerOrtbProcessor({type: REQUEST, name: 'extPrebidFloors', fn: setOrtbExtPrebidFloors, dialects: [PBS]});
@@ -108,6 +108,13 @@
108
108
  * @param {UserConsentData} userConsent
109
109
  */
110
110
 
111
+ /**
112
+ * @function?
113
+ * @summary on data deletion request
114
+ * @name RtdSubmodule#onDataDeletionRequest
115
+ * @param {SubmoduleConfig} config
116
+ */
117
+
111
118
  /**
112
119
  * @interface ModuleConfig
113
120
  */
@@ -156,7 +163,7 @@ import {getHook, module} from '../../src/hook.js';
156
163
  import {logError, logInfo, logWarn} from '../../src/utils.js';
157
164
  import * as events from '../../src/events.js';
158
165
  import CONSTANTS from '../../src/constants.json';
159
- import {gdprDataHandler, uspDataHandler} from '../../src/adapterManager.js';
166
+ import adapterManager, {gdprDataHandler, uspDataHandler} from '../../src/adapterManager.js';
160
167
  import {find} from '../../src/polyfill.js';
161
168
  import {timedAuctionHook} from '../../src/utils/perfMetrics.js';
162
169
 
@@ -230,6 +237,7 @@ export function init(config) {
230
237
  _dataProviders = realTimeData.dataProviders;
231
238
  setEventsListeners();
232
239
  getHook('startAuction').before(setBidRequestsData, 20); // RTD should run before FPD
240
+ adapterManager.callDataDeletionRequest.before(onDataDeletionRequest);
233
241
  initSubModules();
234
242
  });
235
243
  }
@@ -386,5 +394,18 @@ export function deepMerge(arr) {
386
394
  }, {});
387
395
  }
388
396
 
397
+ export function onDataDeletionRequest(next, ...args) {
398
+ subModules.forEach((sm) => {
399
+ if (typeof sm.onDataDeletionRequest === 'function') {
400
+ try {
401
+ sm.onDataDeletionRequest(sm.config);
402
+ } catch (e) {
403
+ logError(`Error executing ${sm.name}.onDataDeletionRequest`, e)
404
+ }
405
+ }
406
+ });
407
+ next.apply(this, args);
408
+ }
409
+
389
410
  module('realTimeData', attachRealTimeDataProvider);
390
411
  init(config);
package/modules/schain.js CHANGED
@@ -1,6 +1,18 @@
1
1
  import { config } from '../src/config.js';
2
2
  import adapterManager from '../src/adapterManager.js';
3
- import { isNumber, isStr, isArray, isPlainObject, hasOwn, logError, isInteger, _each, logWarn } from '../src/utils.js';
3
+ import {
4
+ isNumber,
5
+ isStr,
6
+ isArray,
7
+ isPlainObject,
8
+ hasOwn,
9
+ logError,
10
+ isInteger,
11
+ _each,
12
+ logWarn,
13
+ deepAccess, deepSetValue
14
+ } from '../src/utils.js';
15
+ import {registerOrtbProcessor, REQUEST} from '../src/pbjsORTB.js';
4
16
 
5
17
  // https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md
6
18
 
@@ -181,3 +193,14 @@ export function init() {
181
193
  }
182
194
 
183
195
  init()
196
+
197
+ export function setOrtbSourceExtSchain(ortbRequest, bidderRequest, context) {
198
+ if (!deepAccess(ortbRequest, 'source.ext.schain')) {
199
+ const schain = deepAccess(context, 'bidRequests.0.schain');
200
+ if (schain) {
201
+ deepSetValue(ortbRequest, 'source.ext.schain', schain);
202
+ }
203
+ }
204
+ }
205
+
206
+ registerOrtbProcessor({type: REQUEST, name: 'sourceExtSchain', fn: setOrtbSourceExtSchain});
@@ -149,7 +149,7 @@ export const spec = {
149
149
  }
150
150
  }
151
151
 
152
- const mimes = getBidIdParameter('mimes', bid.params) || ['application/javascript', 'video/mp4', 'video/webm'];
152
+ const mimes = getBidIdParameter('mimes', bid.params) || deepAccess(bid, 'mediaTypes.video.mimes') || ['application/javascript', 'video/mp4', 'video/webm'];
153
153
 
154
154
  const spotxReq = {
155
155
  id: bid.bidId,
@@ -176,28 +176,29 @@ export const spec = {
176
176
  spotxReq.bidfloor = getBidIdParameter('price_floor', bid.params);
177
177
  }
178
178
 
179
- if (getBidIdParameter('start_delay', bid.params) != '') {
180
- spotxReq.video.startdelay = 0 + Boolean(getBidIdParameter('start_delay', bid.params));
179
+ const startdelay = getBidIdParameter('start_delay', bid.params) || deepAccess(bid, 'mediaTypes.video.startdelay');
180
+ if (startdelay) {
181
+ spotxReq.video.startdelay = 0 + Boolean(startdelay);
181
182
  }
182
183
 
183
- if (getBidIdParameter('min_duration', bid.params) != '') {
184
- spotxReq.video.minduration = getBidIdParameter('min_duration', bid.params);
184
+ const minduration = getBidIdParameter('min_duration', bid.params) || deepAccess(bid, 'mediaTypes.video.minduration');
185
+ if (minduration) {
186
+ spotxReq.video.minduration = minduration;
185
187
  }
186
188
 
187
- if (getBidIdParameter('max_duration', bid.params) != '') {
188
- spotxReq.video.maxduration = getBidIdParameter('max_duration', bid.params);
189
+ const maxduration = getBidIdParameter('max_duration', bid.params) || deepAccess(bid, 'mediaTypes.video.maxduration');
190
+ if (maxduration) {
191
+ spotxReq.video.maxduration = maxduration;
189
192
  }
190
193
 
191
- if (getBidIdParameter('placement_type', bid.params) != '') {
192
- spotxReq.video.ext.placement = getBidIdParameter('placement_type', bid.params);
194
+ const placement = getBidIdParameter('placement_type', bid.params) || deepAccess(bid, 'mediaTypes.video.placement');
195
+ if (placement) {
196
+ spotxReq.video.ext.placement = placement;
193
197
  }
194
198
 
195
- if (getBidIdParameter('position', bid.params) != '') {
196
- spotxReq.video.ext.pos = getBidIdParameter('position', bid.params);
197
- } else {
198
- if (deepAccess(bid, 'mediaTypes.video.pos')) {
199
- spotxReq.video.ext.pos = deepAccess(bid, 'mediaTypes.video.pos');
200
- }
199
+ const position = getBidIdParameter('position', bid.params) || deepAccess(bid, 'mediaTypes.video.pos');
200
+ if (position) {
201
+ spotxReq.video.ext.pos = position;
201
202
  }
202
203
 
203
204
  if (bid.crumbs && bid.crumbs.pubcid) {
@@ -71,7 +71,7 @@ export const spec = {
71
71
  seatId = bid.params.seatId;
72
72
  }
73
73
  const tagIdOrPlacementId = bid.params.tagId || bid.params.placementId;
74
- let pos = parseInt(bid.params.pos, 10);
74
+ let pos = parseInt(bid.params.pos || deepAccess(bid.mediaTypes, 'video.pos'), 10);
75
75
  if (isNaN(pos)) {
76
76
  logWarn(`Synacormedia: there is an invalid POS: ${bid.params.pos}`);
77
77
  pos = 0;
@@ -37,6 +37,11 @@ export const teadsIdSubmodule = {
37
37
  * @type {string}
38
38
  */
39
39
  name: MODULE_NAME,
40
+ /**
41
+ * Vendor id of Teads
42
+ * @type {number}
43
+ */
44
+ gvlid: GVL_ID,
40
45
  /**
41
46
  * decode the stored id value for passing to bid requests
42
47
  * @function
@@ -129,7 +129,7 @@ import {find, includes} from '../../src/polyfill.js';
129
129
  import {config} from '../../src/config.js';
130
130
  import * as events from '../../src/events.js';
131
131
  import {getGlobal} from '../../src/prebidGlobal.js';
132
- import {gdprDataHandler} from '../../src/adapterManager.js';
132
+ import adapterManager, {gdprDataHandler} from '../../src/adapterManager.js';
133
133
  import CONSTANTS from '../../src/constants.json';
134
134
  import {hook, module, ready as hooksReady} from '../../src/hook.js';
135
135
  import {buildEidPermissions, createEidsArray, USER_IDS_CONFIG} from './eids.js';
@@ -149,11 +149,12 @@ import {
149
149
  logInfo,
150
150
  logWarn,
151
151
  timestamp,
152
- isEmpty
152
+ isEmpty, deepSetValue
153
153
  } from '../../src/utils.js';
154
154
  import {getPPID as coreGetPPID} from '../../src/adserver.js';
155
155
  import {defer, GreedyPromise} from '../../src/utils/promise.js';
156
156
  import {hasPurpose1Consent} from '../../src/utils/gpdr.js';
157
+ import {registerOrtbProcessor, REQUEST} from '../../src/pbjsORTB.js';
157
158
  import {newMetrics, timedAuctionHook, useMetrics} from '../../src/utils/perfMetrics.js';
158
159
 
159
160
  const MODULE_NAME = 'User ID';
@@ -216,6 +217,14 @@ export function setSubmoduleRegistry(submodules) {
216
217
  submoduleRegistry = submodules;
217
218
  }
218
219
 
220
+ function cookieSetter(submodule) {
221
+ const domainOverride = (typeof submodule.submodule.domainOverride === 'function') ? submodule.submodule.domainOverride() : null;
222
+ const name = submodule.config.storage.name;
223
+ return function setCookie(suffix, value, expiration) {
224
+ coreStorage.setCookie(name + (suffix || ''), value, expiration, 'Lax', domainOverride);
225
+ }
226
+ }
227
+
219
228
  /**
220
229
  * @param {SubmoduleContainer} submodule
221
230
  * @param {(Object|string)} value
@@ -225,15 +234,15 @@ export function setStoredValue(submodule, value) {
225
234
  * @type {SubmoduleStorage}
226
235
  */
227
236
  const storage = submodule.config.storage;
228
- const domainOverride = (typeof submodule.submodule.domainOverride === 'function') ? submodule.submodule.domainOverride() : null;
229
237
 
230
238
  try {
231
- const valueStr = isPlainObject(value) ? JSON.stringify(value) : value;
232
239
  const expiresStr = (new Date(Date.now() + (storage.expires * (60 * 60 * 24 * 1000)))).toUTCString();
240
+ const valueStr = isPlainObject(value) ? JSON.stringify(value) : value;
233
241
  if (storage.type === COOKIE) {
234
- coreStorage.setCookie(storage.name, valueStr, expiresStr, 'Lax', domainOverride);
242
+ const setCookie = cookieSetter(submodule);
243
+ setCookie(null, value, expiresStr);
235
244
  if (typeof storage.refreshInSeconds === 'number') {
236
- coreStorage.setCookie(`${storage.name}_last`, new Date().toUTCString(), expiresStr, 'Lax', domainOverride);
245
+ setCookie('_last', new Date().toUTCString(), expiresStr);
237
246
  }
238
247
  } else if (storage.type === LOCAL_STORAGE) {
239
248
  coreStorage.setDataInLocalStorage(`${storage.name}_exp`, expiresStr);
@@ -247,6 +256,31 @@ export function setStoredValue(submodule, value) {
247
256
  }
248
257
  }
249
258
 
259
+ export function deleteStoredValue(submodule) {
260
+ let deleter, suffixes;
261
+ switch (submodule.config?.storage?.type) {
262
+ case COOKIE:
263
+ const setCookie = cookieSetter(submodule);
264
+ const expiry = (new Date(Date.now() - 1000 * 60 * 60 * 24)).toUTCString();
265
+ deleter = (suffix) => setCookie(suffix, '', expiry)
266
+ suffixes = ['', '_last'];
267
+ break;
268
+ case LOCAL_STORAGE:
269
+ deleter = (suffix) => coreStorage.removeDataFromLocalStorage(submodule.config.storage.name + suffix)
270
+ suffixes = ['', '_last', '_exp'];
271
+ break;
272
+ }
273
+ if (deleter) {
274
+ suffixes.forEach(suffix => {
275
+ try {
276
+ deleter(suffix)
277
+ } catch (e) {
278
+ logError(e);
279
+ }
280
+ });
281
+ }
282
+ }
283
+
250
284
  function setPrebidServerEidPermissions(initializedSubmodules) {
251
285
  let setEidPermissions = getPrebidInternal().setEidPermissions;
252
286
  if (typeof setEidPermissions === 'function' && isArray(initializedSubmodules)) {
@@ -1009,12 +1043,28 @@ function updateSubmodules() {
1009
1043
  if (!addedUserIdHook && submodules.length) {
1010
1044
  // priority value 40 will load after consentManagement with a priority of 50
1011
1045
  getGlobal().requestBids.before(requestBidsHook, 40);
1046
+ adapterManager.callDataDeletionRequest.before(requestDataDeletion);
1012
1047
  coreGetPPID.after((next) => next(getPPID()));
1013
1048
  logInfo(`${MODULE_NAME} - usersync config updated for ${submodules.length} submodules: `, submodules.map(a => a.submodule.name));
1014
1049
  addedUserIdHook = true;
1015
1050
  }
1016
1051
  }
1017
1052
 
1053
+ export function requestDataDeletion(next, ...args) {
1054
+ logInfo('UserID: received data deletion request; deleting all stored IDs...')
1055
+ submodules.forEach(submodule => {
1056
+ if (typeof submodule.submodule.onDataDeletionRequest === 'function') {
1057
+ try {
1058
+ submodule.submodule.onDataDeletionRequest(submodule.config, submodule.idObj, ...args);
1059
+ } catch (e) {
1060
+ logError(`Error calling onDataDeletionRequest for ID submodule ${submodule.submodule.name}`, e);
1061
+ }
1062
+ }
1063
+ deleteStoredValue(submodule);
1064
+ })
1065
+ next.apply(this, args);
1066
+ }
1067
+
1018
1068
  /**
1019
1069
  * enable submodule in User ID
1020
1070
  * @param {Submodule} submodule
@@ -1082,3 +1132,11 @@ export function init(config, {delay = GreedyPromise.timeout} = {}) {
1082
1132
  init(config);
1083
1133
 
1084
1134
  module('userId', attachIdSystem);
1135
+
1136
+ export function setOrtbUserExtEids(ortbRequest, bidderRequest, context) {
1137
+ const eids = deepAccess(context, 'bidRequests.0.userIdAsEids');
1138
+ if (eids) {
1139
+ deepSetValue(ortbRequest, 'user.ext.eids', eids);
1140
+ }
1141
+ }
1142
+ registerOrtbProcessor({type: REQUEST, name: 'userExtEids', fn: setOrtbUserExtEids});