prebid.js 6.20.0 → 6.22.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 (159) hide show
  1. package/.circleci/config.yml +0 -1
  2. package/dist/33acrossBidAdapter.js +1 -1
  3. package/dist/adagioBidAdapter.js +1 -1
  4. package/dist/adbookpspBidAdapter.js +1 -1
  5. package/dist/adgenerationBidAdapter.js +1 -1
  6. package/dist/adomikAnalyticsAdapter.js +1 -1
  7. package/dist/adotBidAdapter.js +1 -1
  8. package/dist/adrelevantisBidAdapter.js +1 -1
  9. package/dist/adxcgBidAdapter.js +1 -1
  10. package/dist/ajaBidAdapter.js +1 -1
  11. package/dist/amxBidAdapter.js +1 -1
  12. package/dist/amxIdSystem.js +1 -1
  13. package/dist/apacdexBidAdapter.js +1 -1
  14. package/dist/appierAnalyticsAdapter.js +1 -1
  15. package/dist/appnexusBidAdapter.js +1 -1
  16. package/dist/asoBidAdapter.js +1 -1
  17. package/dist/audiencerunBidAdapter.js +1 -1
  18. package/dist/axonixBidAdapter.js +1 -1
  19. package/dist/betweenBidAdapter.js +1 -1
  20. package/dist/bidglassBidAdapter.js +1 -1
  21. package/dist/big-richmediaBidAdapter.js +1 -1
  22. package/dist/bridgewellBidAdapter.js +1 -1
  23. package/dist/brightMountainMediaBidAdapter.js +1 -1
  24. package/dist/cointrafficBidAdapter.js +1 -1
  25. package/dist/colossussspBidAdapter.js +1 -1
  26. package/dist/concertBidAdapter.js +1 -1
  27. package/dist/connectadBidAdapter.js +1 -1
  28. package/dist/consentManagement.js +1 -1
  29. package/dist/consentManagementUsp.js +1 -1
  30. package/dist/consumableBidAdapter.js +1 -1
  31. package/dist/conversantBidAdapter.js +1 -1
  32. package/dist/craftBidAdapter.js +1 -1
  33. package/dist/criteoBidAdapter.js +1 -1
  34. package/dist/dspxBidAdapter.js +1 -1
  35. package/dist/e_volutionBidAdapter.js +1 -1
  36. package/dist/eplanningBidAdapter.js +1 -1
  37. package/dist/ftrackIdSystem.js +1 -1
  38. package/dist/glimpseBidAdapter.js +1 -1
  39. package/dist/gmosspBidAdapter.js +1 -1
  40. package/dist/goldbachBidAdapter.js +1 -1
  41. package/dist/gridBidAdapter.js +1 -1
  42. package/dist/gridNMBidAdapter.js +1 -1
  43. package/dist/gumgumBidAdapter.js +1 -1
  44. package/dist/h12mediaBidAdapter.js +1 -1
  45. package/dist/id5IdSystem.js +1 -1
  46. package/dist/improvedigitalBidAdapter.js +1 -1
  47. package/dist/inmarBidAdapter.js +1 -1
  48. package/dist/insticatorBidAdapter.js +1 -1
  49. package/dist/ixBidAdapter.js +1 -1
  50. package/dist/justpremiumBidAdapter.js +1 -1
  51. package/dist/konduitAnalyticsAdapter.js +1 -1
  52. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  53. package/dist/logicadBidAdapter.js +1 -1
  54. package/dist/loglyliftBidAdapter.js +1 -1
  55. package/dist/malltvAnalyticsAdapter.js +1 -1
  56. package/dist/marsmediaBidAdapter.js +1 -1
  57. package/dist/mediafuseBidAdapter.js +1 -1
  58. package/dist/mediasquareBidAdapter.js +1 -1
  59. package/dist/mgidBidAdapter.js +1 -1
  60. package/dist/minutemediaBidAdapter.js +1 -1
  61. package/dist/mobfoxpbBidAdapter.js +1 -0
  62. package/dist/nextMillenniumBidAdapter.js +1 -1
  63. package/dist/nexx360BidAdapter.js +1 -1
  64. package/dist/not-for-prod/prebid.js +118 -117
  65. package/dist/oguryBidAdapter.js +1 -1
  66. package/dist/oneVideoBidAdapter.js +1 -1
  67. package/dist/onetagBidAdapter.js +1 -1
  68. package/dist/ooloAnalyticsAdapter.js +1 -1
  69. package/dist/otmBidAdapter.js +1 -1
  70. package/dist/outbrainBidAdapter.js +1 -1
  71. package/dist/parrableIdSystem.js +1 -1
  72. package/dist/pixfutureBidAdapter.js +1 -1
  73. package/dist/prebid-core.js +3 -3
  74. package/dist/prebidServerBidAdapter.js +1 -1
  75. package/dist/publinkIdSystem.js +1 -1
  76. package/dist/pubmaticBidAdapter.js +1 -1
  77. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  78. package/dist/pxyzBidAdapter.js +1 -1
  79. package/dist/quantcastBidAdapter.js +1 -1
  80. package/dist/readpeakBidAdapter.js +1 -1
  81. package/dist/relaidoBidAdapter.js +1 -1
  82. package/dist/rhythmoneBidAdapter.js +1 -1
  83. package/dist/riseBidAdapter.js +1 -1
  84. package/dist/rubiconAnalyticsAdapter.js +1 -1
  85. package/dist/rubiconBidAdapter.js +1 -1
  86. package/dist/seedingAllianceBidAdapter.js +1 -1
  87. package/dist/seedtagBidAdapter.js +1 -1
  88. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  89. package/dist/sharethroughBidAdapter.js +1 -1
  90. package/dist/smaatoBidAdapter.js +1 -1
  91. package/dist/smartadserverBidAdapter.js +1 -1
  92. package/dist/smartxBidAdapter.js +1 -1
  93. package/dist/smilewantedBidAdapter.js +1 -1
  94. package/dist/sonobiBidAdapter.js +1 -1
  95. package/dist/sortableBidAdapter.js +1 -1
  96. package/dist/sovrnAnalyticsAdapter.js +1 -1
  97. package/dist/sovrnBidAdapter.js +1 -1
  98. package/dist/sspBCBidAdapter.js +1 -1
  99. package/dist/sublimeBidAdapter.js +1 -1
  100. package/dist/synacormediaBidAdapter.js +1 -1
  101. package/dist/targetVideoBidAdapter.js +1 -1
  102. package/dist/teadsBidAdapter.js +1 -1
  103. package/dist/trionBidAdapter.js +1 -1
  104. package/dist/tripleliftBidAdapter.js +1 -1
  105. package/dist/trustxBidAdapter.js +1 -1
  106. package/dist/ttdBidAdapter.js +1 -1
  107. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  108. package/dist/underdogmediaBidAdapter.js +1 -1
  109. package/dist/undertoneBidAdapter.js +1 -1
  110. package/dist/vidazooBidAdapter.js +1 -1
  111. package/dist/videobyteBidAdapter.js +1 -1
  112. package/dist/visxBidAdapter.js +1 -1
  113. package/dist/vuukleBidAdapter.js +1 -1
  114. package/dist/widespaceBidAdapter.js +1 -1
  115. package/dist/winrBidAdapter.js +1 -1
  116. package/dist/yahoosspBidAdapter.js +1 -1
  117. package/dist/yieldmoBidAdapter.js +1 -1
  118. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  119. package/modules/adomikAnalyticsAdapter.js +67 -43
  120. package/modules/adotBidAdapter.js +1 -1
  121. package/modules/apacdexBidAdapter.js +52 -41
  122. package/modules/audiencerunBidAdapter.js +75 -22
  123. package/modules/betweenBidAdapter.js +1 -1
  124. package/modules/cointrafficBidAdapter.js +1 -1
  125. package/modules/colossussspBidAdapter.js +5 -1
  126. package/modules/consentManagement.js +4 -4
  127. package/modules/consentManagementUsp.js +2 -2
  128. package/modules/e_volutionBidAdapter.js +19 -1
  129. package/modules/ftrackIdSystem.js +16 -2
  130. package/modules/ftrackIdSystem.md +12 -1
  131. package/modules/malltvAnalyticsAdapter.js +1 -1
  132. package/modules/mobfoxpbBidAdapter.js +135 -0
  133. package/modules/mobfoxpbBidAdapter.md +3 -3
  134. package/modules/nextMillenniumBidAdapter.js +6 -2
  135. package/modules/nexx360BidAdapter.js +14 -4
  136. package/modules/otmBidAdapter.js +43 -35
  137. package/modules/prebidServerBidAdapter/index.js +58 -14
  138. package/modules/pubmaticBidAdapter.js +34 -2
  139. package/modules/seedingAllianceBidAdapter.js +8 -4
  140. package/package.json +1 -1
  141. package/src/adapters/bidderFactory.js +17 -0
  142. package/src/auction.js +1 -7
  143. package/test/spec/auctionmanager_spec.js +2 -0
  144. package/test/spec/modules/adomikAnalyticsAdapter_spec.js +133 -33
  145. package/test/spec/modules/adotBidAdapter_spec.js +1 -1
  146. package/test/spec/modules/apacdexBidAdapter_spec.js +6 -6
  147. package/test/spec/modules/audiencerunBidAdapter_spec.js +185 -97
  148. package/test/spec/modules/cointrafficBidAdapter_spec.js +1 -1
  149. package/test/spec/modules/colossussspBidAdapter_spec.js +97 -3
  150. package/test/spec/modules/consentManagementUsp_spec.js +1 -0
  151. package/test/spec/modules/consentManagement_spec.js +22 -0
  152. package/test/spec/modules/e_volutionBidAdapter_spec.js +67 -10
  153. package/test/spec/modules/ftrackIdSystem_spec.js +75 -1
  154. package/test/spec/modules/mobfoxpbBidAdapter_spec.js +307 -0
  155. package/test/spec/modules/nexx360BidAdapter_spec.js +49 -0
  156. package/test/spec/modules/otmBidAdapter_spec.js +32 -11
  157. package/test/spec/modules/prebidServerBidAdapter_spec.js +200 -0
  158. package/test/spec/modules/pubmaticBidAdapter_spec.js +129 -0
  159. package/test/spec/unit/core/bidderFactory_spec.js +137 -0
@@ -1,10 +1,21 @@
1
1
  import { registerBidder } from '../src/adapters/bidderFactory.js';
2
- import {logInfo, logError, getBidIdParameter, _each, getValue, isFn, isPlainObject} from '../src/utils.js';
2
+ import {
3
+ logInfo,
4
+ logError,
5
+ getBidIdParameter,
6
+ _each,
7
+ getValue,
8
+ isFn,
9
+ isPlainObject,
10
+ isArray,
11
+ isStr,
12
+ isNumber,
13
+ } from '../src/utils.js';
3
14
  import { BANNER } from '../src/mediaTypes.js';
4
15
 
5
16
  const BIDDER_CODE = 'otm';
6
17
  const OTM_BID_URL = 'https://ssp.otm-r.com/adjson';
7
- const DEF_CUR = 'RUB'
18
+ const DEFAULT_CURRENCY = 'RUB'
8
19
 
9
20
  export const spec = {
10
21
 
@@ -19,7 +30,7 @@ export const spec = {
19
30
  * @return boolean True if this is a valid bid, and false otherwise.
20
31
  */
21
32
  isBidRequestValid: function (bid) {
22
- return !!bid.params.tid;
33
+ return Boolean(bid.params.tid);
23
34
  },
24
35
 
25
36
  /**
@@ -33,43 +44,41 @@ export const spec = {
33
44
  logInfo('validBidRequests', validBidRequests);
34
45
 
35
46
  const bidRequests = [];
36
- let tz = new Date().getTimezoneOffset()
37
- let referrer = '';
38
- if (bidderRequest && bidderRequest.refererInfo) {
39
- referrer = bidderRequest.refererInfo.referer;
40
- }
47
+ const tz = new Date().getTimezoneOffset()
48
+ const referrer = bidderRequest && bidderRequest.refererInfo ? bidderRequest.refererInfo.referer : '';
41
49
 
42
50
  _each(validBidRequests, (bid) => {
43
- let domain = getValue(bid.params, 'domain') || ''
44
- let tid = getValue(bid.params, 'tid')
45
- let cur = getValue(bid.params, 'currency') || DEF_CUR
46
- let bidid = getBidIdParameter('bidId', bid)
47
- let transactionid = getBidIdParameter('transactionId', bid)
48
- let auctionid = getBidIdParameter('auctionId', bid)
49
- let bidfloor = _getBidFloor(bid)
51
+ let topOrigin = ''
52
+ try {
53
+ if (isStr(referrer)) topOrigin = new URL(referrer).host
54
+ } catch (e) { /* do nothing */ }
55
+ const domain = isStr(bid.params.domain) ? bid.params.domain : topOrigin
56
+ const cur = getValue(bid.params, 'currency') || DEFAULT_CURRENCY
57
+ const bidid = getBidIdParameter('bidId', bid)
58
+ const transactionid = getBidIdParameter('transactionId', bid)
59
+ const auctionid = getBidIdParameter('auctionId', bid)
60
+ const bidfloor = _getBidFloor(bid)
50
61
 
51
62
  _each(bid.sizes, size => {
52
- let width = 0;
53
- let height = 0;
54
- if (size.length && typeof size[0] === 'number' && typeof size[1] === 'number') {
55
- width = size[0];
56
- height = size[1];
57
- }
63
+ const hasSizes = isArray(size) && isNumber(size[0]) && isNumber(size[1])
64
+ const width = hasSizes ? size[0] : 0;
65
+ const height = hasSizes ? size[1] : 0;
66
+
58
67
  bidRequests.push({
59
68
  method: 'GET',
60
69
  url: OTM_BID_URL,
61
70
  data: {
62
- tz: tz,
71
+ tz,
63
72
  w: width,
64
73
  h: height,
65
- domain: domain,
74
+ domain,
66
75
  l: referrer,
67
- s: tid,
68
- cur: cur,
69
- bidid: bidid,
70
- transactionid: transactionid,
71
- auctionid: auctionid,
72
- bidfloor: bidfloor,
76
+ s: bid.params.tid,
77
+ cur,
78
+ bidid,
79
+ transactionid,
80
+ auctionid,
81
+ bidfloor,
73
82
  },
74
83
  })
75
84
  })
@@ -81,10 +90,9 @@ export const spec = {
81
90
  * Generate response.
82
91
  *
83
92
  * @param serverResponse
84
- * @param request
85
93
  * @returns {[]|*[]}
86
94
  */
87
- interpretResponse: function (serverResponse, request) {
95
+ interpretResponse: function (serverResponse) {
88
96
  logInfo('serverResponse', serverResponse.body);
89
97
 
90
98
  const responsesBody = serverResponse ? serverResponse.body : {};
@@ -102,7 +110,7 @@ export const spec = {
102
110
  width: bid.w,
103
111
  height: bid.h,
104
112
  creativeId: bid.creativeid,
105
- currency: bid.currency || 'RUB',
113
+ currency: bid.currency || DEFAULT_CURRENCY,
106
114
  netRevenue: true,
107
115
  ad: bid.ad,
108
116
  ttl: bid.ttl,
@@ -132,12 +140,12 @@ function _getBidFloor(bid) {
132
140
  return bid.params.bidfloor ? bid.params.bidfloor : 0;
133
141
  }
134
142
 
135
- let floor = bid.getFloor({
136
- currency: DEF_CUR,
143
+ const floor = bid.getFloor({
144
+ currency: DEFAULT_CURRENCY,
137
145
  mediaType: '*',
138
146
  size: '*'
139
147
  });
140
- if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === DEF_CUR) {
148
+ if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === DEFAULT_CURRENCY) {
141
149
  return floor.floor;
142
150
  }
143
151
  return 0;
@@ -38,6 +38,7 @@ import {find, includes} from '../../src/polyfill.js';
38
38
  import { S2S_VENDORS } from './config.js';
39
39
  import { ajax } from '../../src/ajax.js';
40
40
  import {hook} from '../../src/hook.js';
41
+ import {getGlobal} from '../../src/prebidGlobal.js';
41
42
 
42
43
  const getConfig = config.getConfig;
43
44
 
@@ -755,21 +756,64 @@ Object.assign(ORTB2.prototype, {
755
756
  deepSetValue(imp, 'ext.prebid.storedauctionresponse.id', storedAuctionResponseBid.storedAuctionResponse.toString());
756
757
  }
757
758
 
758
- const getFloorBid = find(firstBidRequest.bids, bid => bid.adUnitCode === adUnit.code && typeof bid.getFloor === 'function');
759
+ const floor = (() => {
760
+ // we have to pick a floor for the imp - here we attempt to find the minimum floor
761
+ // across all bids for this adUnit
762
+
763
+ const convertCurrency = typeof getGlobal().convertCurrency !== 'function'
764
+ ? (amount) => amount
765
+ : (amount, from, to) => {
766
+ if (from === to) return amount;
767
+ let result = null;
768
+ try {
769
+ result = getGlobal().convertCurrency(amount, from, to);
770
+ } catch (e) {
771
+ }
772
+ return result;
773
+ }
774
+ const s2sCurrency = config.getConfig('currency.adServerCurrency') || DEFAULT_S2S_CURRENCY;
775
+
776
+ return adUnit.bids
777
+ .map((bid) => this.getBidRequest(imp.id, bid.bidder))
778
+ .map((bid) => {
779
+ if (!bid || typeof bid.getFloor !== 'function') return;
780
+ try {
781
+ const {currency, floor} = bid.getFloor({
782
+ currency: s2sCurrency
783
+ });
784
+ return {
785
+ currency,
786
+ floor: parseFloat(floor)
787
+ }
788
+ } catch (e) {
789
+ logError('PBS: getFloor threw an error: ', e);
790
+ }
791
+ })
792
+ .reduce((min, floor) => {
793
+ // if any bid does not have a valid floor, do not attempt to send any to PBS
794
+ if (floor == null || floor.currency == null || floor.floor == null || isNaN(floor.floor)) {
795
+ min.min = null;
796
+ }
797
+ if (min.min === null) {
798
+ return min;
799
+ }
800
+ // otherwise, pick the minimum one (or, in some strange confluence of circumstances, the one in the best currency)
801
+ if (min.ref == null) {
802
+ min.ref = min.min = floor;
803
+ } else {
804
+ const value = convertCurrency(floor.floor, floor.currency, min.ref.currency);
805
+ if (value != null && value < min.ref.floor) {
806
+ min.ref.floor = value;
807
+ min.min = floor;
808
+ }
809
+ }
810
+ return min;
811
+ }, {}).min
812
+ })();
759
813
 
760
- if (getFloorBid) {
761
- let floorInfo;
762
- try {
763
- floorInfo = getFloorBid.getFloor({
764
- currency: config.getConfig('currency.adServerCurrency') || DEFAULT_S2S_CURRENCY,
765
- });
766
- } catch (e) {
767
- logError('PBS: getFloor threw an error: ', e);
768
- }
769
- if (floorInfo && floorInfo.currency && !isNaN(parseFloat(floorInfo.floor))) {
770
- imp.bidfloor = parseFloat(floorInfo.floor);
771
- imp.bidfloorcur = floorInfo.currency
772
- }
814
+ if (floor) {
815
+ imp.bidfloor = floor.floor;
816
+ imp.bidfloorcur = floor.currency
773
817
  }
774
818
 
775
819
  if (imp.banner || imp.video || imp.native) {
@@ -977,6 +977,25 @@ function _blockedIabCategoriesValidation(payload, blockedIabCategories) {
977
977
  }
978
978
  }
979
979
 
980
+ function _allowedIabCategoriesValidation(payload, allowedIabCategories) {
981
+ allowedIabCategories = allowedIabCategories
982
+ .filter(function(category) {
983
+ if (typeof category === 'string') { // returns only strings
984
+ return true;
985
+ } else {
986
+ logWarn(LOG_WARN_PREFIX + 'acat: Each category should be a string, ignoring category: ' + category);
987
+ return false;
988
+ }
989
+ })
990
+ .map(category => category.trim()) // trim all categories
991
+ .filter((category, index, arr) => arr.indexOf(category) === index); // return unique values only
992
+
993
+ if (allowedIabCategories.length > 0) {
994
+ logWarn(LOG_WARN_PREFIX + 'acat: Selected: ', allowedIabCategories);
995
+ payload.ext.acat = allowedIabCategories;
996
+ }
997
+ }
998
+
980
999
  function _assignRenderer(newBid, request) {
981
1000
  let bidParams, context, adUnitCode;
982
1001
  if (request.bidderRequest && request.bidderRequest.bids) {
@@ -1082,6 +1101,7 @@ export const spec = {
1082
1101
  var dctrArr = [];
1083
1102
  var bid;
1084
1103
  var blockedIabCategories = [];
1104
+ var allowedIabCategories = [];
1085
1105
 
1086
1106
  validBidRequests.forEach(originalBid => {
1087
1107
  bid = deepClone(originalBid);
@@ -1113,6 +1133,9 @@ export const spec = {
1113
1133
  if (bid.params.hasOwnProperty('bcat') && isArray(bid.params.bcat)) {
1114
1134
  blockedIabCategories = blockedIabCategories.concat(bid.params.bcat);
1115
1135
  }
1136
+ if (bid.params.hasOwnProperty('acat') && isArray(bid.params.acat)) {
1137
+ allowedIabCategories = allowedIabCategories.concat(bid.params.acat);
1138
+ }
1116
1139
  var impObj = _createImpressionObject(bid, conf);
1117
1140
  if (impObj) {
1118
1141
  payload.imp.push(impObj);
@@ -1182,7 +1205,7 @@ export const spec = {
1182
1205
  }
1183
1206
 
1184
1207
  _handleEids(payload, validBidRequests);
1185
- _blockedIabCategoriesValidation(payload, blockedIabCategories);
1208
+
1186
1209
  _handleFlocId(payload, validBidRequests);
1187
1210
  // First Party Data
1188
1211
  const commonFpd = config.getConfig('ortb2') || {};
@@ -1192,7 +1215,16 @@ export const spec = {
1192
1215
  if (commonFpd.user) {
1193
1216
  mergeDeep(payload, {user: commonFpd.user});
1194
1217
  }
1195
-
1218
+ if (commonFpd.bcat) {
1219
+ blockedIabCategories = blockedIabCategories.concat(commonFpd.bcat)
1220
+ }
1221
+ if (commonFpd.ext?.prebid?.bidderparams?.[bidderRequest.bidderCode]?.acat) {
1222
+ const acatParams = commonFpd.ext.prebid.bidderparams[bidderRequest.bidderCode].acat;
1223
+ _allowedIabCategoriesValidation(payload, acatParams);
1224
+ } else if (allowedIabCategories.length) {
1225
+ _allowedIabCategoriesValidation(payload, allowedIabCategories);
1226
+ }
1227
+ _blockedIabCategoriesValidation(payload, blockedIabCategories);
1196
1228
  // Note: Do not move this block up
1197
1229
  // if site object is set in Prebid config then we need to copy required fields from site into app and unset the site object
1198
1230
  if (typeof config.getConfig('app') === 'object') {
@@ -8,7 +8,7 @@ import { config } from '../src/config.js';
8
8
 
9
9
  const BIDDER_CODE = 'seedingAlliance';
10
10
  const DEFAULT_CUR = 'EUR';
11
- const ENDPOINT_URL = 'https://b.nativendo.de/cds/rtb/bid?format=openrtb2.5&ssp=nativendo';
11
+ const ENDPOINT_URL = 'https://b.nativendo.de/cds/rtb/bid?format=openrtb2.5&ssp=pb';
12
12
 
13
13
  const NATIVE_ASSET_IDS = {0: 'title', 1: 'body', 2: 'sponsoredBy', 3: 'image', 4: 'cta', 5: 'icon'};
14
14
 
@@ -124,7 +124,8 @@ export const spec = {
124
124
  user: {},
125
125
  regs: {
126
126
  ext: {
127
- gdpr: 0
127
+ gdpr: 0,
128
+ pb_ver: '$prebid.version$'
128
129
  }
129
130
  }
130
131
  };
@@ -187,11 +188,14 @@ registerBidder(spec);
187
188
  function parseNative(bid) {
188
189
  const {assets, link, imptrackers} = bid.adm.native;
189
190
 
191
+ let clickUrl = link.url.replace(/\$\{AUCTION_PRICE\}/g, bid.price);
192
+
190
193
  if (link.clicktrackers) {
191
194
  link.clicktrackers.forEach(function (clicktracker, index) {
192
195
  link.clicktrackers[index] = clicktracker.replace(/\$\{AUCTION_PRICE\}/g, bid.price);
193
196
  });
194
197
  }
198
+
195
199
  if (imptrackers) {
196
200
  imptrackers.forEach(function (imptracker, index) {
197
201
  imptrackers[index] = imptracker.replace(/\$\{AUCTION_PRICE\}/g, bid.price);
@@ -199,8 +203,8 @@ function parseNative(bid) {
199
203
  }
200
204
 
201
205
  const result = {
202
- url: link.url,
203
- clickUrl: link.url,
206
+ url: clickUrl,
207
+ clickUrl: clickUrl,
204
208
  clickTrackers: link.clicktrackers || undefined,
205
209
  impressionTrackers: imptrackers || undefined
206
210
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prebid.js",
3
- "version": "6.20.0",
3
+ "version": "6.22.0",
4
4
  "description": "Header Bidding Management Library",
5
5
  "main": "src/prebid.js",
6
6
  "scripts": {
@@ -14,6 +14,7 @@ import { ADPOD } from '../mediaTypes.js';
14
14
  import { getHook, hook } from '../hook.js';
15
15
  import { getCoreStorageManager } from '../storageManager.js';
16
16
  import {auctionManager} from '../auctionManager.js';
17
+ import { bidderSettings } from '../bidderSettings.js';
17
18
 
18
19
  export const storage = getCoreStorageManager('bidderFactory');
19
20
 
@@ -235,6 +236,11 @@ export function newBidder(spec) {
235
236
  onBid: (bid) => {
236
237
  const bidRequest = bidRequestMap[bid.requestId];
237
238
  if (bidRequest) {
239
+ bid.adapterCode = bidRequest.bidder;
240
+ if (isInvalidAlternateBidder(bid.bidderCode, bidRequest.bidder)) {
241
+ logWarn(`${bid.bidderCode} is not a registered partner or known bidder of ${bidRequest.bidder}, hence continuing without bid. If you wish to support this bidder, please mark allowAlternateBidderCodes as true in bidderSettings.`);
242
+ return;
243
+ }
238
244
  // creating a copy of original values as cpm and currency are modified later
239
245
  bid.originalCpm = bid.cpm;
240
246
  bid.originalCurrency = bid.currency;
@@ -250,6 +256,17 @@ export function newBidder(spec) {
250
256
  }
251
257
  });
252
258
 
259
+ function isInvalidAlternateBidder(responseBidder, requestBidder) {
260
+ let allowAlternateBidderCodes = bidderSettings.get(requestBidder, 'allowAlternateBidderCodes');
261
+ let alternateBiddersList = bidderSettings.get(requestBidder, 'allowedAlternateBidderCodes');
262
+ if (!!responseBidder && !!requestBidder && requestBidder !== responseBidder) {
263
+ if ((allowAlternateBidderCodes !== undefined && !allowAlternateBidderCodes) || (isArray(alternateBiddersList) && (alternateBiddersList[0] !== '*' && !alternateBiddersList.includes(responseBidder)))) {
264
+ return true;
265
+ }
266
+ }
267
+ return false;
268
+ }
269
+
253
270
  function registerSyncs(responses, gdprConsent, uspConsent) {
254
271
  registerSyncInner(spec, responses, gdprConsent, uspConsent);
255
272
  }
package/src/auction.js CHANGED
@@ -848,13 +848,7 @@ function groupByPlacement(bidsByPlacement, bid) {
848
848
  function getTimedOutBids(bidderRequests, timelyBidders) {
849
849
  const timedOutBids = bidderRequests
850
850
  .map(bid => (bid.bids || []).filter(bid => !timelyBidders.has(bid.bidder)))
851
- .reduce(flatten, [])
852
- .map(bid => ({
853
- bidId: bid.bidId,
854
- bidder: bid.bidder,
855
- adUnitCode: bid.adUnitCode,
856
- auctionId: bid.auctionId,
857
- }));
851
+ .reduce(flatten, []);
858
852
 
859
853
  return timedOutBids;
860
854
  }
@@ -941,6 +941,8 @@ describe('auctionmanager.js', function () {
941
941
  const timedOutBids = bidTimeoutCall.args[1];
942
942
  assert.equal(timedOutBids.length, 1);
943
943
  assert.equal(timedOutBids[0].bidder, BIDDER_CODE1);
944
+ // Check that additional properties are available
945
+ assert.equal(timedOutBids[0].params.placementId, 'id');
944
946
 
945
947
  const auctionEndCall = eventsEmitSpy.withArgs(CONSTANTS.EVENTS.AUCTION_END).getCalls()[0];
946
948
  const auctionProps = auctionEndCall.args[1];
@@ -10,43 +10,34 @@ describe('Adomik Prebid Analytic', function () {
10
10
  let sendWonEventStub;
11
11
  let clock;
12
12
 
13
- before(function () {
13
+ beforeEach(function () {
14
14
  clock = sinon.useFakeTimers();
15
+ sinon.spy(adomikAnalytics, 'track');
16
+ sendEventStub = sinon.stub(adomikAnalytics, 'sendTypedEvent');
17
+ sendWonEventStub = sinon.stub(adomikAnalytics, 'sendWonEvent');
18
+ sinon.stub(events, 'getEvents').returns([]);
19
+ adomikAnalytics.currentContext = undefined;
20
+
21
+ adapterManager.registerAnalyticsAdapter({
22
+ code: 'adomik',
23
+ adapter: adomikAnalytics
24
+ });
15
25
  });
16
- after(function () {
26
+
27
+ afterEach(function () {
28
+ adomikAnalytics.disableAnalytics();
17
29
  clock.restore();
30
+ adomikAnalytics.track.restore();
31
+ sendEventStub.restore();
32
+ sendWonEventStub.restore();
33
+ events.getEvents.restore();
18
34
  });
19
35
 
20
- describe('enableAnalytics', function () {
21
- beforeEach(function () {
22
- sinon.spy(adomikAnalytics, 'track');
23
- sendEventStub = sinon.stub(adomikAnalytics, 'sendTypedEvent');
24
- sendWonEventStub = sinon.stub(adomikAnalytics, 'sendWonEvent');
25
- sinon.stub(events, 'getEvents').returns([]);
26
- });
27
-
28
- afterEach(function () {
29
- adomikAnalytics.track.restore();
30
- sendEventStub.restore();
31
- sendWonEventStub.restore();
32
- events.getEvents.restore();
33
- });
34
-
35
- after(function () {
36
- adomikAnalytics.disableAnalytics();
37
- });
38
-
36
+ describe('adomikAnalytics.enableAnalytics', function () {
39
37
  it('should catch all events', function (done) {
40
- adapterManager.registerAnalyticsAdapter({
41
- code: 'adomik',
42
- adapter: adomikAnalytics
43
- });
44
-
45
38
  const initOptions = {
46
39
  id: '123456',
47
- url: 'testurl',
48
- testId: '12345',
49
- testValue: '1000'
40
+ url: 'testurl'
50
41
  };
51
42
 
52
43
  const bid = {
@@ -74,8 +65,6 @@ describe('Adomik Prebid Analytic', function () {
74
65
  uid: '123456',
75
66
  url: 'testurl',
76
67
  sampling: undefined,
77
- testId: '12345',
78
- testValue: '1000',
79
68
  id: '',
80
69
  timeouted: false
81
70
  });
@@ -87,8 +76,6 @@ describe('Adomik Prebid Analytic', function () {
87
76
  uid: '123456',
88
77
  url: 'testurl',
89
78
  sampling: undefined,
90
- testId: '12345',
91
- testValue: '1000',
92
79
  id: 'test-test-test',
93
80
  timeouted: false
94
81
  });
@@ -149,5 +136,118 @@ describe('Adomik Prebid Analytic', function () {
149
136
 
150
137
  sinon.assert.callCount(adomikAnalytics.track, 6);
151
138
  });
139
+
140
+ describe('when sampling is undefined', function () {
141
+ beforeEach(function() {
142
+ adapterManager.enableAnalytics({
143
+ provider: 'adomik',
144
+ options: { id: '123456', url: 'testurl' }
145
+ });
146
+ });
147
+
148
+ it('is enabled', function () {
149
+ expect(adomikAnalytics.currentContext).is.not.null;
150
+ });
151
+ });
152
+
153
+ describe('when sampling is 0', function () {
154
+ beforeEach(function() {
155
+ adapterManager.enableAnalytics({
156
+ provider: 'adomik',
157
+ options: { id: '123456', url: 'testurl', sampling: 0 }
158
+ });
159
+ });
160
+
161
+ it('is disabled', function () {
162
+ expect(adomikAnalytics.currentContext).to.equal(undefined);
163
+ });
164
+ });
165
+
166
+ describe('when sampling is 1', function () {
167
+ beforeEach(function() {
168
+ adapterManager.enableAnalytics({
169
+ provider: 'adomik',
170
+ options: { id: '123456', url: 'testurl', sampling: 1 }
171
+ });
172
+ });
173
+
174
+ it('is enabled', function () {
175
+ expect(adomikAnalytics.currentContext).is.not.null;
176
+ });
177
+ });
178
+
179
+ describe('when options is not defined', function () {
180
+ beforeEach(function() {
181
+ adapterManager.enableAnalytics({ provider: 'adomik' });
182
+ });
183
+
184
+ it('is disabled', function () {
185
+ expect(adomikAnalytics.currentContext).to.equal(undefined);
186
+ });
187
+ });
188
+
189
+ describe('when id is not defined in options', function () {
190
+ beforeEach(function() {
191
+ adapterManager.enableAnalytics({ provider: 'adomik', url: 'xxx' });
192
+ });
193
+
194
+ it('is disabled', function () {
195
+ expect(adomikAnalytics.currentContext).to.equal(undefined);
196
+ });
197
+ });
198
+
199
+ describe('when url is not defined in options', function () {
200
+ beforeEach(function() {
201
+ adapterManager.enableAnalytics({ provider: 'adomik', id: 'xxx' });
202
+ });
203
+
204
+ it('is disabled', function () {
205
+ expect(adomikAnalytics.currentContext).to.equal(undefined);
206
+ });
207
+ });
208
+ });
209
+
210
+ describe('adomikAnalytics.getKeyValues', function () {
211
+ it('returns [undefined, undefined]', function () {
212
+ let [testId, testValue] = adomikAnalytics.getKeyValues()
213
+ expect(testId).to.equal(undefined);
214
+ expect(testValue).to.equal(undefined);
215
+ });
216
+
217
+ describe('when test is in scope', function () {
218
+ beforeEach(function () {
219
+ sessionStorage.setItem(window.location.hostname + '_AdomikTestInScope', true);
220
+ });
221
+
222
+ it('returns [undefined, undefined]', function () {
223
+ let [testId, testValue] = adomikAnalytics.getKeyValues()
224
+ expect(testId).to.equal(undefined);
225
+ expect(testValue).to.equal(undefined);
226
+ });
227
+
228
+ describe('when key values are defined', function () {
229
+ beforeEach(function () {
230
+ sessionStorage.setItem(window.location.hostname + '_AdomikTest', '{"testId":"12345","testOptionLabel":"1000"}');
231
+ });
232
+
233
+ it('returns key values', function () {
234
+ let [testId, testValue] = adomikAnalytics.getKeyValues()
235
+ expect(testId).to.equal('12345');
236
+ expect(testValue).to.equal('1000');
237
+ });
238
+
239
+ describe('when preventTest is on', function () {
240
+ beforeEach(function () {
241
+ sessionStorage.setItem(window.location.hostname + '_NoAdomikTest', true);
242
+ });
243
+
244
+ it('returns [undefined, undefined]', function () {
245
+ let [testId, testValue] = adomikAnalytics.getKeyValues()
246
+ expect(testId).to.equal(undefined);
247
+ expect(testValue).to.equal(undefined);
248
+ });
249
+ });
250
+ });
251
+ });
152
252
  });
153
253
  });
@@ -12,7 +12,7 @@ describe('Adot Adapter', function () {
12
12
  })
13
13
 
14
14
  it('should return true if video and isValidVideo', function () {
15
- const bid = { mediaTypes: { video: { 'mimes': 1, 'minduration': 1, 'maxduration': 1, 'protocols': 1 } } };
15
+ const bid = { mediaTypes: { video: { 'mimes': 1, 'protocols': 1 } } };
16
16
  const isBidRequestValid = spec.isBidRequestValid(bid);
17
17
  expect(isBidRequestValid).to.equal(true);
18
18
  })
@@ -252,14 +252,14 @@ describe('ApacdexBidAdapter', function () {
252
252
 
253
253
  it('should return a properly formatted request', function () {
254
254
  const bidRequests = spec.buildRequests(bidRequest, bidderRequests)
255
- expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/apacdex')
255
+ expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/pbjs')
256
256
  expect(bidRequests.method).to.equal('POST')
257
257
  expect(bidRequests.bidderRequests).to.eql(bidRequest);
258
258
  })
259
259
 
260
260
  it('should return a properly formatted request with GDPR applies set to true', function () {
261
261
  const bidRequests = spec.buildRequests(bidRequest, bidderRequests)
262
- expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/apacdex')
262
+ expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/pbjs')
263
263
  expect(bidRequests.method).to.equal('POST')
264
264
  expect(bidRequests.data.gdpr.gdprApplies).to.equal(true)
265
265
  expect(bidRequests.data.gdpr.consentString).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A==')
@@ -268,7 +268,7 @@ describe('ApacdexBidAdapter', function () {
268
268
  it('should return a properly formatted request with GDPR applies set to false', function () {
269
269
  bidderRequests.gdprConsent.gdprApplies = false;
270
270
  const bidRequests = spec.buildRequests(bidRequest, bidderRequests)
271
- expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/apacdex')
271
+ expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/pbjs')
272
272
  expect(bidRequests.method).to.equal('POST')
273
273
  expect(bidRequests.data.gdpr.gdprApplies).to.equal(false)
274
274
  expect(bidRequests.data.gdpr.consentString).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A==')
@@ -288,7 +288,7 @@ describe('ApacdexBidAdapter', function () {
288
288
  }
289
289
  };
290
290
  const bidRequests = spec.buildRequests(bidRequest, bidderRequests)
291
- expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/apacdex')
291
+ expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/pbjs')
292
292
  expect(bidRequests.method).to.equal('POST')
293
293
  expect(bidRequests.data.gdpr.gdprApplies).to.equal(false)
294
294
  expect(bidRequests.data.gdpr).to.not.include.keys('consentString')
@@ -308,7 +308,7 @@ describe('ApacdexBidAdapter', function () {
308
308
  }
309
309
  };
310
310
  const bidRequests = spec.buildRequests(bidRequest, bidderRequests)
311
- expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/apacdex')
311
+ expect(bidRequests.url).to.equal('https://useast.quantumdex.io/auction/pbjs')
312
312
  expect(bidRequests.method).to.equal('POST')
313
313
  expect(bidRequests.data.gdpr.gdprApplies).to.equal(true)
314
314
  expect(bidRequests.data.gdpr).to.not.include.keys('consentString')
@@ -384,7 +384,7 @@ describe('ApacdexBidAdapter', function () {
384
384
  describe('.interpretResponse', function () {
385
385
  const bidRequests = {
386
386
  'method': 'POST',
387
- 'url': 'https://useast.quantumdex.io/auction/apacdex',
387
+ 'url': 'https://useast.quantumdex.io/auction/pbjs',
388
388
  'withCredentials': true,
389
389
  'data': {
390
390
  'device': {