prebid.js 6.28.0 → 6.29.2

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 (162) hide show
  1. package/dist/33acrossBidAdapter.js +1 -1
  2. package/dist/adagioBidAdapter.js +1 -1
  3. package/dist/adbookpspBidAdapter.js +1 -1
  4. package/dist/adgenerationBidAdapter.js +1 -1
  5. package/dist/adoceanBidAdapter.js +1 -1
  6. package/dist/adrelevantisBidAdapter.js +1 -1
  7. package/dist/adxcgBidAdapter.js +1 -1
  8. package/dist/adyoulikeBidAdapter.js +1 -1
  9. package/dist/ajaBidAdapter.js +1 -1
  10. package/dist/amxBidAdapter.js +1 -1
  11. package/dist/amxIdSystem.js +1 -1
  12. package/dist/appierAnalyticsAdapter.js +1 -1
  13. package/dist/appnexusBidAdapter.js +1 -1
  14. package/dist/asoBidAdapter.js +1 -1
  15. package/dist/audiencerunBidAdapter.js +1 -1
  16. package/dist/axonixBidAdapter.js +1 -1
  17. package/dist/bidglassBidAdapter.js +1 -1
  18. package/dist/big-richmediaBidAdapter.js +1 -1
  19. package/dist/bluebillywigBidAdapter.js +1 -1
  20. package/dist/bridgewellBidAdapter.js +1 -1
  21. package/dist/brightMountainMediaBidAdapter.js +1 -1
  22. package/dist/concertBidAdapter.js +1 -1
  23. package/dist/connectIdSystem.js +1 -1
  24. package/dist/connectadBidAdapter.js +1 -1
  25. package/dist/consentManagement.js +1 -1
  26. package/dist/consumableBidAdapter.js +1 -1
  27. package/dist/conversantBidAdapter.js +1 -1
  28. package/dist/craftBidAdapter.js +1 -1
  29. package/dist/criteoBidAdapter.js +1 -1
  30. package/dist/currency.js +1 -1
  31. package/dist/dspxBidAdapter.js +1 -1
  32. package/dist/eplanningBidAdapter.js +1 -1
  33. package/dist/gdprEnforcement.js +1 -1
  34. package/dist/glimpseBidAdapter.js +1 -1
  35. package/dist/gmosspBidAdapter.js +1 -1
  36. package/dist/goldbachBidAdapter.js +1 -1
  37. package/dist/gridBidAdapter.js +1 -1
  38. package/dist/gridNMBidAdapter.js +1 -1
  39. package/dist/gumgumBidAdapter.js +1 -1
  40. package/dist/h12mediaBidAdapter.js +1 -1
  41. package/dist/id5IdSystem.js +1 -1
  42. package/dist/impactifyBidAdapter.js +1 -1
  43. package/dist/improvedigitalBidAdapter.js +1 -1
  44. package/dist/inmarBidAdapter.js +1 -1
  45. package/dist/insticatorBidAdapter.js +1 -1
  46. package/dist/ixBidAdapter.js +1 -1
  47. package/dist/jixieBidAdapter.js +1 -1
  48. package/dist/justpremiumBidAdapter.js +1 -1
  49. package/dist/konduitAnalyticsAdapter.js +1 -1
  50. package/dist/lassoBidAdapter.js +1 -0
  51. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  52. package/dist/logicadBidAdapter.js +1 -1
  53. package/dist/loglyliftBidAdapter.js +1 -1
  54. package/dist/malltvAnalyticsAdapter.js +1 -1
  55. package/dist/marsmediaBidAdapter.js +1 -1
  56. package/dist/mediafuseBidAdapter.js +1 -1
  57. package/dist/mediakeysBidAdapter.js +1 -1
  58. package/dist/mediasquareBidAdapter.js +1 -1
  59. package/dist/merkleIdSystem.js +1 -1
  60. package/dist/mgidBidAdapter.js +1 -1
  61. package/dist/minutemediaBidAdapter.js +1 -1
  62. package/dist/not-for-prod/prebid.js +120 -119
  63. package/dist/oguryBidAdapter.js +1 -1
  64. package/dist/oneVideoBidAdapter.js +1 -1
  65. package/dist/onetagBidAdapter.js +1 -1
  66. package/dist/ooloAnalyticsAdapter.js +1 -1
  67. package/dist/outbrainBidAdapter.js +1 -1
  68. package/dist/parrableIdSystem.js +1 -1
  69. package/dist/pixfutureBidAdapter.js +1 -1
  70. package/dist/prebid-core.js +3 -3
  71. package/dist/pubCommonId.js +1 -1
  72. package/dist/publinkIdSystem.js +1 -1
  73. package/dist/pubmaticAnalyticsAdapter.js +1 -1
  74. package/dist/pubmaticBidAdapter.js +1 -1
  75. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  76. package/dist/pxyzBidAdapter.js +1 -1
  77. package/dist/quantcastBidAdapter.js +1 -1
  78. package/dist/readpeakBidAdapter.js +1 -1
  79. package/dist/relaidoBidAdapter.js +1 -1
  80. package/dist/rhythmoneBidAdapter.js +1 -1
  81. package/dist/riseBidAdapter.js +1 -1
  82. package/dist/rubiconAnalyticsAdapter.js +1 -1
  83. package/dist/rubiconBidAdapter.js +1 -1
  84. package/dist/seedingAllianceBidAdapter.js +1 -1
  85. package/dist/seedtagBidAdapter.js +1 -1
  86. package/dist/sharedIdSystem.js +1 -1
  87. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  88. package/dist/sharethroughBidAdapter.js +1 -1
  89. package/dist/smaatoBidAdapter.js +1 -1
  90. package/dist/smartadserverBidAdapter.js +1 -1
  91. package/dist/smartxBidAdapter.js +1 -1
  92. package/dist/smilewantedBidAdapter.js +1 -1
  93. package/dist/sonobiBidAdapter.js +1 -1
  94. package/dist/sortableBidAdapter.js +1 -1
  95. package/dist/sovrnAnalyticsAdapter.js +1 -1
  96. package/dist/sovrnBidAdapter.js +1 -1
  97. package/dist/sspBCBidAdapter.js +1 -1
  98. package/dist/sublimeBidAdapter.js +1 -1
  99. package/dist/synacormediaBidAdapter.js +1 -1
  100. package/dist/taboolaBidAdapter.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/userId.js +1 -1
  111. package/dist/vidazooBidAdapter.js +1 -1
  112. package/dist/videobyteBidAdapter.js +1 -1
  113. package/dist/visxBidAdapter.js +1 -1
  114. package/dist/vuukleBidAdapter.js +1 -1
  115. package/dist/widespaceBidAdapter.js +1 -1
  116. package/dist/winrBidAdapter.js +1 -1
  117. package/dist/yahoosspBidAdapter.js +1 -1
  118. package/dist/yieldmoBidAdapter.js +1 -1
  119. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  120. package/modules/adoceanBidAdapter.js +29 -1
  121. package/modules/consentManagement.js +20 -10
  122. package/modules/currency.js +2 -2
  123. package/modules/gdprEnforcement.js +15 -9
  124. package/modules/insticatorBidAdapter.js +109 -42
  125. package/modules/ixBidAdapter.js +3 -2
  126. package/modules/ixBidAdapter.md +1 -1
  127. package/modules/lassoBidAdapter.js +133 -0
  128. package/modules/lassoBidAdapter.md +29 -0
  129. package/modules/merkleIdSystem.js +43 -31
  130. package/modules/pubCommonId.js +2 -1
  131. package/modules/pubmaticAnalyticsAdapter.js +49 -33
  132. package/modules/sharedIdSystem.js +5 -11
  133. package/modules/synacormediaBidAdapter.js +11 -2
  134. package/modules/taboolaBidAdapter.js +1 -1
  135. package/modules/userId/eids.js +25 -5
  136. package/modules/userId/index.js +39 -21
  137. package/package.json +1 -1
  138. package/src/auction.js +6 -5
  139. package/src/consentHandler.js +11 -11
  140. package/src/hook.js +2 -2
  141. package/src/storageManager.js +5 -4
  142. package/src/utils/promise.js +96 -21
  143. package/src/utils.js +3 -2
  144. package/test/helpers/consentData.js +2 -1
  145. package/test/spec/auctionmanager_spec.js +1 -6
  146. package/test/spec/modules/adoceanBidAdapter_spec.js +25 -1
  147. package/test/spec/modules/consentManagement_spec.js +75 -16
  148. package/test/spec/modules/eids_spec.js +48 -3
  149. package/test/spec/modules/gdprEnforcement_spec.js +100 -53
  150. package/test/spec/modules/idxIdSystem_spec.js +1 -1
  151. package/test/spec/modules/insticatorBidAdapter_spec.js +46 -1
  152. package/test/spec/modules/ixBidAdapter_spec.js +1 -1
  153. package/test/spec/modules/lassoBidAdapter_spec.js +177 -0
  154. package/test/spec/modules/merkleIdSystem_spec.js +58 -37
  155. package/test/spec/modules/parrableIdSystem_spec.js +2 -1
  156. package/test/spec/modules/pubmaticAnalyticsAdapter_spec.js +117 -0
  157. package/test/spec/modules/synacormediaBidAdapter_spec.js +74 -0
  158. package/test/spec/modules/userId_spec.js +42 -3
  159. package/test/spec/modules/vidazooBidAdapter_spec.js +9 -4
  160. package/test/spec/unit/pbjs_api_spec.js +2 -6
  161. package/test/spec/unit/utils/promise_spec.js +283 -38
  162. package/test/helpers/syncPromise.js +0 -71
@@ -18,6 +18,8 @@ const TCF2 = {
18
18
  'purpose7': { id: 7, name: 'measurement' }
19
19
  }
20
20
 
21
+ const VENDORLESS_MODULE_TYPES = ['fpid-module'];
22
+
21
23
  /*
22
24
  These rules would be used if `consentManagement.gdpr.rules` is undefined by the publisher.
23
25
  */
@@ -123,9 +125,10 @@ function getGvlidForAnalyticsAdapter(code) {
123
125
  * @param {Object} consentData - gdpr consent data
124
126
  * @param {string=} currentModule - Bidder code of the current module
125
127
  * @param {number=} gvlId - GVL ID for the module
128
+ * @param {string=} moduleType module type
126
129
  * @returns {boolean}
127
130
  */
128
- export function validateRules(rule, consentData, currentModule, gvlId) {
131
+ export function validateRules(rule, consentData, currentModule, gvlId, moduleType) {
129
132
  const purposeId = TCF2[Object.keys(TCF2).filter(purposeName => TCF2[purposeName].name === rule.purpose)[0]].id;
130
133
 
131
134
  // return 'true' if vendor present in 'vendorExceptions'
@@ -138,12 +141,14 @@ export function validateRules(rule, consentData, currentModule, gvlId) {
138
141
  const vendorConsent = deepAccess(consentData, `vendorData.vendor.consents.${gvlId}`);
139
142
  const liTransparency = deepAccess(consentData, `vendorData.purpose.legitimateInterests.${purposeId}`);
140
143
 
144
+ const vendorlessModule = includes(VENDORLESS_MODULE_TYPES, moduleType);
145
+
141
146
  /*
142
147
  Since vendor exceptions have already been handled, the purpose as a whole is allowed if it's not being enforced
143
148
  or the user has consented. Similar with vendors.
144
149
  */
145
150
  const purposeAllowed = rule.enforcePurpose === false || purposeConsent === true;
146
- const vendorAllowed = rule.enforceVendor === false || vendorConsent === true;
151
+ const vendorAllowed = rule.enforceVendor === false || vendorConsent === true || vendorlessModule === true;
147
152
 
148
153
  /*
149
154
  Few if any vendors should be declaring Legitimate Interest for Device Access (Purpose 1), but some are claiming
@@ -162,15 +167,16 @@ export function validateRules(rule, consentData, currentModule, gvlId) {
162
167
  * @param {Function} fn reference to original function (used by hook logic)
163
168
  * @param {Number=} gvlid gvlid of the module
164
169
  * @param {string=} moduleName name of the module
170
+ * @param {string=} moduleType module type
165
171
  */
166
- export function deviceAccessHook(fn, gvlid, moduleName, result) {
172
+ export function deviceAccessHook(fn, gvlid, moduleName, moduleType, result) {
167
173
  result = Object.assign({}, {
168
174
  hasEnforcementHook: true
169
175
  });
170
176
  if (!hasDeviceAccess()) {
171
177
  logWarn('Device access is disabled by Publisher');
172
178
  result.valid = false;
173
- fn.call(this, gvlid, moduleName, result);
179
+ fn.call(this, gvlid, moduleName, moduleType, result);
174
180
  } else {
175
181
  const consentData = gdprDataHandler.getConsentData();
176
182
  if (consentData && consentData.gdprApplies) {
@@ -183,24 +189,24 @@ export function deviceAccessHook(fn, gvlid, moduleName, result) {
183
189
  gvlid = getGvlid(moduleName) || gvlid;
184
190
  }
185
191
  const curModule = moduleName || curBidder;
186
- let isAllowed = validateRules(purpose1Rule, consentData, curModule, gvlid);
192
+ let isAllowed = validateRules(purpose1Rule, consentData, curModule, gvlid, moduleType);
187
193
  if (isAllowed) {
188
194
  result.valid = true;
189
- fn.call(this, gvlid, moduleName, result);
195
+ fn.call(this, gvlid, moduleName, moduleType, result);
190
196
  } else {
191
197
  curModule && logWarn(`TCF2 denied device access for ${curModule}`);
192
198
  result.valid = false;
193
199
  storageBlocked.push(curModule);
194
- fn.call(this, gvlid, moduleName, result);
200
+ fn.call(this, gvlid, moduleName, moduleType, result);
195
201
  }
196
202
  } else {
197
203
  // The module doesn't enforce TCF1.1 strings
198
204
  result.valid = true;
199
- fn.call(this, gvlid, moduleName, result);
205
+ fn.call(this, gvlid, moduleName, moduleType, result);
200
206
  }
201
207
  } else {
202
208
  result.valid = true;
203
- fn.call(this, gvlid, moduleName, result);
209
+ fn.call(this, gvlid, moduleName, moduleType, result);
204
210
  }
205
211
  }
206
212
  }
@@ -1,5 +1,5 @@
1
1
  import {config} from '../src/config.js';
2
- import {BANNER} from '../src/mediaTypes.js';
2
+ import {BANNER, VIDEO} from '../src/mediaTypes.js';
3
3
  import {registerBidder} from '../src/adapters/bidderFactory.js';
4
4
  import {deepAccess, generateUUID, logError, isArray} from '../src/utils.js';
5
5
  import {getStorageManager} from '../src/storageManager.js';
@@ -48,14 +48,9 @@ function setUserId(userId) {
48
48
  }
49
49
  }
50
50
 
51
- function buildImpression(bidRequest) {
51
+ function buildBanner(bidRequest) {
52
52
  const format = [];
53
- const ext = {
54
- insticator: {
55
- adUnitId: bidRequest.params.adUnitId,
56
- },
57
- }
58
-
53
+ const pos = deepAccess(bidRequest, 'mediaTypes.banner.pos');
59
54
  const sizes =
60
55
  deepAccess(bidRequest, 'mediaTypes.banner.sizes') || bidRequest.sizes;
61
56
 
@@ -66,27 +61,47 @@ function buildImpression(bidRequest) {
66
61
  });
67
62
  }
68
63
 
69
- const gpid = deepAccess(bidRequest, 'ortb2Imp.ext.gpid');
70
-
71
- if (gpid) {
72
- ext.gpid = gpid;
64
+ return {
65
+ format,
66
+ pos,
73
67
  }
68
+ }
74
69
 
75
- const instl = deepAccess(bidRequest, 'ortb2Imp.instl')
76
- const secure = location.protocol === 'https:' ? 1 : 0;
77
- const pos = deepAccess(bidRequest, 'mediaTypes.banner.pos');
70
+ function buildVideo(bidRequest) {
71
+ const w = deepAccess(bidRequest, 'mediaTypes.video.w');
72
+ const h = deepAccess(bidRequest, 'mediaTypes.video.h');
73
+ const mimes = deepAccess(bidRequest, 'mediaTypes.video.mimes');
78
74
 
79
75
  return {
76
+ mimes,
77
+ w,
78
+ h,
79
+ }
80
+ }
81
+
82
+ function buildImpression(bidRequest) {
83
+ const imp = {
80
84
  id: bidRequest.bidId,
81
85
  tagid: bidRequest.adUnitCode,
82
- instl,
83
- secure,
84
- banner: {
85
- format,
86
- pos,
86
+ instl: deepAccess(bidRequest, 'ortb2Imp.instl'),
87
+ secure: location.protocol === 'https:' ? 1 : 0,
88
+ ext: {
89
+ gpid: deepAccess(bidRequest, 'ortb2Imp.ext.gpid'),
90
+ insticator: {
91
+ adUnitId: bidRequest.params.adUnitId,
92
+ },
87
93
  },
88
- ext,
89
- };
94
+ }
95
+
96
+ if (deepAccess(bidRequest, 'mediaTypes.banner')) {
97
+ imp.banner = buildBanner(bidRequest);
98
+ }
99
+
100
+ if (deepAccess(bidRequest, 'mediaTypes.video')) {
101
+ imp.video = buildVideo(bidRequest);
102
+ }
103
+
104
+ return imp;
90
105
  }
91
106
 
92
107
  function buildDevice() {
@@ -252,31 +267,83 @@ function validateSizes(sizes) {
252
267
  );
253
268
  }
254
269
 
255
- export const spec = {
256
- code: BIDDER_CODE,
257
- gvlid: GVLID,
258
- supportedMediaTypes: [BANNER],
270
+ function validateAdUnitId(bid) {
271
+ if (!bid.params.adUnitId) {
272
+ logError('insticator: missing adUnitId bid parameter');
273
+ return false;
274
+ }
259
275
 
260
- isBidRequestValid: function (bid) {
261
- if (!bid.params.adUnitId) {
262
- logError('insticator: missing adUnitId bid parameter');
263
- return false;
264
- }
276
+ return true;
277
+ }
265
278
 
266
- if (!(BANNER in bid.mediaTypes)) {
267
- logError('insticator: expected banner in mediaTypes');
268
- return false;
269
- }
279
+ function validateMediaType(bid) {
280
+ if (!(BANNER in bid.mediaTypes || VIDEO in bid.mediaTypes)) {
281
+ logError('insticator: expected banner or video in mediaTypes');
282
+ return false;
283
+ }
270
284
 
271
- if (
272
- !validateSizes(bid.sizes) &&
273
- !validateSizes(bid.mediaTypes.banner.sizes)
274
- ) {
275
- logError('insticator: banner sizes not specified or invalid');
276
- return false;
277
- }
285
+ return true;
286
+ }
278
287
 
288
+ function validateBanner(bid) {
289
+ const banner = deepAccess(bid, 'mediaTypes.banner');
290
+
291
+ if (banner === undefined) {
279
292
  return true;
293
+ }
294
+
295
+ if (
296
+ !validateSizes(bid.sizes) &&
297
+ !validateSizes(bid.mediaTypes.banner.sizes)
298
+ ) {
299
+ logError('insticator: banner sizes not specified or invalid');
300
+ return false;
301
+ }
302
+
303
+ return true;
304
+ }
305
+
306
+ function validateVideo(bid) {
307
+ const video = deepAccess(bid, 'mediaTypes.video');
308
+
309
+ if (video === undefined) {
310
+ return true;
311
+ }
312
+
313
+ const videoSize = [
314
+ deepAccess(bid, 'mediaTypes.video.w'),
315
+ deepAccess(bid, 'mediaTypes.video.h'),
316
+ ];
317
+
318
+ if (
319
+ !validateSize(videoSize)
320
+ ) {
321
+ logError('insticator: video size not specified or invalid');
322
+ return false;
323
+ }
324
+
325
+ const mimes = deepAccess(bid, 'mediaTypes.video.mimes');
326
+
327
+ if (!Array.isArray(mimes) || mimes.length === 0) {
328
+ logError('insticator: mimes not specified');
329
+ return false;
330
+ }
331
+
332
+ return true;
333
+ }
334
+
335
+ export const spec = {
336
+ code: BIDDER_CODE,
337
+ gvlid: GVLID,
338
+ supportedMediaTypes: [ BANNER, VIDEO ],
339
+
340
+ isBidRequestValid: function (bid) {
341
+ return (
342
+ validateAdUnitId(bid) &&
343
+ validateMediaType(bid) &&
344
+ validateBanner(bid) &&
345
+ validateVideo(bid)
346
+ );
280
347
  },
281
348
 
282
349
  buildRequests: function (validBidRequests, bidderRequest) {
@@ -30,7 +30,8 @@ import {Renderer} from '../src/Renderer.js';
30
30
  const BIDDER_CODE = 'ix';
31
31
  const ALIAS_BIDDER_CODE = 'roundel';
32
32
  const GLOBAL_VENDOR_ID = 10;
33
- const SECURE_BID_URL = 'https://htlb.casalemedia.com/cygnus';
33
+ const MODULE_TYPE = 'bid-adapter';
34
+ const SECURE_BID_URL = 'https://htlb.casalemedia.com/openrtb/pbjs';
34
35
  const SUPPORTED_AD_TYPES = [BANNER, VIDEO];
35
36
  const BANNER_ENDPOINT_VERSION = 7.2;
36
37
  const VIDEO_ENDPOINT_VERSION = 8.1;
@@ -1086,7 +1087,7 @@ function localStorageHandler(data) {
1086
1087
  hasEnforcementHook: false,
1087
1088
  valid: hasDeviceAccess()
1088
1089
  };
1089
- validateStorageEnforcement(GLOBAL_VENDOR_ID, BIDDER_CODE, DEFAULT_ENFORCEMENT_SETTINGS, (permissions) => {
1090
+ validateStorageEnforcement(GLOBAL_VENDOR_ID, BIDDER_CODE, MODULE_TYPE, DEFAULT_ENFORCEMENT_SETTINGS, (permissions) => {
1090
1091
  if (permissions.valid) {
1091
1092
  storeErrorEventData(data);
1092
1093
  }
@@ -423,4 +423,4 @@ The `size` parameter is no longer a required field, the `siteId` will now be ass
423
423
  In your browser of choice, create a new tab and open the developer tools. In
424
424
  developer tools, select the network tab. Then, navigate to a page where IX is
425
425
  setup to bid. Now, in the network tab, search for requests to
426
- `casalemedia.com/cygnus`. These are the bid requests.
426
+ `casalemedia.com/openrtb/pbjs`. These are the bid requests.
@@ -0,0 +1,133 @@
1
+ import { registerBidder } from '../src/adapters/bidderFactory.js';
2
+ import { BANNER } from '../src/mediaTypes.js';
3
+ import { getStorageManager } from '../src/storageManager.js';
4
+ import { ajax } from '../src/ajax.js';
5
+ import { config } from '../src/config.js';
6
+
7
+ const BIDDER_CODE = 'lasso';
8
+ const ENDPOINT_URL = 'https://trc.lhmos.com/prebid';
9
+ const GET_IUD_URL = 'https://secure.adnxs.com/getuid?';
10
+ const COOKIE_NAME = 'aim-xr';
11
+ const storage = getStorageManager({bidderCode: BIDDER_CODE});
12
+
13
+ export const spec = {
14
+ code: BIDDER_CODE,
15
+ isBidRequestValid: function(bid) {
16
+ return !!(bid.params && bid.params.adUnitId);
17
+ },
18
+
19
+ buildRequests: function(validBidRequests, bidderRequest) {
20
+ if (validBidRequests.length === 0) {
21
+ return [];
22
+ }
23
+
24
+ let aimXR = '';
25
+ if (storage.cookiesAreEnabled) {
26
+ aimXR = storage.getCookie(COOKIE_NAME, undefined);
27
+ }
28
+
29
+ return validBidRequests.map(bidRequest => {
30
+ let sizes = []
31
+ if (bidRequest.mediaTypes && bidRequest.mediaTypes[BANNER] && bidRequest.mediaTypes[BANNER].sizes) {
32
+ sizes = bidRequest.mediaTypes[BANNER].sizes;
33
+ }
34
+
35
+ const payload = {
36
+ auctionStart: bidderRequest.auctionStart,
37
+ url: encodeURIComponent(window.location.href),
38
+ bidderRequestId: bidRequest.bidderRequestId,
39
+ adUnitCode: bidRequest.adUnitCode,
40
+ auctionId: bidRequest.auctionId,
41
+ bidId: bidRequest.bidId,
42
+ transactionId: bidRequest.transactionId,
43
+ device: JSON.stringify(getDeviceData()),
44
+ sizes,
45
+ aimXR,
46
+ uid: '$UID',
47
+ params: JSON.stringify(bidRequest.params),
48
+ crumbs: JSON.stringify(bidRequest.crumbs),
49
+ prebidVersion: '$prebid.version$',
50
+ version: 1,
51
+ coppa: config.getConfig('coppa') == true ? 1 : 0,
52
+ ccpa: bidderRequest.uspConsent || undefined
53
+ }
54
+
55
+ return {
56
+ method: 'GET',
57
+ url: getBidRequestUrl(aimXR),
58
+ data: payload,
59
+ options: {
60
+ withCredentials: false
61
+ },
62
+ };
63
+ });
64
+ },
65
+
66
+ interpretResponse: function(serverResponse) {
67
+ const response = serverResponse && serverResponse.body;
68
+ const bidResponses = [];
69
+
70
+ if (!response) {
71
+ return bidResponses;
72
+ }
73
+
74
+ const bidResponse = {
75
+ requestId: response.bidid,
76
+ cpm: response.bid.price,
77
+ currency: response.cur,
78
+ width: response.bid.w,
79
+ height: response.bid.h,
80
+ creativeId: response.bid.crid,
81
+ netRevenue: response.netRevenue,
82
+ ttl: response.ttl,
83
+ ad: response.bid.ad,
84
+ mediaType: response.bid.mediaType,
85
+ meta: {
86
+ secondaryCatIds: response.bid.cat,
87
+ advertiserDomains: response.bid.advertiserDomains,
88
+ advertiserName: response.meta.advertiserName,
89
+ mediaType: response.bid.mediaType
90
+ }
91
+ };
92
+ bidResponses.push(bidResponse);
93
+ return bidResponses;
94
+ },
95
+
96
+ onTimeout: function(timeoutData) {
97
+ if (timeoutData === null) {
98
+ return;
99
+ }
100
+ ajax(ENDPOINT_URL + '/timeout', null, JSON.stringify(timeoutData), {
101
+ method: 'POST',
102
+ withCredentials: false
103
+ });
104
+ },
105
+
106
+ onBidWon: function(bid) {
107
+ ajax(ENDPOINT_URL + '/won', null, JSON.stringify(bid), {
108
+ method: 'POST',
109
+ withCredentials: false
110
+ });
111
+ },
112
+
113
+ supportedMediaTypes: [BANNER]
114
+ }
115
+
116
+ function getBidRequestUrl(aimXR) {
117
+ if (!aimXR) {
118
+ return GET_IUD_URL + ENDPOINT_URL + '/request';
119
+ }
120
+ return ENDPOINT_URL + '/request'
121
+ }
122
+
123
+ function getDeviceData() {
124
+ const win = window.top;
125
+ return {
126
+ ua: navigator.userAgent,
127
+ width: win.innerWidth || win.document.documentElement.clientWidth || win.document.body.clientWidth,
128
+ height: win.innerHeight || win.document.documentElement.clientHeight || win.document.body.clientHeight,
129
+ browserLanguage: navigator.language,
130
+ }
131
+ }
132
+
133
+ registerBidder(spec);
@@ -0,0 +1,29 @@
1
+ # Overview
2
+
3
+ **Module Name**: Lasso Bidder Adapter
4
+ **Module Type**: Bidder Adapter
5
+ **Maintainer**: headerbidding@lassomarketing.io
6
+
7
+ # Description
8
+
9
+ Connects to Lasso demand source to fetch bids.
10
+ Only banner format supported.
11
+
12
+ # Test Parameters
13
+
14
+ ```
15
+ var adUnits = [{
16
+ code: 'banner-ad-unit',
17
+ mediaTypes: {
18
+ banner: {
19
+ sizes: [[300, 250]],
20
+ }
21
+ },
22
+ bids: [{
23
+ bidder: 'lasso',
24
+ params: {
25
+ adUnitId: '0'
26
+ }
27
+ }]
28
+ }];
29
+ ```
@@ -11,7 +11,7 @@ import {submodule} from '../src/hook.js'
11
11
  import {getStorageManager} from '../src/storageManager.js';
12
12
 
13
13
  const MODULE_NAME = 'merkleId';
14
- const ID_URL = 'https://id2.sv.rkdms.com/identity/';
14
+ const ID_URL = 'https://prebid.sv.rkdms.com/identity/';
15
15
  const DEFAULT_REFRESH = 7 * 3600;
16
16
  const SESSION_COOKIE_NAME = '_svsid';
17
17
 
@@ -30,19 +30,19 @@ function getSession(configParams) {
30
30
  function setCookie(name, value, expires) {
31
31
  let expTime = new Date();
32
32
  expTime.setTime(expTime.getTime() + expires * 1000 * 60);
33
- storage.setCookie(name, value, expTime.toUTCString());
33
+ storage.setCookie(name, value, expTime.toUTCString(), 'Lax');
34
34
  }
35
35
 
36
36
  function setSession(storage, response) {
37
- logInfo('Merkle setting session ');
38
- if (response && response.c && response.c.value && typeof response.c.value === 'string') {
39
- setCookie(SESSION_COOKIE_NAME, response.c.value, storage.expires);
37
+ logInfo('Merkle setting ' + `${SESSION_COOKIE_NAME}`);
38
+ if (response && response[SESSION_COOKIE_NAME] && typeof response[SESSION_COOKIE_NAME] === 'string') {
39
+ setCookie(SESSION_COOKIE_NAME, response[SESSION_COOKIE_NAME], storage.expires);
40
40
  }
41
41
  }
42
42
 
43
43
  function constructUrl(configParams) {
44
44
  const session = getSession(configParams);
45
- let url = configParams.endpoint + `?vendor=${configParams.vendor}&sv_cid=${configParams.sv_cid}&sv_domain=${configParams.sv_domain}&sv_pubid=${configParams.sv_pubid}`;
45
+ let url = configParams.endpoint + `?sv_domain=${configParams.sv_domain}&sv_pubid=${configParams.sv_pubid}&ssp_ids=${configParams.ssp_ids.join()}`;
46
46
  if (session) {
47
47
  url = `${url}&sv_session=${session}`;
48
48
  }
@@ -86,45 +86,52 @@ function generateId(configParams, configStorage) {
86
86
  /** @type {Submodule} */
87
87
  export const merkleIdSubmodule = {
88
88
  /**
89
- * used to link submodule with config
90
- * @type {string}
91
- */
89
+ * used to link submodule with config
90
+ * @type {string}
91
+ */
92
92
  name: MODULE_NAME,
93
+
93
94
  /**
94
- * decode the stored id value for passing to bid requests
95
- * @function
96
- * @param {string} value
97
- * @returns {{merkleId:string}}
98
- */
95
+ * decode the stored id value for passing to bid requests
96
+ * @function
97
+ * @param {string} value
98
+ * @returns {{eids:arrayofields}}
99
+ */
99
100
  decode(value) {
101
+ // Legacy support for a single id
100
102
  const id = (value && value.pam_id && typeof value.pam_id.id === 'string') ? value.pam_id : undefined;
101
103
  logInfo('Merkle id ' + JSON.stringify(id));
102
- return id ? {'merkleId': id} : undefined;
104
+
105
+ if (id) {
106
+ return {'merkleId': id}
107
+ }
108
+
109
+ // Supports multiple IDs for different SSPs
110
+ const merkleIds = (value && value?.merkleId && Array.isArray(value.merkleId)) ? value.merkleId : undefined;
111
+ logInfo('merkleIds: ' + JSON.stringify(merkleIds));
112
+
113
+ return merkleIds ? {'merkleId': merkleIds} : undefined;
103
114
  },
115
+
104
116
  /**
105
- * performs action to obtain id and return a value in the callback's response argument
106
- * @function
107
- * @param {SubmoduleConfig} [config]
108
- * @param {ConsentData} [consentData]
109
- * @returns {IdResponse|undefined}
110
- */
117
+ * performs action to obtain id and return a value in the callback's response argument
118
+ * @function
119
+ * @param {SubmoduleConfig} [config]
120
+ * @param {ConsentData} [consentData]
121
+ * @returns {IdResponse|undefined}
122
+ */
111
123
  getId(config, consentData) {
112
124
  logInfo('User ID - merkleId generating id');
113
125
 
114
126
  const configParams = (config && config.params) || {};
115
127
 
116
- if (!configParams || typeof configParams.vendor !== 'string') {
117
- logError('User ID - merkleId submodule requires a valid vendor to be defined');
118
- return;
119
- }
120
-
121
- if (typeof configParams.sv_cid !== 'string') {
122
- logError('User ID - merkleId submodule requires a valid sv_cid string to be defined');
128
+ if (typeof configParams.sv_pubid !== 'string') {
129
+ logError('User ID - merkleId submodule requires a valid sv_pubid string to be defined');
123
130
  return;
124
131
  }
125
132
 
126
- if (typeof configParams.sv_pubid !== 'string') {
127
- logError('User ID - merkleId submodule requires a valid sv_pubid string to be defined');
133
+ if (!Array.isArray(configParams.ssp_ids)) {
134
+ logError('User ID - merkleId submodule requires a valid ssp_ids array to be defined');
128
135
  return;
129
136
  }
130
137
 
@@ -132,6 +139,7 @@ export const merkleIdSubmodule = {
132
139
  logError('User ID - merkleId submodule does not currently handle consent strings');
133
140
  return;
134
141
  }
142
+
135
143
  if (typeof configParams.endpoint !== 'string') {
136
144
  logWarn('User ID - merkleId submodule endpoint string is not defined');
137
145
  configParams.endpoint = ID_URL
@@ -146,7 +154,7 @@ export const merkleIdSubmodule = {
146
154
  return {callback: resp};
147
155
  },
148
156
  extendId: function (config = {}, consentData, storedId) {
149
- logInfo('User ID - merkleId stored id ' + storedId);
157
+ logInfo('User ID - stored id ' + storedId);
150
158
  const configParams = (config && config.params) || {};
151
159
 
152
160
  if (typeof configParams.endpoint !== 'string') {
@@ -162,15 +170,18 @@ export const merkleIdSubmodule = {
162
170
  if (typeof configParams.sv_domain !== 'string') {
163
171
  configParams.sv_domain = merkleIdSubmodule.findRootDomain();
164
172
  }
173
+
165
174
  const configStorage = (config && config.storage) || {};
166
175
  if (configStorage && configStorage.refreshInSeconds && typeof configParams.refreshInSeconds === 'number') {
167
176
  return {id: storedId};
168
177
  }
178
+
169
179
  let refreshInSeconds = DEFAULT_REFRESH;
170
180
  if (configParams && configParams.refreshInSeconds && typeof configParams.refreshInSeconds === 'number') {
171
181
  refreshInSeconds = configParams.refreshInSeconds;
172
182
  logInfo('User ID - merkleId param refreshInSeconds' + refreshInSeconds);
173
183
  }
184
+
174
185
  const storedDate = new Date(storedId.date);
175
186
  let refreshNeeded = false;
176
187
  if (storedDate) {
@@ -181,6 +192,7 @@ export const merkleIdSubmodule = {
181
192
  return {callback: resp};
182
193
  }
183
194
  }
195
+
184
196
  logInfo('User ID - merkleId not refreshed');
185
197
  return {id: storedId};
186
198
  }
@@ -9,7 +9,8 @@ import * as events from '../src/events.js';
9
9
  import CONSTANTS from '../src/constants.json';
10
10
  import { getStorageManager } from '../src/storageManager.js';
11
11
 
12
- const storage = getStorageManager();
12
+ const MODULE_TYPE = 'fpid-module';
13
+ const storage = getStorageManager({moduleType: MODULE_TYPE});
13
14
 
14
15
  const ID_NAME = '_pubcid';
15
16
  const OPTOUT_NAME = '_pubcid_optout';