prebid.js 7.19.0 → 7.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/dist/33acrossBidAdapter.js +1 -1
  2. package/dist/33acrossIdSystem.js +1 -1
  3. package/dist/adWMGAnalyticsAdapter.js +1 -1
  4. package/dist/adagioAnalyticsAdapter.js +1 -1
  5. package/dist/adagioBidAdapter.js +1 -1
  6. package/dist/adbookpspBidAdapter.js +1 -1
  7. package/dist/adgenerationBidAdapter.js +1 -1
  8. package/dist/adkernelAdnAnalyticsAdapter.js +1 -1
  9. package/dist/adkernelBidAdapter.js +1 -1
  10. package/dist/adlooxAdServerVideo.js +1 -1
  11. package/dist/adlooxAnalyticsAdapter.js +1 -1
  12. package/dist/adlooxRtdProvider.js +1 -1
  13. package/dist/adomikAnalyticsAdapter.js +1 -1
  14. package/dist/adrelevantisBidAdapter.js +1 -1
  15. package/dist/adtrgtmeBidAdapter.js +1 -1
  16. package/dist/adxcgAnalyticsAdapter.js +1 -1
  17. package/dist/adxcgBidAdapter.js +1 -1
  18. package/dist/adxpremiumAnalyticsAdapter.js +1 -1
  19. package/dist/ajaBidAdapter.js +1 -1
  20. package/dist/amxBidAdapter.js +1 -1
  21. package/dist/amxIdSystem.js +1 -1
  22. package/dist/aolBidAdapter.js +1 -1
  23. package/dist/appierAnalyticsAdapter.js +1 -1
  24. package/dist/appnexusBidAdapter.js +1 -1
  25. package/dist/asoBidAdapter.js +1 -1
  26. package/dist/atsAnalyticsAdapter.js +1 -1
  27. package/dist/axonixBidAdapter.js +1 -1
  28. package/dist/bidViewability.js +1 -1
  29. package/dist/bidglassBidAdapter.js +1 -1
  30. package/dist/bidwatchAnalyticsAdapter.js +1 -1
  31. package/dist/big-richmediaBidAdapter.js +1 -1
  32. package/dist/bridgewellBidAdapter.js +1 -1
  33. package/dist/brightMountainMediaBidAdapter.js +1 -1
  34. package/dist/byDataAnalyticsAdapter.js +1 -1
  35. package/dist/carodaBidAdapter.js +1 -1
  36. package/dist/categoryTranslation.js +1 -1
  37. package/dist/concertAnalyticsAdapter.js +1 -1
  38. package/dist/concertBidAdapter.js +1 -1
  39. package/dist/connectIdSystem.js +1 -1
  40. package/dist/connectadBidAdapter.js +1 -1
  41. package/dist/consentManagement.js +1 -1
  42. package/dist/consentManagementUsp.js +1 -1
  43. package/dist/consumableBidAdapter.js +1 -1
  44. package/dist/conversantAnalyticsAdapter.js +1 -1
  45. package/dist/conversantBidAdapter.js +1 -1
  46. package/dist/craftBidAdapter.js +1 -1
  47. package/dist/criteoBidAdapter.js +1 -1
  48. package/dist/currency.js +1 -1
  49. package/dist/datablocksAnalyticsAdapter.js +1 -1
  50. package/dist/dchain.js +1 -1
  51. package/dist/debugging-standalone.js +1 -1
  52. package/dist/debugging.js +1 -1
  53. package/dist/dependencies.json +3 -0
  54. package/dist/dfpAdServerVideo.js +1 -1
  55. package/dist/dspxBidAdapter.js +1 -1
  56. package/dist/eplanningAnalyticsAdapter.js +1 -1
  57. package/dist/eplanningBidAdapter.js +1 -1
  58. package/dist/finativeBidAdapter.js +1 -1
  59. package/dist/fintezaAnalyticsAdapter.js +1 -1
  60. package/dist/ftrackIdSystem.js +1 -1
  61. package/dist/gdprEnforcement.js +1 -1
  62. package/dist/glimpseBidAdapter.js +1 -1
  63. package/dist/gmosspBidAdapter.js +1 -1
  64. package/dist/goldbachBidAdapter.js +1 -1
  65. package/dist/googleAnalyticsAdapter.js +1 -1
  66. package/dist/gridBidAdapter.js +1 -1
  67. package/dist/gridNMBidAdapter.js +1 -1
  68. package/dist/gumgumBidAdapter.js +1 -1
  69. package/dist/h12mediaBidAdapter.js +1 -1
  70. package/dist/hadronAnalyticsAdapter.js +1 -1
  71. package/dist/id5AnalyticsAdapter.js +1 -1
  72. package/dist/id5IdSystem.js +1 -1
  73. package/dist/improvedigitalBidAdapter.js +1 -1
  74. package/dist/inmarBidAdapter.js +1 -1
  75. package/dist/insticatorBidAdapter.js +1 -1
  76. package/dist/invisiblyAnalyticsAdapter.js +1 -1
  77. package/dist/ixBidAdapter.js +1 -1
  78. package/dist/justpremiumBidAdapter.js +1 -1
  79. package/dist/kargoAnalyticsAdapter.js +1 -1
  80. package/dist/kinessoIdSystem.js +1 -1
  81. package/dist/konduitAnalyticsAdapter.js +1 -1
  82. package/dist/kueezBidAdapter.js +1 -1
  83. package/dist/lassoBidAdapter.js +1 -1
  84. package/dist/lifestreetBidAdapter.js +1 -1
  85. package/dist/liveIntentAnalyticsAdapter.js +1 -1
  86. package/dist/liveIntentIdSystem.js +1 -1
  87. package/dist/livewrappedAnalyticsAdapter.js +1 -1
  88. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  89. package/dist/logicadBidAdapter.js +1 -1
  90. package/dist/loglyliftBidAdapter.js +1 -1
  91. package/dist/lotamePanoramaIdSystem.js +1 -1
  92. package/dist/magniteAnalyticsAdapter.js +1 -0
  93. package/dist/malltvAnalyticsAdapter.js +1 -1
  94. package/dist/marsmediaAnalyticsAdapter.js +1 -1
  95. package/dist/marsmediaBidAdapter.js +1 -1
  96. package/dist/mass.js +1 -1
  97. package/dist/mediafuseBidAdapter.js +1 -1
  98. package/dist/medianetAnalyticsAdapter.js +1 -1
  99. package/dist/mediasquareBidAdapter.js +1 -1
  100. package/dist/mgidBidAdapter.js +1 -1
  101. package/dist/minutemediaBidAdapter.js +1 -1
  102. package/dist/multibid.js +1 -1
  103. package/dist/not-for-prod/prebid.js +186 -184
  104. package/dist/oguryBidAdapter.js +1 -1
  105. package/dist/onetagBidAdapter.js +1 -1
  106. package/dist/ooloAnalyticsAdapter.js +1 -1
  107. package/dist/openxAnalyticsAdapter.js +1 -1
  108. package/dist/optimonAnalyticsAdapter.js +1 -1
  109. package/dist/outbrainBidAdapter.js +1 -1
  110. package/dist/parrableIdSystem.js +1 -1
  111. package/dist/pianoDmpAnalyticsAdapter.js +1 -1
  112. package/dist/pixfutureBidAdapter.js +1 -1
  113. package/dist/prebid-core.js +2 -2
  114. package/dist/prebidServerBidAdapter.js +1 -1
  115. package/dist/prebidmanagerAnalyticsAdapter.js +1 -1
  116. package/dist/priceFloors.js +1 -1
  117. package/dist/publinkIdSystem.js +1 -1
  118. package/dist/pubmaticAnalyticsAdapter.js +1 -1
  119. package/dist/pubmaticBidAdapter.js +1 -1
  120. package/dist/pubperfAnalyticsAdapter.js +1 -1
  121. package/dist/pubstackAnalyticsAdapter.js +1 -1
  122. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  123. package/dist/pubxaiAnalyticsAdapter.js +1 -1
  124. package/dist/pulsepointAnalyticsAdapter.js +1 -1
  125. package/dist/pxyzBidAdapter.js +1 -1
  126. package/dist/quantcastBidAdapter.js +1 -1
  127. package/dist/quantcastIdSystem.js +1 -1
  128. package/dist/readpeakBidAdapter.js +1 -1
  129. package/dist/realvuAnalyticsAdapter.js +1 -1
  130. package/dist/relaidoBidAdapter.js +1 -1
  131. package/dist/relevantAnalyticsAdapter.js +1 -1
  132. package/dist/rhythmoneBidAdapter.js +1 -1
  133. package/dist/riseBidAdapter.js +1 -1
  134. package/dist/rivrAnalyticsAdapter.js +1 -1
  135. package/dist/roxotAnalyticsAdapter.js +1 -1
  136. package/dist/rtdModule.js +1 -1
  137. package/dist/rubiconAnalyticsAdapter.js +1 -1
  138. package/dist/rubiconBidAdapter.js +1 -1
  139. package/dist/s2sTesting.js +1 -1
  140. package/dist/scaleableAnalyticsAdapter.js +1 -1
  141. package/dist/schain.js +1 -1
  142. package/dist/seedingAllianceBidAdapter.js +1 -1
  143. package/dist/seedtagBidAdapter.js +1 -1
  144. package/dist/sharedIdSystem.js +1 -1
  145. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  146. package/dist/sharethroughBidAdapter.js +1 -1
  147. package/dist/shinezBidAdapter.js +1 -1
  148. package/dist/sigmoidAnalyticsAdapter.js +1 -1
  149. package/dist/smaatoBidAdapter.js +1 -1
  150. package/dist/smartadserverBidAdapter.js +1 -1
  151. package/dist/smartxBidAdapter.js +1 -1
  152. package/dist/smilewantedBidAdapter.js +1 -1
  153. package/dist/sonobiAnalyticsAdapter.js +1 -1
  154. package/dist/sonobiBidAdapter.js +1 -1
  155. package/dist/sovrnAnalyticsAdapter.js +1 -1
  156. package/dist/sovrnBidAdapter.js +1 -1
  157. package/dist/sspBCBidAdapter.js +1 -1
  158. package/dist/staqAnalyticsAdapter.js +1 -1
  159. package/dist/sublimeBidAdapter.js +1 -1
  160. package/dist/synacormediaBidAdapter.js +1 -1
  161. package/dist/taboolaBidAdapter.js +1 -1
  162. package/dist/tapadIdSystem.js +1 -1
  163. package/dist/targetVideoBidAdapter.js +1 -1
  164. package/dist/teadsBidAdapter.js +1 -1
  165. package/dist/teadsIdSystem.js +1 -0
  166. package/dist/terceptAnalyticsAdapter.js +1 -1
  167. package/dist/trionBidAdapter.js +1 -1
  168. package/dist/tripleliftBidAdapter.js +1 -1
  169. package/dist/ttdBidAdapter.js +1 -1
  170. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  171. package/dist/underdogmediaBidAdapter.js +1 -1
  172. package/dist/undertoneBidAdapter.js +1 -1
  173. package/dist/userId.js +1 -1
  174. package/dist/vidazooBidAdapter.js +1 -1
  175. package/dist/videobyteBidAdapter.js +1 -1
  176. package/dist/visxBidAdapter.js +1 -1
  177. package/dist/vrtcalBidAdapter.js +1 -1
  178. package/dist/vuukleBidAdapter.js +1 -1
  179. package/dist/weboramaRtdProvider.js +1 -1
  180. package/dist/widespaceBidAdapter.js +1 -1
  181. package/dist/winrBidAdapter.js +1 -1
  182. package/dist/yahoosspBidAdapter.js +1 -1
  183. package/dist/yieldmoBidAdapter.js +1 -1
  184. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  185. package/dist/yuktamediaAnalyticsAdapter.js +1 -1
  186. package/dist/zeta_global_sspAnalyticsAdapter.js +1 -1
  187. package/modules/.submodules.json +1 -0
  188. package/modules/adkernelBidAdapter.js +2 -2
  189. package/modules/aolBidAdapter.js +25 -2
  190. package/modules/appnexusBidAdapter.js +19 -2
  191. package/modules/categoryTranslation.js +4 -4
  192. package/modules/connectIdSystem.js +16 -1
  193. package/modules/currency.js +11 -11
  194. package/modules/dchain.js +2 -2
  195. package/modules/debugging/legacy.js +2 -2
  196. package/modules/eplanningBidAdapter.js +48 -2
  197. package/modules/lotamePanoramaIdSystem.js +10 -6
  198. package/modules/magniteAnalyticsAdapter.js +902 -0
  199. package/modules/magniteAnalyticsAdapter.md +18 -0
  200. package/modules/mass.js +2 -2
  201. package/modules/multibid/index.js +5 -5
  202. package/modules/pixfutureBidAdapter.js +46 -15
  203. package/modules/prebidServerBidAdapter/index.js +10 -6
  204. package/modules/priceFloors.js +8 -22
  205. package/modules/rubiconAnalyticsAdapter.js +14 -9
  206. package/modules/taboolaBidAdapter.js +4 -4
  207. package/modules/teadsIdSystem.js +234 -0
  208. package/modules/teadsIdSystem.md +22 -0
  209. package/modules/userId/index.js +21 -14
  210. package/modules/vrtcalBidAdapter.js +7 -1
  211. package/modules/yahoosspBidAdapter.js +1 -1
  212. package/package.json +1 -1
  213. package/src/adapters/bidderFactory.js +13 -11
  214. package/src/auction.js +140 -69
  215. package/src/constants.json +8 -0
  216. package/src/prebid.js +2 -3
  217. package/src/targeting.js +31 -14
  218. package/test/fixtures/fixtures.js +2 -1
  219. package/test/spec/auctionmanager_spec.js +109 -21
  220. package/test/spec/modules/aolBidAdapter_spec.js +42 -9
  221. package/test/spec/modules/appnexusBidAdapter_spec.js +24 -0
  222. package/test/spec/modules/connectIdSystem_spec.js +20 -0
  223. package/test/spec/modules/currency_spec.js +14 -6
  224. package/test/spec/modules/eplanningBidAdapter_spec.js +285 -1
  225. package/test/spec/modules/lotamePanoramaIdSystem_spec.js +0 -1
  226. package/test/spec/modules/magniteAnalyticsAdapter_spec.js +1942 -0
  227. package/test/spec/modules/prebidServerBidAdapter_spec.js +43 -11
  228. package/test/spec/modules/priceFloors_spec.js +5 -5
  229. package/test/spec/modules/rubiconAnalyticsAdapter_spec.js +2 -3
  230. package/test/spec/modules/taboolaBidAdapter_spec.js +110 -11
  231. package/test/spec/modules/teadsIdSystem_spec.js +271 -0
  232. package/test/spec/modules/userId_spec.js +39 -4
  233. package/test/spec/modules/vrtcalBidAdapter_spec.js +12 -1
  234. package/test/spec/modules/yahoosspBidAdapter_spec.js +45 -0
  235. package/test/spec/unit/core/bidderFactory_spec.js +66 -11
  236. package/test/spec/unit/core/targeting_spec.js +28 -9
  237. package/test/spec/unit/pbjs_api_spec.js +4 -2
@@ -0,0 +1,18 @@
1
+ # Magnite Analytics Adapter
2
+
3
+ ```
4
+ Module Name: Magnite Analytics Adapter
5
+ Module Type: Analytics Adapter
6
+ Maintainer: demand-manager-support@magnite.com
7
+ ```
8
+
9
+ ## How to configure?
10
+ ```
11
+ pbjs.enableAnalytics({
12
+ provider: 'magnite',
13
+ options: {
14
+ accountId: 12345, // The account id assigned to you by the Magnite Team
15
+ endpoint: 'http:localhost:9999/event' // Given by the Magnite Team
16
+ }
17
+ });
18
+ ```
package/modules/mass.js CHANGED
@@ -78,7 +78,7 @@ export function updateRenderers() {
78
78
  /**
79
79
  * Before hook for 'addBidResponse'.
80
80
  */
81
- export const addBidResponseHook = timedBidResponseHook('mass', function addBidResponseHook(next, adUnitCode, bid, {index = auctionManager.index} = {}) {
81
+ export const addBidResponseHook = timedBidResponseHook('mass', function addBidResponseHook(next, adUnitCode, bid, reject, {index = auctionManager.index} = {}) {
82
82
  let renderer;
83
83
  for (let i = 0; i < renderers.length; i++) {
84
84
  if (renderers[i].match(bid)) {
@@ -104,7 +104,7 @@ export const addBidResponseHook = timedBidResponseHook('mass', function addBidRe
104
104
  addListenerOnce();
105
105
  }
106
106
 
107
- next(adUnitCode, bid);
107
+ next(adUnitCode, bid, reject);
108
108
  });
109
109
 
110
110
  /**
@@ -99,7 +99,7 @@ export function adjustBidderRequestsHook(fn, bidderRequests) {
99
99
  * @param {String} ad unit code for bid
100
100
  * @param {Object} bid object
101
101
  */
102
- export const addBidResponseHook = timedBidResponseHook('multibid', function addBidResponseHook(fn, adUnitCode, bid) {
102
+ export const addBidResponseHook = timedBidResponseHook('multibid', function addBidResponseHook(fn, adUnitCode, bid, reject) {
103
103
  let floor = deepAccess(bid, 'floorData.floorValue');
104
104
 
105
105
  if (!config.getConfig('multibid')) resetMultiConfig();
@@ -107,7 +107,7 @@ export const addBidResponseHook = timedBidResponseHook('multibid', function addB
107
107
  // Else checks if multiconfig exists and bid bidderCode exists within config
108
108
  // Else continue with no modifications
109
109
  if (hasMultibid && multiConfig[bid.bidderCode] && deepAccess(bid, 'video.context') === 'adpod') {
110
- fn.call(this, adUnitCode, bid);
110
+ fn.call(this, adUnitCode, bid, reject);
111
111
  } else if (hasMultibid && multiConfig[bid.bidderCode]) {
112
112
  // Set property multibidPrefix on bid
113
113
  if (multiConfig[bid.bidderCode].prefix) bid.multibidPrefix = multiConfig[bid.bidderCode].prefix;
@@ -127,7 +127,7 @@ export const addBidResponseHook = timedBidResponseHook('multibid', function addB
127
127
  if (multiConfig[bid.bidderCode].prefix) bid.targetingBidder = multiConfig[bid.bidderCode].prefix + length;
128
128
  if (length === multiConfig[bid.bidderCode].maxbids) multibidUnits[adUnitCode][bid.bidderCode].maxReached = true;
129
129
 
130
- fn.call(this, adUnitCode, bid);
130
+ fn.call(this, adUnitCode, bid, reject);
131
131
  } else {
132
132
  logWarn(`Filtering multibid received from bidder ${bid.bidderCode}: ` + ((multibidUnits[adUnitCode][bid.bidderCode].maxReached) ? `Maximum bid limit reached for ad unit code ${adUnitCode}` : 'Bid cpm under floors value.'));
133
133
  }
@@ -137,10 +137,10 @@ export const addBidResponseHook = timedBidResponseHook('multibid', function addB
137
137
  deepSetValue(multibidUnits, [adUnitCode, bid.bidderCode], {ads: [bid]});
138
138
  if (multibidUnits[adUnitCode][bid.bidderCode].ads.length === multiConfig[bid.bidderCode].maxbids) multibidUnits[adUnitCode][bid.bidderCode].maxReached = true;
139
139
 
140
- fn.call(this, adUnitCode, bid);
140
+ fn.call(this, adUnitCode, bid, reject);
141
141
  }
142
142
  } else {
143
- fn.call(this, adUnitCode, bid);
143
+ fn.call(this, adUnitCode, bid, reject);
144
144
  }
145
145
  });
146
146
 
@@ -1,8 +1,8 @@
1
- import {registerBidder} from '../src/adapters/bidderFactory.js';
2
- import {getStorageManager} from '../src/storageManager.js';
3
- import {BANNER} from '../src/mediaTypes.js';
4
- import {config} from '../src/config.js';
5
- import {find, includes} from '../src/polyfill.js';
1
+ import { registerBidder } from '../src/adapters/bidderFactory.js';
2
+ import { getStorageManager } from '../src/storageManager.js';
3
+ import { BANNER } from '../src/mediaTypes.js';
4
+ import { config } from '../src/config.js';
5
+ import { find, includes } from '../src/polyfill.js';
6
6
  import {
7
7
  convertCamelToUnderscore,
8
8
  deepAccess,
@@ -13,14 +13,17 @@ import {
13
13
  isPlainObject,
14
14
  transformBidderParamKeywords
15
15
  } from '../src/utils.js';
16
- import {auctionManager} from '../src/auctionManager.js';
17
- import {hasPurpose1Consent} from '../src/utils/gpdr.js';
16
+ import { auctionManager } from '../src/auctionManager.js';
18
17
 
19
18
  const SOURCE = 'pbjs';
20
19
  const storageManager = getStorageManager({bidderCode: 'pixfuture'});
21
20
  const USER_PARAMS = ['age', 'externalUid', 'segments', 'gender', 'dnt', 'language'];
21
+ let pixID = '';
22
+ const GVLID = 839;
23
+
22
24
  export const spec = {
23
25
  code: 'pixfuture',
26
+ gvlid: GVLID,
24
27
  hostname: 'https://gosrv.pixfuture.com',
25
28
 
26
29
  getHostname() {
@@ -41,6 +44,10 @@ export const spec = {
41
44
  const tags = validBidRequests.map(bidToTag);
42
45
  const hostname = this.getHostname();
43
46
  return validBidRequests.map((bidRequest) => {
47
+ if (bidRequest.params.pix_id) {
48
+ pixID = bidRequest.params.pix_id
49
+ }
50
+
44
51
  let referer = '';
45
52
  if (bidderRequest && bidderRequest.refererInfo) {
46
53
  referer = bidderRequest.refererInfo.page || '';
@@ -123,7 +130,7 @@ export const spec = {
123
130
  const ret = {
124
131
  url: `${hostname}/pixservices`,
125
132
  method: 'POST',
126
- options: {withCredentials: false},
133
+ options: {withCredentials: true},
127
134
  data: {
128
135
  v: $$PREBID_GLOBAL$$.version,
129
136
  pageUrl: referer,
@@ -162,15 +169,39 @@ export const spec = {
162
169
 
163
170
  return bids;
164
171
  },
165
- getUserSyncs: function (syncOptions, bid, gdprConsent) {
166
- var pixid = '';
167
- if (typeof bid[0] === 'undefined' || bid[0] === null) { pixid = '0'; } else { pixid = bid[0].body.pix_id; }
168
- if (syncOptions.iframeEnabled && hasPurpose1Consent(gdprConsent)) {
169
- return [{
172
+ getUserSyncs: function (syncOptions, bid, gdprConsent, uspConsent) {
173
+ const syncs = [];
174
+
175
+ let syncurl = 'pixid=' + pixID;
176
+ let gdpr = (gdprConsent && gdprConsent.gdprApplies) ? 1 : 0;
177
+ let consent = gdprConsent ? encodeURIComponent(gdprConsent.consentString || '') : '';
178
+
179
+ // Attaching GDPR Consent Params in UserSync url
180
+ syncurl += '&gdprconcent=' + gdpr + '&adsync=' + consent;
181
+
182
+ // CCPA
183
+ if (uspConsent) {
184
+ syncurl += '&us_privacy=' + encodeURIComponent(uspConsent);
185
+ }
186
+
187
+ // coppa compliance
188
+ if (config.getConfig('coppa') === true) {
189
+ syncurl += '&coppa=1';
190
+ }
191
+
192
+ if (syncOptions.iframeEnabled) {
193
+ syncs.push({
170
194
  type: 'iframe',
171
- url: 'https://gosrv.pixfuture.com/cookiesync?adsync=' + gdprConsent.consentString + '&pixid=' + pixid + '&gdprconcent=' + gdprConsent.gdprApplies
172
- }];
195
+ url: 'https://gosrv.pixfuture.com/cookiesync?f=b&' + syncurl
196
+ });
197
+ } else {
198
+ syncs.push({
199
+ type: 'image',
200
+ url: 'https://gosrv.pixfuture.com/cookiesync?f=i&' + syncurl
201
+ });
173
202
  }
203
+
204
+ return syncs;
174
205
  }
175
206
  };
176
207
 
@@ -950,10 +950,6 @@ Object.assign(ORTB2.prototype, {
950
950
  (seatbid.bid || []).forEach(bid => {
951
951
  let bidRequest = this.getBidRequest(bid.impid, seatbid.seat);
952
952
  if (bidRequest == null) {
953
- if (!s2sConfig.allowUnknownBidderCodes) {
954
- logWarn(`PBS adapter received bid from unknown bidder (${seatbid.seat}), but 's2sConfig.allowUnknownBidderCodes' is not set. Ignoring bid.`);
955
- return;
956
- }
957
953
  // for stored impression, a request was made with bidder code `null`. Pick it up here so that NO_BID, BID_WON, etc events
958
954
  // can work as expected (otherwise, the original request will always result in NO_BID).
959
955
  bidRequest = this.getBidRequest(bid.impid, null);
@@ -968,6 +964,7 @@ Object.assign(ORTB2.prototype, {
968
964
  transactionId: this.adUnitsByImp[bid.impid].transactionId,
969
965
  auctionId: this.auctionId,
970
966
  });
967
+ bidObject.requestBidder = bidRequest?.bidder;
971
968
  bidObject.requestTimestamp = this.requestTimestamp;
972
969
  bidObject.cpm = cpm;
973
970
  if (bid?.ext?.prebid?.meta?.adaptercode) {
@@ -1158,8 +1155,15 @@ export function PrebidServer() {
1158
1155
  onBid: function ({adUnit, bid}) {
1159
1156
  const metrics = bid.metrics = s2sBidRequest.metrics.fork().renameWith();
1160
1157
  metrics.checkpoint('addBidResponse');
1161
- if (metrics.measureTime('addBidResponse.validate', () => isValid(adUnit, bid))) {
1162
- addBidResponse(adUnit, bid);
1158
+ if ((bid.requestId == null || bid.requestBidder == null) && !s2sBidRequest.s2sConfig.allowUnknownBidderCodes) {
1159
+ logWarn(`PBS adapter received bid from unknown bidder (${bid.bidder}), but 's2sConfig.allowUnknownBidderCodes' is not set. Ignoring bid.`);
1160
+ addBidResponse.reject(adUnit, bid, CONSTANTS.REJECTION_REASON.BIDDER_DISALLOWED);
1161
+ } else {
1162
+ if (metrics.measureTime('addBidResponse.validate', () => isValid(adUnit, bid))) {
1163
+ addBidResponse(adUnit, bid);
1164
+ } else {
1165
+ addBidResponse.reject(adUnit, bid, CONSTANTS.REJECTION_REASON.INVALID);
1166
+ }
1163
1167
  }
1164
1168
  }
1165
1169
  })
@@ -20,7 +20,6 @@ import {ajaxBuilder} from '../src/ajax.js';
20
20
  import * as events from '../src/events.js';
21
21
  import CONSTANTS from '../src/constants.json';
22
22
  import {getHook} from '../src/hook.js';
23
- import {createBid} from '../src/bidfactory.js';
24
23
  import {find} from '../src/polyfill.js';
25
24
  import {getRefererInfo} from '../src/refererDetection.js';
26
25
  import {bidderSettings} from '../src/bidderSettings.js';
@@ -694,11 +693,11 @@ function shouldFloorBid(floorData, floorInfo, bid) {
694
693
  * @summary The main driving force of floors. On bidResponse we hook in and intercept bidResponses.
695
694
  * And if the rule we find determines a bid should be floored we will do so.
696
695
  */
697
- export const addBidResponseHook = timedBidResponseHook('priceFloors', function addBidResponseHook(fn, adUnitCode, bid) {
696
+ export const addBidResponseHook = timedBidResponseHook('priceFloors', function addBidResponseHook(fn, adUnitCode, bid, reject) {
698
697
  let floorData = _floorDataForAuction[bid.auctionId];
699
698
  // if no floor data then bail
700
699
  if (!floorData || !bid || floorData.skipped) {
701
- return fn.call(this, adUnitCode, bid);
700
+ return fn.call(this, adUnitCode, bid, reject);
702
701
  }
703
702
 
704
703
  const matchingBidRequest = auctionManager.index.getBidRequest(bid);
@@ -708,7 +707,7 @@ export const addBidResponseHook = timedBidResponseHook('priceFloors', function a
708
707
 
709
708
  if (!floorInfo.matchingFloor) {
710
709
  logWarn(`${MODULE_NAME}: unable to determine a matching price floor for bidResponse`, bid);
711
- return fn.call(this, adUnitCode, bid);
710
+ return fn.call(this, adUnitCode, bid, reject);
712
711
  }
713
712
 
714
713
  // determine the base cpm to use based on if the currency matches the floor currency
@@ -724,7 +723,7 @@ export const addBidResponseHook = timedBidResponseHook('priceFloors', function a
724
723
  adjustedCpm = getGlobal().convertCurrency(bid.cpm, bidResponseCurrency.toUpperCase(), floorCurrency);
725
724
  } catch (err) {
726
725
  logError(`${MODULE_NAME}: Unable do get currency conversion for bidResponse to Floor Currency. Do you have Currency module enabled? ${bid}`);
727
- return fn.call(this, adUnitCode, bid);
726
+ return fn.call(this, adUnitCode, bid, reject);
728
727
  }
729
728
  }
730
729
 
@@ -737,25 +736,12 @@ export const addBidResponseHook = timedBidResponseHook('priceFloors', function a
737
736
  // now do the compare!
738
737
  if (shouldFloorBid(floorData, floorInfo, bid)) {
739
738
  // bid fails floor -> throw it out
740
- // create basic bid no-bid with necessary data fro analytics adapters
741
- let flooredBid = createBid(CONSTANTS.STATUS.NO_BID, bid.getIdentifiers());
742
- Object.assign(flooredBid, pick(bid, [
743
- 'floorData',
744
- 'width',
745
- 'height',
746
- 'mediaType',
747
- 'currency',
748
- 'originalCpm',
749
- 'originalCurrency',
750
- 'getCpmInNewCurrency',
751
- ]));
752
- flooredBid.status = CONSTANTS.BID_STATUS.BID_REJECTED;
753
- // if floor not met update bid with 0 cpm so it is not included downstream and marked as no-bid
754
- flooredBid.cpm = 0;
739
+ // continue with a "NO_BID" bid, TODO: remove this in v8
740
+ const flooredBid = reject(CONSTANTS.REJECTION_REASON.FLOOR_NOT_MET);
755
741
  logWarn(`${MODULE_NAME}: ${flooredBid.bidderCode}'s Bid Response for ${adUnitCode} was rejected due to floor not met (adjusted cpm: ${bid?.floorData?.cpmAfterAdjustments}, floor: ${floorInfo?.matchingFloor})`, bid);
756
- return fn.call(this, adUnitCode, flooredBid);
742
+ return fn.call(this, adUnitCode, flooredBid, reject);
757
743
  }
758
- return fn.call(this, adUnitCode, bid);
744
+ return fn.call(this, adUnitCode, bid, reject);
759
745
  });
760
746
 
761
747
  config.getConfig('floors', config => handleSetFloorsConfig(config.floors));
@@ -62,15 +62,20 @@ const cache = {
62
62
 
63
63
  const BID_REJECTED_IPF = 'rejected-ipf';
64
64
 
65
- export let rubiConf = {
66
- pvid: generateUUID().slice(0, 8),
67
- analyticsEventDelay: 0,
68
- dmBilling: {
69
- enabled: false,
70
- vendors: [],
71
- waitForAuction: true
65
+ export let rubiConf;
66
+ export const resetRubiConf = () => {
67
+ rubiConf = {
68
+ pvid: generateUUID().slice(0, 8),
69
+ analyticsEventDelay: 0,
70
+ dmBilling: {
71
+ enabled: false,
72
+ vendors: [],
73
+ waitForAuction: true
74
+ }
72
75
  }
73
- };
76
+ }
77
+ resetRubiConf();
78
+
74
79
  // we are saving these as global to this module so that if a pub accidentally overwrites the entire
75
80
  // rubicon object, then we do not lose other data
76
81
  config.getConfig('rubicon', config => {
@@ -418,7 +423,7 @@ function getBidPrice(bid) {
418
423
  }
419
424
  }
420
425
 
421
- export function parseBidResponse(bid, previousBidResponse, auctionFloorData) {
426
+ export function parseBidResponse(bid, previousBidResponse) {
422
427
  // The current bidResponse for this matching requestId/bidRequestId
423
428
  let responsePrice = getBidPrice(bid)
424
429
  // we need to compare it with the previous one (if there was one)
@@ -147,7 +147,7 @@ export const spec = {
147
147
  return [];
148
148
  }
149
149
 
150
- return bids.map((bid, id) => getBid(bid.bidId, currency, bidResponses[id])).filter(Boolean);
150
+ return bidResponses.map((bidResponse) => getBid(bids, currency, bidResponse)).filter(Boolean);
151
151
  },
152
152
  };
153
153
 
@@ -204,7 +204,7 @@ function getBidResponses({body}) {
204
204
 
205
205
  const {seatbid, cur} = body;
206
206
 
207
- if (!seatbid.length || !seatbid[0].bid) {
207
+ if (!seatbid.length || !seatbid[0].bid || !seatbid[0].bid.length) {
208
208
  return [];
209
209
  }
210
210
 
@@ -214,14 +214,14 @@ function getBidResponses({body}) {
214
214
  };
215
215
  }
216
216
 
217
- function getBid(requestId, currency, bidResponse) {
217
+ function getBid(bids, currency, bidResponse) {
218
218
  if (!bidResponse) {
219
219
  return;
220
220
  }
221
221
  const {
222
222
  price: cpm, crid: creativeId, adm: ad, w: width, h: height, exp: ttl, adomain: advertiserDomains, meta = {}
223
223
  } = bidResponse;
224
-
224
+ let requestId = bids[bidResponse.impid - 1].bidId;
225
225
  if (advertiserDomains && advertiserDomains.length > 0) {
226
226
  meta.advertiserDomains = advertiserDomains
227
227
  }
@@ -0,0 +1,234 @@
1
+ /**
2
+ * This module adds TeadsId to the User ID module
3
+ * The {@link module:modules/userId} module is required
4
+ * @module modules/teadsIdSystem
5
+ * @requires module:modules/userId
6
+ */
7
+
8
+ import {isStr, isNumber, logError, logInfo, isEmpty, timestamp} from '../src/utils.js'
9
+ import {ajax} from '../src/ajax.js';
10
+ import {submodule} from '../src/hook.js';
11
+ import {getStorageManager} from '../src/storageManager.js';
12
+ import {uspDataHandler} from '../src/adapterManager.js';
13
+
14
+ const MODULE_NAME = 'teadsId';
15
+ const GVL_ID = 132;
16
+ const FP_TEADS_ID_COOKIE_NAME = '_tfpvi';
17
+ const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT';
18
+
19
+ export const gdprStatus = {
20
+ GDPR_DOESNT_APPLY: 0,
21
+ CMP_NOT_FOUND_OR_ERROR: 22,
22
+ GDPR_APPLIES_PUBLISHER: 12,
23
+ };
24
+
25
+ export const gdprReason = {
26
+ GDPR_DOESNT_APPLY: 0,
27
+ CMP_NOT_FOUND: 220,
28
+ GDPR_APPLIES_PUBLISHER_CLASSIC: 120,
29
+ };
30
+
31
+ export const storage = getStorageManager({gvlid: GVL_ID, moduleName: MODULE_NAME});
32
+
33
+ /** @type {Submodule} */
34
+ export const teadsIdSubmodule = {
35
+ /**
36
+ * used to link submodule with config
37
+ * @type {string}
38
+ */
39
+ name: MODULE_NAME,
40
+ /**
41
+ * decode the stored id value for passing to bid requests
42
+ * @function
43
+ * @param {string} value
44
+ * @returns {{teadsId:string}}
45
+ */
46
+ decode(value) {
47
+ return {teadsId: value}
48
+ },
49
+ /**
50
+ * performs action to obtain id and return a value in the callback's response argument
51
+ * @function
52
+ * @param {SubmoduleConfig} [submoduleConfig]
53
+ * @param {ConsentData} [consentData]
54
+ * @returns {IdResponse|undefined}
55
+ */
56
+ getId(submoduleConfig, consentData) {
57
+ const resp = function (callback) {
58
+ const url = buildAnalyticsTagUrl(submoduleConfig, consentData);
59
+
60
+ const callbacks = {
61
+ success: (bodyResponse, responseObj) => {
62
+ if (responseObj && responseObj.status === 200) {
63
+ if (isStr(bodyResponse) && !isEmpty(bodyResponse)) {
64
+ const cookiesMaxAge = getTimestampFromDays(365); // 1 year
65
+ const expirationCookieDate = getCookieExpirationDate(cookiesMaxAge);
66
+ storage.setCookie(FP_TEADS_ID_COOKIE_NAME, bodyResponse, expirationCookieDate);
67
+ callback(bodyResponse);
68
+ } else {
69
+ storage.setCookie(FP_TEADS_ID_COOKIE_NAME, '', EXPIRED_COOKIE_DATE);
70
+ callback();
71
+ }
72
+ } else {
73
+ logInfo(`${MODULE_NAME}: Server error while fetching ID`);
74
+ callback();
75
+ }
76
+ },
77
+ error: error => {
78
+ logError(`${MODULE_NAME}: ID fetch encountered an error`, error);
79
+ callback();
80
+ }
81
+ };
82
+
83
+ ajax(url, callbacks, undefined, {method: 'GET'});
84
+ };
85
+ return {callback: resp};
86
+ }
87
+ };
88
+
89
+ /**
90
+ * Build the full URL from the Submodule config & consentData
91
+ * @param submoduleConfig
92
+ * @param consentData
93
+ * @returns {string}
94
+ */
95
+ export function buildAnalyticsTagUrl(submoduleConfig, consentData) {
96
+ const pubId = getPublisherId(submoduleConfig);
97
+ const teadsViewerId = getTeadsViewerId();
98
+ const status = getGdprStatus(consentData);
99
+ const gdprConsentString = getGdprConsentString(consentData);
100
+ const ccpaConsentString = getCcpaConsentString(uspDataHandler?.getConsentData());
101
+ const gdprReason = getGdprReasonFromStatus(status);
102
+ const params = {
103
+ analytics_tag_id: pubId,
104
+ tfpvi: teadsViewerId,
105
+ gdpr_consent: gdprConsentString,
106
+ gdpr_status: status,
107
+ gdpr_reason: gdprReason,
108
+ ccpa_consent: ccpaConsentString,
109
+ sv: 'prebid-v1',
110
+ };
111
+
112
+ const url = 'https://at.teads.tv/fpc';
113
+ const queryParams = new URLSearchParams();
114
+
115
+ for (const param in params) {
116
+ queryParams.append(param, params[param]);
117
+ }
118
+
119
+ return url + '?' + queryParams.toString();
120
+ }
121
+
122
+ /**
123
+ * Extract the Publisher ID from the Submodule config
124
+ * @returns {string}
125
+ * @param submoduleConfig
126
+ */
127
+ export function getPublisherId(submoduleConfig) {
128
+ const pubId = submoduleConfig?.params?.pubId;
129
+ const prefix = 'PUB_';
130
+ if (isNumber(pubId)) {
131
+ return prefix + pubId.toString();
132
+ }
133
+ if (isStr(pubId) && parseInt(pubId)) {
134
+ return prefix + pubId;
135
+ }
136
+ return '';
137
+ }
138
+
139
+ /**
140
+ * Extract the GDPR status from the given consentData
141
+ * @param consentData
142
+ * @returns {number}
143
+ */
144
+ export function getGdprStatus(consentData) {
145
+ const gdprApplies = consentData?.gdprApplies;
146
+ if (gdprApplies === true) {
147
+ return gdprStatus.GDPR_APPLIES_PUBLISHER;
148
+ } else if (gdprApplies === false) {
149
+ return gdprStatus.GDPR_DOESNT_APPLY;
150
+ } else {
151
+ return gdprStatus.CMP_NOT_FOUND_OR_ERROR;
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Extract the GDPR consent string from the given consentData
157
+ * @param consentData
158
+ * @returns {string}
159
+ */
160
+ export function getGdprConsentString(consentData) {
161
+ const consentString = consentData?.consentString;
162
+ if (isStr(consentString)) {
163
+ return consentString;
164
+ } else {
165
+ return '';
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Map the GDPR reason from the given GDPR status
171
+ * @param status
172
+ * @returns {number}
173
+ */
174
+ function getGdprReasonFromStatus(status) {
175
+ switch (status) {
176
+ case gdprStatus.GDPR_DOESNT_APPLY:
177
+ return gdprReason.GDPR_DOESNT_APPLY;
178
+ case gdprStatus.CMP_NOT_FOUND_OR_ERROR:
179
+ return gdprReason.CMP_NOT_FOUND;
180
+ case gdprStatus.GDPR_APPLIES_PUBLISHER:
181
+ return gdprReason.GDPR_APPLIES_PUBLISHER_CLASSIC;
182
+ default:
183
+ return -1;
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Return the well formatted CCPA consent string
189
+ * @param ccpaConsentString
190
+ * @returns {string|*}
191
+ */
192
+ export function getCcpaConsentString(ccpaConsentString) {
193
+ if (isStr(ccpaConsentString)) {
194
+ return ccpaConsentString;
195
+ } else {
196
+ return '';
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Get the cookie expiration date string from a given Date and a max age
202
+ * @param {number} maxAge
203
+ * @returns {string}
204
+ */
205
+ export function getCookieExpirationDate(maxAge) {
206
+ return new Date(timestamp() + maxAge).toUTCString()
207
+ }
208
+
209
+ /**
210
+ * Get cookie from Cookie or Local Storage
211
+ * @returns {string}
212
+ */
213
+ function getTeadsViewerId() {
214
+ const teadsViewerId = readCookie()
215
+ if (isStr(teadsViewerId)) {
216
+ return teadsViewerId
217
+ } else {
218
+ return '';
219
+ }
220
+ }
221
+
222
+ function readCookie() {
223
+ return storage.cookiesAreEnabled(null) ? storage.getCookie(FP_TEADS_ID_COOKIE_NAME, null) : null;
224
+ }
225
+
226
+ /**
227
+ * Return a number of milliseconds from given days number
228
+ * @param days
229
+ * @returns {number}
230
+ */
231
+ export function getTimestampFromDays(days) {
232
+ return days * 24 * 60 * 60 * 1000;
233
+ }
234
+ submodule('userId', teadsIdSubmodule);
@@ -0,0 +1,22 @@
1
+ # Overview
2
+
3
+ Module Name: Teads Id System
4
+ Module Type: User Id System
5
+ Maintainer: innov-ssp@teads.com
6
+
7
+ # Description
8
+
9
+ Teads user identification system. GDPR & CCPA compliant.
10
+
11
+ ## Example configuration for publishers:
12
+
13
+ pbjs.setConfig({
14
+ userSync: {
15
+ userIds: [{
16
+ name: 'teadsId',
17
+ params: {
18
+ pubId: 1234
19
+ }
20
+ }]
21
+ }
22
+ });
@@ -425,6 +425,7 @@ function processSubmoduleCallbacks(submodules, cb) {
425
425
  }
426
426
  // cache decoded value (this is copied to every adUnit bid)
427
427
  submodule.idObj = submodule.submodule.decode(idObj, submodule.config);
428
+ updatePPID(submodule.idObj);
428
429
  } else {
429
430
  logInfo(`${MODULE_NAME}: ${submodule.submodule.name} - request id responded with an empty value`);
430
431
  }
@@ -613,9 +614,9 @@ function idSystemInitializer({delay = GreedyPromise.timeout} = {}) {
613
614
 
614
615
  let initIdSystem;
615
616
 
616
- function getPPID() {
617
+ function getPPID(eids = getUserIdsAsEids() || []) {
617
618
  // userSync.ppid should be one of the 'source' values in getUserIdsAsEids() eg pubcid.org or id5-sync.com
618
- const matchingUserId = ppidSource && (getUserIdsAsEids() || []).find(userID => userID.source === ppidSource);
619
+ const matchingUserId = ppidSource && eids.find(userID => userID.source === ppidSource);
619
620
  if (matchingUserId && typeof deepAccess(matchingUserId, 'uids.0.id') === 'string') {
620
621
  const ppidValue = matchingUserId.uids[0].id.replace(/[\W_]/g, '');
621
622
  if (ppidValue.length >= 32 && ppidValue.length <= 150) {
@@ -642,18 +643,6 @@ export const requestBidsHook = timedAuctionHook('userId', function requestBidsHo
642
643
  ]).then(() => {
643
644
  // pass available user id data to bid adapters
644
645
  addIdDataToAdUnitBids(reqBidsConfigObj.adUnits || getGlobal().adUnits, initializedSubmodules);
645
- const ppid = getPPID();
646
- if (ppid) {
647
- if (isGptPubadsDefined()) {
648
- window.googletag.pubads().setPublisherProvidedId(ppid);
649
- } else {
650
- window.googletag = window.googletag || {};
651
- window.googletag.cmd = window.googletag.cmd || [];
652
- window.googletag.cmd.push(function() {
653
- window.googletag.pubads().setPublisherProvidedId(ppid);
654
- });
655
- }
656
- }
657
646
  uidMetrics().join(useMetrics(reqBidsConfigObj.metrics), {propagate: false, includeGroups: true});
658
647
  // calling fn allows prebid to continue processing
659
648
  fn.call(this, reqBidsConfigObj);
@@ -853,6 +842,24 @@ function populateSubmoduleId(submodule, consentData, storedConsentData, forceRef
853
842
  if (response.id) { submodule.idObj = submodule.submodule.decode(response.id, submodule.config); }
854
843
  }
855
844
  }
845
+ updatePPID(submodule.idObj);
846
+ }
847
+
848
+ function updatePPID(userIds = getUserIds()) {
849
+ if (userIds && ppidSource) {
850
+ const ppid = getPPID(createEidsArray(userIds));
851
+ if (ppid) {
852
+ if (isGptPubadsDefined()) {
853
+ window.googletag.pubads().setPublisherProvidedId(ppid);
854
+ } else {
855
+ window.googletag = window.googletag || {};
856
+ window.googletag.cmd = window.googletag.cmd || [];
857
+ window.googletag.cmd.push(function() {
858
+ window.googletag.pubads().setPublisherProvidedId(ppid);
859
+ });
860
+ }
861
+ }
862
+ }
856
863
  }
857
864
 
858
865
  function initSubmodules(dest, submodules, consentData, forceRefresh = false) {