prebid.js 6.0.0 → 6.1.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 (61) hide show
  1. package/.babelrc.js +1 -7
  2. package/gulpfile.js +1 -0
  3. package/modules/adheseBidAdapter.js +7 -2
  4. package/modules/adkernelBidAdapter.js +1 -0
  5. package/modules/adlivetechBidAdapter.md +61 -0
  6. package/modules/adomikAnalyticsAdapter.js +10 -4
  7. package/modules/appnexusBidAdapter.js +4 -0
  8. package/modules/codefuelBidAdapter.js +1 -3
  9. package/modules/codefuelBidAdapter.md +3 -3
  10. package/modules/datablocksBidAdapter.js +3 -3
  11. package/modules/deepintentBidAdapter.js +1 -1
  12. package/modules/engageyaBidAdapter.js +68 -54
  13. package/modules/glimpseBidAdapter.js +31 -16
  14. package/modules/gptPreAuction.js +11 -5
  15. package/modules/gridBidAdapter.js +1 -1
  16. package/modules/id5IdSystem.md +6 -6
  17. package/modules/imRtdProvider.js +31 -0
  18. package/modules/ixBidAdapter.js +166 -21
  19. package/modules/merkleIdSystem.js +5 -0
  20. package/modules/nativoBidAdapter.js +27 -1
  21. package/modules/oguryBidAdapter.js +2 -1
  22. package/modules/openxBidAdapter.js +6 -1
  23. package/modules/prebidServerBidAdapter/index.js +3 -3
  24. package/modules/pubmaticBidAdapter.js +2 -0
  25. package/modules/saambaaBidAdapter.js +420 -0
  26. package/modules/saambaaBidAdapter.md +65 -68
  27. package/modules/seedtagBidAdapter.js +6 -0
  28. package/modules/smaatoBidAdapter.js +6 -1
  29. package/modules/sspBCBidAdapter.js +34 -3
  30. package/modules/trustxBidAdapter.js +10 -1
  31. package/modules/vidoomyBidAdapter.js +51 -100
  32. package/modules/visxBidAdapter.js +1 -1
  33. package/modules/yieldlabBidAdapter.js +41 -10
  34. package/modules/yieldlabBidAdapter.md +91 -48
  35. package/package.json +6 -1
  36. package/src/adapterManager.js +14 -8
  37. package/test/spec/modules/adheseBidAdapter_spec.js +27 -1
  38. package/test/spec/modules/adomikAnalyticsAdapter_spec.js +3 -1
  39. package/test/spec/modules/appnexusBidAdapter_spec.js +14 -0
  40. package/test/spec/modules/codefuelBidAdapter_spec.js +1 -1
  41. package/test/spec/modules/datablocksBidAdapter_spec.js +3 -3
  42. package/test/spec/modules/engageyaBidAdapter_spec.js +231 -95
  43. package/test/spec/modules/eplanningBidAdapter_spec.js +8 -8
  44. package/test/spec/modules/glimpseBidAdapter_spec.js +33 -0
  45. package/test/spec/modules/gptPreAuction_spec.js +58 -4
  46. package/test/spec/modules/imRtdProvider_spec.js +25 -0
  47. package/test/spec/modules/ixBidAdapter_spec.js +285 -2
  48. package/test/spec/modules/konduitWrapper_spec.js +0 -1
  49. package/test/spec/modules/merkleIdSystem_spec.js +18 -0
  50. package/test/spec/modules/nativoBidAdapter_spec.js +35 -18
  51. package/test/spec/modules/oguryBidAdapter_spec.js +13 -11
  52. package/test/spec/modules/openxBidAdapter_spec.js +5 -0
  53. package/test/spec/modules/prebidServerBidAdapter_spec.js +19 -2
  54. package/test/spec/modules/seedtagBidAdapter_spec.js +3 -0
  55. package/test/spec/modules/smaatoBidAdapter_spec.js +30 -0
  56. package/test/spec/modules/sspBCBidAdapter_spec.js +33 -3
  57. package/test/spec/modules/trustxBidAdapter_spec.js +42 -0
  58. package/test/spec/modules/vidoomyBidAdapter_spec.js +32 -13
  59. package/test/spec/modules/visxBidAdapter_spec.js +1 -1
  60. package/test/spec/modules/yieldlabBidAdapter_spec.js +81 -0
  61. package/test/spec/unit/core/adapterManager_spec.js +24 -6
@@ -37,6 +37,34 @@ function setImDataInCookie(value) {
37
37
  );
38
38
  }
39
39
 
40
+ /**
41
+ * @param {string} bidderName
42
+ */
43
+ export function getBidderFunction(bidderName) {
44
+ const biddersFunction = {
45
+ ix: function (bid, data) {
46
+ if (data.im_segments && data.im_segments.length) {
47
+ config.setConfig({
48
+ ix: {firstPartyData: {im_segments: data.im_segments}},
49
+ });
50
+ }
51
+ return bid
52
+ },
53
+ pubmatic: function (bid, data) {
54
+ if (data.im_segments && data.im_segments.length) {
55
+ const dctr = deepAccess(bid, 'params.dctr');
56
+ deepSetValue(
57
+ bid,
58
+ 'params.dctr',
59
+ `${dctr ? dctr + '|' : ''}im_segments=${data.im_segments.join(',')}`
60
+ );
61
+ }
62
+ return bid
63
+ }
64
+ }
65
+ return biddersFunction[bidderName] || null;
66
+ }
67
+
40
68
  export function getCustomBidderFunction(config, bidder) {
41
69
  const overwriteFn = deepAccess(config, `params.overwrites.${bidder}`)
42
70
 
@@ -73,9 +101,12 @@ export function setRealTimeData(bidConfig, moduleConfig, data) {
73
101
 
74
102
  adUnits.forEach(adUnit => {
75
103
  adUnit.bids.forEach(bid => {
104
+ const bidderFunction = getBidderFunction(bid.bidder);
76
105
  const overwriteFunction = getCustomBidderFunction(moduleConfig, bid.bidder);
77
106
  if (overwriteFunction) {
78
107
  overwriteFunction(bid, data, utils, config);
108
+ } else if (bidderFunction) {
109
+ bidderFunction(bid, data);
79
110
  }
80
111
  })
81
112
  });
@@ -1,6 +1,9 @@
1
1
  import { deepAccess, parseGPTSingleSizeArray, inIframe, deepClone, logError, logWarn, isFn, contains, isInteger, isArray, deepSetValue, parseQueryStringParameters, isEmpty, mergeDeep, convertTypes } from '../src/utils.js';
2
2
  import { BANNER, VIDEO } from '../src/mediaTypes.js';
3
3
  import { config } from '../src/config.js';
4
+ import { EVENTS } from '../src/constants.json';
5
+ import { getStorageManager } from '../src/storageManager.js';
6
+ import events from '../src/events.js';
4
7
  import find from 'core-js-pure/features/array/find.js';
5
8
  import { registerBidder } from '../src/adapters/bidderFactory.js';
6
9
  import { INSTREAM, OUTSTREAM } from '../src/video.js';
@@ -20,15 +23,23 @@ const VIDEO_TIME_TO_LIVE = 3600; // 1hr
20
23
  const NET_REVENUE = true;
21
24
  const MAX_REQUEST_SIZE = 8000;
22
25
  const MAX_REQUEST_LIMIT = 4;
23
-
24
26
  const PRICE_TO_DOLLAR_FACTOR = {
25
27
  JPY: 1
26
28
  };
27
29
  const USER_SYNC_URL = 'https://js-sec.indexww.com/um/ixmatch.html';
28
30
  const RENDERER_URL = 'https://js-sec.indexww.com/htv/video-player.js';
29
31
  const FLOOR_SOURCE = { PBJS: 'p', IX: 'x' };
30
- // determines which eids we send and the rtiPartner field in ext
31
-
32
+ export const ERROR_CODES = {
33
+ BID_SIZE_INVALID_FORMAT: 1,
34
+ BID_SIZE_NOT_INCLUDED: 2,
35
+ PROPERTY_NOT_INCLUDED: 3,
36
+ SITE_ID_INVALID_VALUE: 4,
37
+ BID_FLOOR_INVALID_FORMAT: 5,
38
+ IX_FPD_EXCEEDS_MAX_SIZE: 6,
39
+ EXCEEDS_MAX_SIZE: 7,
40
+ PB_FPD_EXCEEDS_MAX_SIZE: 8,
41
+ VIDEO_DURATION_INVALID: 9
42
+ };
32
43
  const FIRST_PARTY_DATA = {
33
44
  SITE: [
34
45
  'id', 'name', 'domain', 'cat', 'sectioncat', 'pagecat', 'page', 'ref', 'search', 'mobile',
@@ -36,7 +47,6 @@ const FIRST_PARTY_DATA = {
36
47
  ],
37
48
  USER: ['id', 'buyeruid', 'yob', 'gender', 'keywords', 'customdata', 'geo', 'data', 'ext']
38
49
  };
39
-
40
50
  const SOURCE_RTI_MAPPING = {
41
51
  'liveramp.com': 'idl',
42
52
  'netid.de': 'NETID',
@@ -45,7 +55,6 @@ const SOURCE_RTI_MAPPING = {
45
55
  'uidapi.com': 'UID2',
46
56
  'adserver.org': 'TDID'
47
57
  };
48
-
49
58
  const PROVIDERS = [
50
59
  'britepoolid',
51
60
  'id5id',
@@ -62,9 +71,7 @@ const PROVIDERS = [
62
71
  'TDID',
63
72
  'flocId'
64
73
  ];
65
-
66
74
  const REQUIRED_VIDEO_PARAMS = ['mimes', 'minduration', 'maxduration']; // note: protocol/protocols is also reqd
67
-
68
75
  const VIDEO_PARAMS_ALLOW_LIST = [
69
76
  'mimes', 'minduration', 'maxduration', 'protocols', 'protocol',
70
77
  'startdelay', 'placement', 'linearity', 'skip', 'skipmin',
@@ -73,6 +80,17 @@ const VIDEO_PARAMS_ALLOW_LIST = [
73
80
  'delivery', 'pos', 'companionad', 'api', 'companiontype', 'ext',
74
81
  'playerSize', 'w', 'h'
75
82
  ];
83
+ const LOCAL_STORAGE_KEY = 'ixdiag';
84
+ let hasRegisteredHandler = false;
85
+ export const storage = getStorageManager(GLOBAL_VENDOR_ID, BIDDER_CODE);
86
+
87
+ // Possible values for bidResponse.seatBid[].bid[].mtype which indicates the type of the creative markup so that it can properly be associated with the right sub-object of the BidRequest.Imp.
88
+ const MEDIA_TYPES = {
89
+ Banner: 1,
90
+ Video: 2,
91
+ Audio: 3,
92
+ Native: 4
93
+ }
76
94
 
77
95
  /**
78
96
  * Transform valid bid request config object to banner impression object that will be sent to ad server.
@@ -125,7 +143,10 @@ function bidToVideoImp(bid) {
125
143
  }
126
144
 
127
145
  if (imp.video.minduration > imp.video.maxduration) {
128
- logError(`IX Bid Adapter: video minduration [${imp.video.minduration}] cannot be greater than video maxduration [${imp.video.maxduration}]`);
146
+ logError(
147
+ `IX Bid Adapter: video minduration [${imp.video.minduration}] cannot be greater than video maxduration [${imp.video.maxduration}]`,
148
+ { bidder: BIDDER_CODE, code: ERROR_CODES.VIDEO_DURATION_INVALID }
149
+ );
129
150
  return {};
130
151
  }
131
152
 
@@ -262,9 +283,14 @@ function parseBid(rawBid, currency, bidRequest) {
262
283
  bid.currency = currency;
263
284
  bid.creativeId = rawBid.hasOwnProperty('crid') ? rawBid.crid : '-';
264
285
 
265
- // in the event of a video
266
- if (deepAccess(rawBid, 'ext.vasturl')) {
286
+ if (rawBid.mtype == MEDIA_TYPES.Video) {
287
+ bid.vastXml = rawBid.adm
288
+ } else if (rawBid.ext && rawBid.ext.vasturl) {
267
289
  bid.vastUrl = rawBid.ext.vasturl
290
+ }
291
+
292
+ // in the event of a video
293
+ if ((rawBid.ext && rawBid.ext.vasturl) || rawBid.mtype == MEDIA_TYPES.Video) {
268
294
  bid.width = bidRequest.video.w;
269
295
  bid.height = bidRequest.video.h;
270
296
  bid.mediaType = VIDEO;
@@ -498,6 +524,13 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
498
524
  r.ext.ixdiag[key] = ixdiag[key];
499
525
  }
500
526
 
527
+ // Get cached errors stored in LocalStorage
528
+ const cachedErrors = getCachedErrors();
529
+
530
+ if (!isEmpty(cachedErrors)) {
531
+ r.ext.ixdiag.err = cachedErrors;
532
+ }
533
+
501
534
  // if an schain is provided, send it along
502
535
  if (validBidRequests[0].schain) {
503
536
  r.source = {
@@ -576,7 +609,7 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
576
609
  const baseRequestSize = `${baseUrl}${parseQueryStringParameters({ ...payload, r: JSON.stringify(r) })}`.length;
577
610
 
578
611
  if (baseRequestSize > MAX_REQUEST_SIZE) {
579
- logError('ix bidder: Base request size has exceeded maximum request size.');
612
+ logError('IX Bid Adapter: Base request size has exceeded maximum request size.', { bidder: BIDDER_CODE, code: ERROR_CODES.EXCEEDS_MAX_SIZE });
580
613
  return requests;
581
614
  }
582
615
 
@@ -606,7 +639,7 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
606
639
  }
607
640
  currentRequestSize += fpdRequestSize;
608
641
  } else {
609
- logError('ix bidder: IX config FPD request size has exceeded maximum request size.');
642
+ logError('IX Bid Adapter: IX config FPD request size has exceeded maximum request size.', { bidder: BIDDER_CODE, code: ERROR_CODES.IX_FPD_EXCEEDS_MAX_SIZE });
610
643
  }
611
644
  }
612
645
 
@@ -713,7 +746,7 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
713
746
  const fpdRequestSize = encodeURIComponent(JSON.stringify({ ...site, ...user })).length;
714
747
  currentRequestSize += fpdRequestSize;
715
748
  } else {
716
- logError('ix bidder: FPD request size has exceeded maximum request size.');
749
+ logError('IX Bid Adapter: FPD request size has exceeded maximum request size.', { bidder: BIDDER_CODE, code: ERROR_CODES.PB_FPD_EXCEEDS_MAX_SIZE });
717
750
  }
718
751
  }
719
752
 
@@ -946,10 +979,99 @@ function createMissingBannerImp(bid, imp, newSize) {
946
979
  }
947
980
 
948
981
  /**
982
+ * @typedef {Array[message: string, err: Object<bidder: string, code: number>]} ErrorData
983
+ * @property {string} message - The error message.
984
+ * @property {object} err - The error object.
985
+ * @property {string} err.bidder - The bidder of the error.
986
+ * @property {string} err.code - The error code.
987
+ */
988
+
989
+ /**
990
+ * Error Event handler that receives type and arguments in a data object.
991
+ *
992
+ * @param {ErrorData} data
993
+ */
994
+ function errorEventHandler(data) {
995
+ if (!storage.localStorageIsEnabled()) {
996
+ return;
997
+ }
998
+
999
+ let currentStorage;
1000
+
1001
+ try {
1002
+ currentStorage = JSON.parse(storage.getDataFromLocalStorage(LOCAL_STORAGE_KEY) || '{}');
1003
+ } catch (e) {
1004
+ logWarn('ix can not read ixdiag from localStorage.');
1005
+ }
1006
+
1007
+ const todayDate = new Date();
1008
+
1009
+ Object.keys(currentStorage).map((errorDate) => {
1010
+ const date = new Date(errorDate);
1011
+
1012
+ if (date.setDate(date.getDate() + 7) - todayDate < 0) {
1013
+ delete currentStorage[errorDate];
1014
+ }
1015
+ });
1016
+
1017
+ if (data.type === 'ERROR' && data.arguments && data.arguments[1] && data.arguments[1].bidder === BIDDER_CODE) {
1018
+ const todayString = todayDate.toISOString().slice(0, 10);
1019
+
1020
+ const errorCode = data.arguments[1].code;
1021
+
1022
+ if (errorCode) {
1023
+ currentStorage[todayString] = currentStorage[todayString] || {};
1024
+
1025
+ if (!Number(currentStorage[todayString][errorCode])) {
1026
+ currentStorage[todayString][errorCode] = 0;
1027
+ }
1028
+
1029
+ currentStorage[todayString][errorCode]++;
1030
+ };
1031
+ }
1032
+
1033
+ storage.setDataInLocalStorage(LOCAL_STORAGE_KEY, JSON.stringify(currentStorage));
1034
+ }
1035
+
1036
+ /**
1037
+ * Get ixdiag stored in LocalStorage and format to be added to request payload
1038
+ *
1039
+ * @returns {Object} Object with error codes and counts
1040
+ */
1041
+ function getCachedErrors() {
1042
+ if (!storage.localStorageIsEnabled()) {
1043
+ return;
1044
+ }
1045
+
1046
+ const errors = {};
1047
+ let currentStorage;
1048
+
1049
+ try {
1050
+ currentStorage = JSON.parse(storage.getDataFromLocalStorage(LOCAL_STORAGE_KEY) || '{}');
1051
+ } catch (e) {
1052
+ logError('ix can not read ixdiag from localStorage.');
1053
+ return null;
1054
+ }
1055
+
1056
+ Object.keys(currentStorage).forEach((date) => {
1057
+ Object.keys(currentStorage[date]).forEach((code) => {
1058
+ if (typeof currentStorage[date][code] === 'number') {
1059
+ errors[code] = errors[code]
1060
+ ? errors[code] + currentStorage[date][code]
1061
+ : currentStorage[date][code];
1062
+ }
1063
+ });
1064
+ });
1065
+
1066
+ return errors;
1067
+ }
1068
+
1069
+ /**
1070
+ *
949
1071
  * Initialize Outstream Renderer
950
1072
  * @param {Object} bid
951
1073
  */
952
- function outstreamRenderer (bid) {
1074
+ function outstreamRenderer(bid) {
953
1075
  bid.renderer.push(() => {
954
1076
  var config = {
955
1077
  width: bid.width,
@@ -957,7 +1079,13 @@ function outstreamRenderer (bid) {
957
1079
  timeout: 3000
958
1080
  };
959
1081
 
960
- window.IXOutstreamPlayer(bid.vastUrl, bid.adUnitCode, config);
1082
+ // IXOutstreamPlayer supports both vastUrl and vastXml, so we can pass either.
1083
+ // Since vastUrl is going to be deprecated from exchange response, vastXml takes priority.
1084
+ if (bid.vastXml) {
1085
+ window.IXOutstreamPlayer(bid.vastXml, bid.adUnitCode, config);
1086
+ } else {
1087
+ window.IXOutstreamPlayer(bid.vastUrl, bid.adUnitCode, config);
1088
+ }
961
1089
  });
962
1090
  }
963
1091
 
@@ -966,7 +1094,7 @@ function outstreamRenderer (bid) {
966
1094
  * @param {string} id
967
1095
  * @returns {Renderer}
968
1096
  */
969
- function createRenderer (id) {
1097
+ function createRenderer(id) {
970
1098
  const renderer = Renderer.install({
971
1099
  id: id,
972
1100
  url: RENDERER_URL,
@@ -1000,6 +1128,12 @@ export const spec = {
1000
1128
  * @return {boolean} True if this is a valid bid, and false otherwise.
1001
1129
  */
1002
1130
  isBidRequestValid: function (bid) {
1131
+ if (!hasRegisteredHandler) {
1132
+ events.on(EVENTS.AUCTION_DEBUG, errorEventHandler);
1133
+ events.on(EVENTS.AD_RENDER_FAILED, errorEventHandler);
1134
+ hasRegisteredHandler = true;
1135
+ }
1136
+
1003
1137
  const paramsVideoRef = deepAccess(bid, 'params.video');
1004
1138
  const paramsSize = deepAccess(bid, 'params.size');
1005
1139
  const mediaTypeBannerSizes = deepAccess(bid, 'mediaTypes.banner.sizes');
@@ -1009,6 +1143,7 @@ export const spec = {
1009
1143
  const hasBidFloorCur = bid.params.hasOwnProperty('bidFloorCur');
1010
1144
 
1011
1145
  if (bid.hasOwnProperty('mediaType') && !(contains(SUPPORTED_AD_TYPES, bid.mediaType))) {
1146
+ logWarn('IX Bid Adapter: media type is not supported.');
1012
1147
  return false;
1013
1148
  }
1014
1149
 
@@ -1020,26 +1155,26 @@ export const spec = {
1020
1155
  // since there is an ix bidder level size, make sure its valid
1021
1156
  const ixSize = getFirstSize(paramsSize);
1022
1157
  if (!ixSize) {
1023
- logError('ix bidder params: size has invalid format.');
1158
+ logError('IX Bid Adapter: size has invalid format.', { bidder: BIDDER_CODE, code: ERROR_CODES.BID_SIZE_INVALID_FORMAT });
1024
1159
  return false;
1025
1160
  }
1026
1161
  // check if the ix bidder level size, is present in ad unit level
1027
1162
  if (!includesSize(bid.sizes, ixSize) &&
1028
1163
  !(includesSize(mediaTypeVideoPlayerSize, ixSize)) &&
1029
1164
  !(includesSize(mediaTypeBannerSizes, ixSize))) {
1030
- logError('ix bidder params: bid size is not included in ad unit sizes or player size.');
1165
+ logError('IX Bid Adapter: bid size is not included in ad unit sizes or player size.', { bidder: BIDDER_CODE, code: ERROR_CODES.BID_SIZE_NOT_INCLUDED });
1031
1166
  return false;
1032
1167
  }
1033
1168
  }
1034
1169
 
1035
1170
  if (typeof bid.params.siteId !== 'string' && typeof bid.params.siteId !== 'number') {
1036
- logError('ix bidder params: siteId must be string or number value.');
1171
+ logError('IX Bid Adapter: siteId must be string or number value.', { bidder: BIDDER_CODE, code: ERROR_CODES.SITE_ID_INVALID_VALUE });
1037
1172
  return false;
1038
1173
  }
1039
1174
 
1040
1175
  if (hasBidFloor || hasBidFloorCur) {
1041
1176
  if (!(hasBidFloor && hasBidFloorCur && isValidBidFloorParams(bid.params.bidFloor, bid.params.bidFloorCur))) {
1042
- logError('ix bidder params: bidFloor / bidFloorCur parameter has invalid format.');
1177
+ logError('IX Bid Adapter: bidFloor / bidFloorCur parameter has invalid format.', { bidder: BIDDER_CODE, code: ERROR_CODES.BID_FLOOR_INVALID_FORMAT });
1043
1178
  return false;
1044
1179
  }
1045
1180
  }
@@ -1048,7 +1183,7 @@ export const spec = {
1048
1183
  const errorList = checkVideoParams(mediaTypeVideoRef, paramsVideoRef);
1049
1184
  if (errorList.length) {
1050
1185
  errorList.forEach((err) => {
1051
- logError(err);
1186
+ logError(err, { bidder: BIDDER_CODE, code: ERROR_CODES.PROPERTY_NOT_INCLUDED });
1052
1187
  });
1053
1188
  return false;
1054
1189
  }
@@ -1169,6 +1304,16 @@ export const spec = {
1169
1304
 
1170
1305
  bids.push(bid);
1171
1306
  }
1307
+
1308
+ if (deepAccess(requestBid, 'ext.ixdiag.err')) {
1309
+ if (storage.localStorageIsEnabled()) {
1310
+ try {
1311
+ storage.removeDataFromLocalStorage(LOCAL_STORAGE_KEY);
1312
+ } catch (e) {
1313
+ logError('ix can not clear ixdiag from localStorage.');
1314
+ }
1315
+ }
1316
+ }
1172
1317
  }
1173
1318
 
1174
1319
  return bids;
@@ -149,6 +149,11 @@ export const merkleIdSubmodule = {
149
149
  logInfo('User ID - merkleId stored id ' + storedId);
150
150
  const configParams = (config && config.params) || {};
151
151
 
152
+ if (typeof configParams.endpoint !== 'string') {
153
+ logWarn('User ID - merkleId submodule endpoint string is not defined');
154
+ configParams.endpoint = ID_URL
155
+ }
156
+
152
157
  if (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) {
153
158
  logError('User ID - merkleId submodule does not currently handle consent strings');
154
159
  return;
@@ -17,6 +17,16 @@ const adUnitsRequested = {}
17
17
 
18
18
  // Prebid adapter referrence doc: https://docs.prebid.org/dev-docs/bidder-adaptor.html
19
19
 
20
+ // Validity checks for optionsl paramters
21
+ const validParameter = {
22
+ url: (value) => typeof value === 'string',
23
+ placementId: (value) => {
24
+ const isString = typeof value === 'string'
25
+ const isNumber = typeof value === 'number'
26
+ return isString || isNumber
27
+ },
28
+ }
29
+
20
30
  export const spec = {
21
31
  code: BIDDER_CODE,
22
32
  gvlid: GVLID,
@@ -30,7 +40,23 @@ export const spec = {
30
40
  * @return boolean True if this is a valid bid, and false otherwise.
31
41
  */
32
42
  isBidRequestValid: function (bid) {
33
- return true
43
+ // We don't need any specific parameters to make a bid request
44
+ // If not parameters are supplied just verify it's the correct bidder code
45
+ if (!bid.params) return bid.bidder === BIDDER_CODE
46
+
47
+ // Check if any supplied parameters are invalid
48
+ const hasInvalidParameters = Object.keys(bid.params).some(key => {
49
+ const value = bid.params[key]
50
+ const validityCheck = validParameter[key]
51
+
52
+ // We don't have a test for this so it's not a paramter we care about
53
+ if (!validityCheck) return false
54
+
55
+ // Return if the check is not passed
56
+ return !validityCheck(value)
57
+ })
58
+
59
+ return !hasInvalidParameters
34
60
  },
35
61
 
36
62
  /**
@@ -83,7 +83,8 @@ function buildRequests(validBidRequests, bidderRequest) {
83
83
  bidfloor: getFloor(bidRequest),
84
84
  banner: {
85
85
  format: sizes
86
- }
86
+ },
87
+ ext: bidRequest.params
87
88
  });
88
89
  }
89
90
  });
@@ -42,7 +42,12 @@ export const USER_ID_CODE_TO_QUERY_ARG = {
42
42
  novatiq: 'novatiqid', // Novatiq ID
43
43
  mwOpenLinkId: 'mwopenlinkid', // MediaWallah OpenLink ID
44
44
  dapId: 'dapid', // Akamai DAP ID
45
- amxId: 'amxid' // AMX RTB ID
45
+ amxId: 'amxid', // AMX RTB ID
46
+ kpuid: 'kpuid', // Kinesso ID
47
+ publinkId: 'publinkid', // Publisher Link
48
+ naveggId: 'naveggid', // Navegg ID
49
+ imuid: 'imuid', // IM-UID by Intimate Merger
50
+ adtelligentId: 'adtelligentid' // Adtelligent ID
46
51
  };
47
52
 
48
53
  export const spec = {
@@ -731,7 +731,7 @@ const OPEN_RTB_PROTOCOL = {
731
731
  return;
732
732
  }
733
733
  const request = {
734
- id: s2sBidRequest.tid,
734
+ id: firstBidRequest.auctionId,
735
735
  source: {tid: s2sBidRequest.tid},
736
736
  tmax: s2sConfig.timeout,
737
737
  imp: imps,
@@ -751,7 +751,7 @@ const OPEN_RTB_PROTOCOL = {
751
751
  }
752
752
  };
753
753
 
754
- // Sets pbjs version, can be overwritten below if channel exists in s2sConfig.extPrebid
754
+ // This is no longer overwritten unless name and version explicitly overwritten by extPrebid (mergeDeep)
755
755
  request.ext.prebid = Object.assign(request.ext.prebid, {channel: {name: 'pbjs', version: $$PREBID_GLOBAL$$.version}})
756
756
 
757
757
  // set debug flag if in debug mode
@@ -761,7 +761,7 @@ const OPEN_RTB_PROTOCOL = {
761
761
 
762
762
  // s2sConfig video.ext.prebid is passed through openrtb to PBS
763
763
  if (s2sConfig.extPrebid && typeof s2sConfig.extPrebid === 'object') {
764
- request.ext.prebid = Object.assign(request.ext.prebid, s2sConfig.extPrebid);
764
+ request.ext.prebid = mergeDeep(request.ext.prebid, s2sConfig.extPrebid);
765
765
  }
766
766
 
767
767
  /**
@@ -11,6 +11,7 @@ const USER_SYNC_URL_IFRAME = 'https://ads.pubmatic.com/AdServer/js/user_sync.htm
11
11
  const USER_SYNC_URL_IMAGE = 'https://image8.pubmatic.com/AdServer/ImgSync?p=';
12
12
  const DEFAULT_CURRENCY = 'USD';
13
13
  const AUCTION_TYPE = 1;
14
+ const GROUPM_ALIAS = {code: 'groupm', gvlid: 98};
14
15
  const UNDEFINED = undefined;
15
16
  const DEFAULT_WIDTH = 0;
16
17
  const DEFAULT_HEIGHT = 0;
@@ -1005,6 +1006,7 @@ export const spec = {
1005
1006
  code: BIDDER_CODE,
1006
1007
  gvlid: 76,
1007
1008
  supportedMediaTypes: [BANNER, VIDEO, NATIVE],
1009
+ aliases: [GROUPM_ALIAS],
1008
1010
  /**
1009
1011
  * Determines whether or not the given bid request is valid. Valid bid request must have placementId and hbid
1010
1012
  *