prebid.js 7.47.0 → 7.48.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 (178) hide show
  1. package/dist/33acrossBidAdapter.js +1 -1
  2. package/dist/33acrossIdSystem.js +1 -1
  3. package/dist/ablidaBidAdapter.js +1 -1
  4. package/dist/adagioBidAdapter.js +1 -1
  5. package/dist/adbookpspBidAdapter.js +1 -1
  6. package/dist/adgenerationBidAdapter.js +1 -1
  7. package/dist/admaticBidAdapter.js +1 -1
  8. package/dist/adrelevantisBidAdapter.js +1 -1
  9. package/dist/adrinoBidAdapter.js +1 -1
  10. package/dist/adtrgtmeBidAdapter.js +1 -1
  11. package/dist/adxcgBidAdapter.js +1 -1
  12. package/dist/adyoulikeBidAdapter.js +1 -1
  13. package/dist/ajaBidAdapter.js +1 -1
  14. package/dist/amxBidAdapter.js +1 -1
  15. package/dist/amxIdSystem.js +1 -1
  16. package/dist/appierAnalyticsAdapter.js +1 -1
  17. package/dist/appnexusBidAdapter.js +1 -1
  18. package/dist/asoBidAdapter.js +1 -1
  19. package/dist/axonixBidAdapter.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/carodaBidAdapter.js +1 -1
  25. package/dist/chtnwBidAdapter.js +1 -1
  26. package/dist/concertBidAdapter.js +1 -1
  27. package/dist/connectIdSystem.js +1 -1
  28. package/dist/connectadBidAdapter.js +1 -1
  29. package/dist/consumableBidAdapter.js +1 -1
  30. package/dist/conversantAnalyticsAdapter.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/cwireBidAdapter.js +1 -1
  35. package/dist/dependencies.json +4 -0
  36. package/dist/dspxBidAdapter.js +1 -1
  37. package/dist/eplanningBidAdapter.js +1 -1
  38. package/dist/feedadBidAdapter.js +1 -1
  39. package/dist/finativeBidAdapter.js +1 -1
  40. package/dist/freewheel-sspBidAdapter.js +1 -1
  41. package/dist/glimpseBidAdapter.js +1 -1
  42. package/dist/gmosspBidAdapter.js +1 -1
  43. package/dist/goldbachBidAdapter.js +1 -1
  44. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  45. package/dist/greenbidsRtdProvider.js +1 -0
  46. package/dist/gridBidAdapter.js +1 -1
  47. package/dist/gumgumBidAdapter.js +1 -1
  48. package/dist/h12mediaBidAdapter.js +1 -1
  49. package/dist/id5IdSystem.js +1 -1
  50. package/dist/impactifyBidAdapter.js +1 -1
  51. package/dist/improvedigitalBidAdapter.js +1 -1
  52. package/dist/inmarBidAdapter.js +1 -1
  53. package/dist/insticatorBidAdapter.js +1 -1
  54. package/dist/iqmBidAdapter.js +1 -1
  55. package/dist/ixBidAdapter.js +1 -1
  56. package/dist/justpremiumBidAdapter.js +1 -1
  57. package/dist/kargoBidAdapter.js +1 -1
  58. package/dist/konduitAnalyticsAdapter.js +1 -1
  59. package/dist/kueezBidAdapter.js +1 -1
  60. package/dist/kueezRtbBidAdapter.js +1 -1
  61. package/dist/kulturemediaBidAdapter.js +1 -1
  62. package/dist/lassoBidAdapter.js +1 -1
  63. package/dist/lifestreetBidAdapter.js +1 -1
  64. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  65. package/dist/logicadBidAdapter.js +1 -1
  66. package/dist/loglyliftBidAdapter.js +1 -1
  67. package/dist/magniteAnalyticsAdapter.js +1 -1
  68. package/dist/malltvAnalyticsAdapter.js +1 -1
  69. package/dist/marsmediaBidAdapter.js +1 -1
  70. package/dist/mediafuseBidAdapter.js +1 -1
  71. package/dist/mediasquareBidAdapter.js +1 -1
  72. package/dist/mgidBidAdapter.js +1 -1
  73. package/dist/minutemediaBidAdapter.js +1 -1
  74. package/dist/minutemediaplusBidAdapter.js +1 -1
  75. package/dist/nexx360BidAdapter.js +1 -1
  76. package/dist/not-for-prod/prebid.js +137 -135
  77. package/dist/oguryBidAdapter.js +1 -1
  78. package/dist/onetagBidAdapter.js +1 -1
  79. package/dist/ooloAnalyticsAdapter.js +1 -1
  80. package/dist/optidigitalBidAdapter.js +1 -1
  81. package/dist/orbitsoftBidAdapter.js +1 -1
  82. package/dist/outbrainBidAdapter.js +1 -1
  83. package/dist/parrableIdSystem.js +1 -1
  84. package/dist/pixfutureBidAdapter.js +1 -1
  85. package/dist/prebid-core.js +1 -1
  86. package/dist/publinkIdSystem.js +1 -1
  87. package/dist/pubmaticBidAdapter.js +1 -1
  88. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  89. package/dist/pxyzBidAdapter.js +1 -1
  90. package/dist/quantcastBidAdapter.js +1 -1
  91. package/dist/radsBidAdapter.js +1 -1
  92. package/dist/readpeakBidAdapter.js +1 -1
  93. package/dist/relaidoBidAdapter.js +1 -1
  94. package/dist/relevantdigitalBidAdapter.js +1 -0
  95. package/dist/rhythmoneBidAdapter.js +1 -1
  96. package/dist/riseBidAdapter.js +1 -1
  97. package/dist/rtbhouseBidAdapter.js +1 -1
  98. package/dist/rubiconAnalyticsAdapter.js +1 -1
  99. package/dist/rubiconBidAdapter.js +1 -1
  100. package/dist/seedingAllianceBidAdapter.js +1 -1
  101. package/dist/seedtagBidAdapter.js +1 -1
  102. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  103. package/dist/sharethroughBidAdapter.js +1 -1
  104. package/dist/shinezBidAdapter.js +1 -1
  105. package/dist/smaatoBidAdapter.js +1 -1
  106. package/dist/smartadserverBidAdapter.js +1 -1
  107. package/dist/smartxBidAdapter.js +1 -1
  108. package/dist/smilewantedBidAdapter.js +1 -1
  109. package/dist/sonobiBidAdapter.js +1 -1
  110. package/dist/sovrnAnalyticsAdapter.js +1 -1
  111. package/dist/sovrnBidAdapter.js +1 -1
  112. package/dist/sspBCBidAdapter.js +1 -1
  113. package/dist/stvBidAdapter.js +1 -1
  114. package/dist/sublimeBidAdapter.js +1 -1
  115. package/dist/synacormediaBidAdapter.js +1 -1
  116. package/dist/targetVideoBidAdapter.js +1 -1
  117. package/dist/teadsBidAdapter.js +1 -1
  118. package/dist/trionBidAdapter.js +1 -1
  119. package/dist/tripleliftBidAdapter.js +1 -1
  120. package/dist/ttdBidAdapter.js +1 -1
  121. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  122. package/dist/uid2IdSystem.js +1 -1
  123. package/dist/underdogmediaBidAdapter.js +1 -1
  124. package/dist/undertoneBidAdapter.js +1 -1
  125. package/dist/userId.js +1 -1
  126. package/dist/vdoaiBidAdapter.js +1 -1
  127. package/dist/vidazooBidAdapter.js +1 -1
  128. package/dist/videobyteBidAdapter.js +1 -1
  129. package/dist/visxBidAdapter.js +1 -1
  130. package/dist/vuukleBidAdapter.js +1 -1
  131. package/dist/widespaceBidAdapter.js +1 -1
  132. package/dist/winrBidAdapter.js +1 -1
  133. package/dist/wipesBidAdapter.js +1 -1
  134. package/dist/yahoosspBidAdapter.js +1 -1
  135. package/dist/yieldmoBidAdapter.js +1 -1
  136. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  137. package/dist/yieldoneBidAdapter.js +1 -1
  138. package/modules/ablidaBidAdapter.js +4 -5
  139. package/modules/admaticBidAdapter.js +32 -5
  140. package/modules/adrinoBidAdapter.js +11 -4
  141. package/modules/axonixBidAdapter.js +6 -6
  142. package/modules/connectIdSystem.js +5 -2
  143. package/modules/criteoBidAdapter.js +3 -5
  144. package/modules/dspxBidAdapter.js +2 -3
  145. package/modules/freewheel-sspBidAdapter.js +32 -7
  146. package/modules/greenbidsRtdProvider.js +110 -0
  147. package/modules/greenbidsRtdProvider.md +65 -0
  148. package/modules/impactifyBidAdapter.js +0 -1
  149. package/modules/iqmBidAdapter.js +1 -2
  150. package/modules/orbitsoftBidAdapter.js +1 -2
  151. package/modules/radsBidAdapter.js +3 -4
  152. package/modules/relevantdigitalBidAdapter.js +198 -0
  153. package/modules/relevantdigitalBidAdapter.md +117 -0
  154. package/modules/rtbhouseBidAdapter.js +6 -9
  155. package/modules/sovrnBidAdapter.js +4 -0
  156. package/modules/stvBidAdapter.js +4 -5
  157. package/modules/tripleliftBidAdapter.js +14 -3
  158. package/modules/ttdBidAdapter.js +73 -71
  159. package/modules/underdogmediaBidAdapter.js +9 -12
  160. package/modules/userId/index.js +1 -1
  161. package/modules/vdoaiBidAdapter.js +2 -3
  162. package/modules/wipesBidAdapter.js +2 -3
  163. package/modules/yieldoneBidAdapter.js +3 -4
  164. package/package.json +1 -1
  165. package/test/spec/modules/adlooxAdServerVideo_spec.js +18 -35
  166. package/test/spec/modules/admaticBidAdapter_spec.js +164 -11
  167. package/test/spec/modules/adrinoBidAdapter_spec.js +50 -2
  168. package/test/spec/modules/connectIdSystem_spec.js +4 -4
  169. package/test/spec/modules/criteoBidAdapter_spec.js +56 -0
  170. package/test/spec/modules/freewheel-sspBidAdapter_spec.js +31 -2
  171. package/test/spec/modules/greenbidsRtdProvider_spec.js +210 -0
  172. package/test/spec/modules/relevantdigitalBidAdapter_spec.js +295 -0
  173. package/test/spec/modules/rtbhouseBidAdapter_spec.js +22 -0
  174. package/test/spec/modules/sovrnBidAdapter_spec.js +65 -0
  175. package/test/spec/modules/tripleliftBidAdapter_spec.js +53 -8
  176. package/test/spec/modules/ttdBidAdapter_spec.js +20 -0
  177. package/test/spec/ortbConverter/userId_spec.js +12 -0
  178. package/test/spec/modules/realvuAnalyticsAdapter_spec.js +0 -189
@@ -0,0 +1,110 @@
1
+ import { logError } from '../src/utils.js';
2
+ import { ajax } from '../src/ajax.js';
3
+ import { submodule } from '../src/hook.js';
4
+
5
+ const MODULE_NAME = 'greenbidsRtdProvider';
6
+ const MODULE_VERSION = '1.0.0';
7
+ const ENDPOINT = 'https://europe-west1-greenbids-357713.cloudfunctions.net/partner-selection';
8
+
9
+ const auctionInfo = {};
10
+ const rtdOptions = {};
11
+
12
+ function init(moduleConfig) {
13
+ let params = moduleConfig?.params;
14
+ if (!params?.pbuid) {
15
+ logError('Greenbids pbuid is not set!');
16
+ return false;
17
+ } else {
18
+ rtdOptions.pbuid = params?.pbuid;
19
+ rtdOptions.targetTPR = params?.targetTPR || 0.99;
20
+ rtdOptions.timeout = params?.timeout || 200;
21
+ return true;
22
+ }
23
+ }
24
+
25
+ function onAuctionInitEvent(auctionDetails) {
26
+ auctionInfo.auctionId = auctionDetails.auctionId;
27
+ }
28
+
29
+ function getBidRequestData(reqBidsConfigObj, callback, config, userConsent) {
30
+ let promise = createPromise(reqBidsConfigObj);
31
+ promise.then(callback);
32
+ }
33
+
34
+ function createPromise(reqBidsConfigObj) {
35
+ return new Promise((resolve) => {
36
+ const timeoutId = setTimeout(() => {
37
+ resolve(reqBidsConfigObj);
38
+ }, rtdOptions.timeout);
39
+ ajax(
40
+ ENDPOINT,
41
+ {
42
+ success: (response) => {
43
+ processSuccessResponse(response, timeoutId, reqBidsConfigObj);
44
+ resolve(reqBidsConfigObj);
45
+ },
46
+ error: () => {
47
+ clearTimeout(timeoutId);
48
+ resolve(reqBidsConfigObj);
49
+ },
50
+ },
51
+ createPayload(reqBidsConfigObj),
52
+ { contentType: 'application/json' }
53
+ );
54
+ });
55
+ }
56
+
57
+ function processSuccessResponse(response, timeoutId, reqBidsConfigObj) {
58
+ clearTimeout(timeoutId);
59
+ const responseAdUnits = JSON.parse(response);
60
+
61
+ updateAdUnitsBasedOnResponse(reqBidsConfigObj.adUnits, responseAdUnits);
62
+ }
63
+
64
+ function updateAdUnitsBasedOnResponse(adUnits, responseAdUnits) {
65
+ adUnits.forEach((adUnit) => {
66
+ const matchingAdUnit = findMatchingAdUnit(responseAdUnits, adUnit.code);
67
+ if (matchingAdUnit) {
68
+ removeFalseBidders(adUnit, matchingAdUnit);
69
+ }
70
+ });
71
+ }
72
+
73
+ function findMatchingAdUnit(responseAdUnits, adUnitCode) {
74
+ return responseAdUnits.find((responseAdUnit) => responseAdUnit.code === adUnitCode);
75
+ }
76
+
77
+ function removeFalseBidders(adUnit, matchingAdUnit) {
78
+ const falseBidders = getFalseBidders(matchingAdUnit.bidders);
79
+ adUnit.bids = adUnit.bids.filter((bidRequest) => !falseBidders.includes(bidRequest.bidder));
80
+ }
81
+
82
+ function getFalseBidders(bidders) {
83
+ return Object.entries(bidders)
84
+ .filter(([bidder, shouldKeep]) => !shouldKeep)
85
+ .map(([bidder]) => bidder);
86
+ }
87
+
88
+ function createPayload(reqBidsConfigObj) {
89
+ return JSON.stringify({
90
+ auctionId: auctionInfo.auctionId,
91
+ version: MODULE_VERSION,
92
+ referrer: window.location.href,
93
+ prebid: '$prebid.version$',
94
+ rtdOptions: rtdOptions,
95
+ adUnits: reqBidsConfigObj.adUnits,
96
+ });
97
+ }
98
+
99
+ export const greenbidsSubmodule = {
100
+ name: MODULE_NAME,
101
+ init: init,
102
+ onAuctionInitEvent: onAuctionInitEvent,
103
+ getBidRequestData: getBidRequestData,
104
+ updateAdUnitsBasedOnResponse: updateAdUnitsBasedOnResponse,
105
+ findMatchingAdUnit: findMatchingAdUnit,
106
+ removeFalseBidders: removeFalseBidders,
107
+ getFalseBidders: getFalseBidders,
108
+ };
109
+
110
+ submodule('realTimeData', greenbidsSubmodule);
@@ -0,0 +1,65 @@
1
+ # Overview
2
+
3
+ ```
4
+ Module Name: Greenbids RTD Provider
5
+ Module Type: RTD Provider
6
+ Maintainer: jb@greenbids.ai
7
+ ```
8
+
9
+ # Description
10
+
11
+ The Greenbids RTD adapter allows to dynamically filter calls to SSP to reduce outgoing call to the programmatics chain, reducing ad serving carbon impact
12
+
13
+ ## Configuration
14
+
15
+ This module is configured as part of the `realTimeData.dataProviders` object.
16
+
17
+ {: .table .table-bordered .table-striped }
18
+ | Name | Scope | Description | Example | Type |
19
+ |------------|----------|----------------------------------------|---------------|----------|
20
+ | `name ` | required | Real time data module name | `'greenbidsRtdProvider'` | `string` |
21
+ | `waitForIt ` | required (mandatory true value) | Tells prebid auction to wait for the result of this module | `'true'` | `boolean` |
22
+ | `params` | required | | | `Object` |
23
+ | `params.pbuid` | required | The client site id provided by Greenbids. | `'TEST_FROM_GREENBIDS'` | `string` |
24
+ | `params.targetTPR` | optional (default 0.95) | Target True positive rate for the throttling model | `0.99` | `[0-1]` |
25
+ | `params.timeout` | optional (default 200) | Maximum amount of milliseconds allowed for module to finish working (has to be <= to the realTimeData.auctionDelay property) | `200` | `number` |
26
+
27
+ #### Example
28
+
29
+ ```javascript
30
+ const greenbidsDataProvider = {
31
+ name: 'greenbidsRtdProvider',
32
+ waitForIt: true,
33
+ params: {
34
+ pbuid: 'TEST_FROM_GREENBIDS',
35
+ timeout: 200
36
+ }
37
+ };
38
+
39
+ pbjs.setConfig({
40
+ realTimeData: {
41
+ auctionDelay: 200,
42
+ dataProviders: [greenbidsDataProvider]
43
+ }
44
+ });
45
+ ```
46
+
47
+ ## Integration
48
+ To install the module, follow these instructions:
49
+
50
+ #### Step 1: Contact Greenbids to get a pbuid and account
51
+
52
+ #### Step 2: Integrate the Greenbids Analytics Adapter
53
+
54
+ Greenbids RTD module works hand in hand with Greenbids Analytics module
55
+ See prebid Analytics modules -> Greenbids Analytics module
56
+
57
+ #### Step 3: Prepare the base Prebid file
58
+
59
+ - Option 1: Use Prebid [Download](/download.html) page to build the prebid package. Ensure that you do check *Greenbids RTD Provider* module
60
+
61
+ - Option 2: From the command line, run `gulp build --modules=greenbidsRtdProvider,...`
62
+
63
+ #### Step 4: Set configuration
64
+
65
+ Enable Greenbids Real Time Module using `pbjs.setConfig`. Example is provided in Configuration section.
@@ -91,7 +91,6 @@ const createOpenRtbRequest = (validBidRequests, bidderRequest) => {
91
91
 
92
92
  if (bidderRequest.uspConsent) {
93
93
  deepSetValue(request, 'regs.ext.us_privacy', bidderRequest.uspConsent);
94
- this.syncStore.uspConsent = bidderRequest.uspConsent;
95
94
  }
96
95
 
97
96
  if (GETCONFIG('coppa') == true) deepSetValue(request, 'regs.coppa', 1);
@@ -1,6 +1,5 @@
1
1
  import {_each, deepAccess, getBidIdParameter, isArray} from '../src/utils.js';
2
2
  import {registerBidder} from '../src/adapters/bidderFactory.js';
3
- import {config} from '../src/config.js';
4
3
  import {BANNER, VIDEO} from '../src/mediaTypes.js';
5
4
  import {INSTREAM} from '../src/video.js';
6
5
 
@@ -155,7 +154,7 @@ export const spec = {
155
154
  auctionId: bidRequest.data.auctionId,
156
155
  mediaType: bidRequest.data.imp.mediatype,
157
156
 
158
- ttl: bid.ttl || config.getConfig('_bidderTimeout')
157
+ ttl: bid.ttl || 60
159
158
  };
160
159
 
161
160
  if (bidRequest.data.imp.mediatype === VIDEO) {
@@ -1,6 +1,5 @@
1
1
  import * as utils from '../src/utils.js';
2
2
  import {registerBidder} from '../src/adapters/bidderFactory.js';
3
- import {config} from '../src/config.js';
4
3
 
5
4
  const BIDDER_CODE = 'orbitsoft';
6
5
  let styleParamsMap = {
@@ -122,7 +121,7 @@ export const spec = {
122
121
  const HEIGHT = serverBody.height;
123
122
  const CREATIVE = serverBody.content_url;
124
123
  const CALLBACK_UID = serverBody.callback_uid;
125
- const TIME_TO_LIVE = config.getConfig('_bidderTimeout');
124
+ const TIME_TO_LIVE = 60;
126
125
  const REFERER = utils.getWindowTop();
127
126
  let bidRequest = request.bidRequest;
128
127
  if (CPM > 0 && WIDTH > 0 && HEIGHT > 0) {
@@ -1,7 +1,6 @@
1
- import { deepAccess } from '../src/utils.js';
2
- import {config} from '../src/config.js';
1
+ import {deepAccess} from '../src/utils.js';
3
2
  import {registerBidder} from '../src/adapters/bidderFactory.js';
4
- import { BANNER, VIDEO } from '../src/mediaTypes.js';
3
+ import {BANNER, VIDEO} from '../src/mediaTypes.js';
5
4
 
6
5
  const BIDDER_CODE = 'rads';
7
6
  const ENDPOINT_URL = 'https://rads.recognified.net/md.request.php';
@@ -86,7 +85,7 @@ export const spec = {
86
85
  dealId: dealId,
87
86
  currency: currency,
88
87
  netRevenue: netRevenue,
89
- ttl: config.getConfig('_bidderTimeout'),
88
+ ttl: 60,
90
89
  meta: {
91
90
  advertiserDomains: response.adomain || []
92
91
  }
@@ -0,0 +1,198 @@
1
+ import {registerBidder} from '../src/adapters/bidderFactory.js';
2
+ import {ortbConverter} from '../libraries/ortbConverter/converter.js'
3
+ import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js';
4
+ import {config} from '../src/config.js';
5
+ import {pbsExtensions} from '../libraries/pbsExtensions/pbsExtensions.js'
6
+ import {deepSetValue, isEmpty, deepClone, shuffle, triggerPixel, deepAccess} from '../src/utils.js';
7
+
8
+ const BIDDER_CODE = 'relevantdigital';
9
+
10
+ /** Global settings per bidder-code for this adapter (which might be > 1 if using aliasing) */
11
+ let configByBidder = {};
12
+
13
+ /** Used by the tests */
14
+ export const resetBidderConfigs = () => {
15
+ configByBidder = {};
16
+ };
17
+
18
+ /** Settings ber bidder-code. checkParams === true means that it can optionally be set in bid-params */
19
+ const FIELDS = [
20
+ { name: 'pbsHost', checkParams: true, required: true },
21
+ { name: 'accountId', checkParams: true, required: true },
22
+ { name: 'pbsBufferMs', checkParams: false, required: false, default: 250 },
23
+ { name: 'useSourceBidderCode', checkParams: false, required: false, default: false },
24
+ ];
25
+
26
+ const SYNC_HTML = 'https://cdn.relevant-digital.com/resources/load-cookie.html';
27
+ const MAX_SYNC_COUNT = 10; // Max server-side bidder to sync at once via the iframe
28
+
29
+ /** Get settings for a bidder-code via config and, if needed, bid parameters */
30
+ const getBidderConfig = (bids) => {
31
+ const { bidder } = bids[0];
32
+ const cfg = configByBidder[bidder] || {
33
+ ...Object.fromEntries(FIELDS.filter((f) => 'default' in f).map((f) => [f.name, f.default])),
34
+ syncedBidders: {}, // To keep track of S2S-bidders we already (started to) synced
35
+ };
36
+ if (cfg.complete) {
37
+ return cfg; // Most common case, we already have the settings we need (and we won't re-read them)
38
+ }
39
+ configByBidder[bidder] = cfg;
40
+ const bidderConfiguration = config.getConfig(bidder) || {};
41
+
42
+ // Read settings set by setConfig({ [bidder]: { ... }}) and if not available - from bid params
43
+ FIELDS.forEach(({ name, checkParams }) => {
44
+ cfg[name] = bidderConfiguration[name] || cfg[name];
45
+ if (!cfg[name] && checkParams) {
46
+ bids.forEach((bid) => {
47
+ cfg[name] = cfg[name] || bid.params?.[name];
48
+ });
49
+ }
50
+ });
51
+ cfg.complete = FIELDS.every((field) => !field.required || cfg[field.name]);
52
+ if (cfg.complete) {
53
+ cfg.pbsHost = cfg.pbsHost.trim().replace('http://', 'https://');
54
+ if (cfg.pbsHost.indexOf('https://') < 0) {
55
+ cfg.pbsHost = `https://${cfg.pbsHost}`;
56
+ }
57
+ }
58
+ return cfg;
59
+ }
60
+
61
+ const converter = ortbConverter({
62
+ context: {
63
+ netRevenue: true,
64
+ ttl: 300
65
+ },
66
+ processors: pbsExtensions,
67
+ imp(buildImp, bidRequest, context) {
68
+ // Set stored request id from placementId
69
+ const imp = buildImp(bidRequest, context);
70
+ const { placementId } = bidRequest.params;
71
+ deepSetValue(imp, 'ext.prebid.storedrequest.id', placementId);
72
+ delete imp.ext.prebid.bidder;
73
+ return imp;
74
+ },
75
+ overrides: {
76
+ bidResponse: {
77
+ bidderCode(orig, bidResponse, bid, { bidRequest }) {
78
+ const { bidder, params = {} } = bidRequest || {};
79
+ let useSourceBidderCode = configByBidder[bidder]?.useSourceBidderCode;
80
+ if ('useSourceBidderCode' in params) {
81
+ useSourceBidderCode = params.useSourceBidderCode;
82
+ }
83
+ // Only use the orignal function when useSourceBidderCode is true, else our own bidder code will be used
84
+ if (useSourceBidderCode) {
85
+ orig.apply(this, [...arguments].slice(1));
86
+ }
87
+ },
88
+ },
89
+ }
90
+ });
91
+
92
+ export const spec = {
93
+ code: BIDDER_CODE,
94
+ gvlid: 1100,
95
+ supportedMediaTypes: [BANNER, VIDEO, NATIVE],
96
+
97
+ /** We need both params.placementId + a complete configuration (pbsHost + accountId) to continue **/
98
+ isBidRequestValid: (bid) => bid.params?.placementId && getBidderConfig([bid]).complete,
99
+
100
+ /** Trigger impression-pixel */
101
+ onBidWon: ({pbsWurl}) => pbsWurl && triggerPixel(pbsWurl),
102
+
103
+ /** Build BidRequest for PBS */
104
+ buildRequests(bidRequests, bidderRequest) {
105
+ const { bidder } = bidRequests[0];
106
+ const cfg = getBidderConfig(bidRequests);
107
+ const data = converter.toORTB({bidRequests, bidderRequest});
108
+
109
+ /** Set tmax, in general this will be timeout - pbsBufferMs */
110
+ const pbjsTimeout = bidderRequest.timeout || 1000;
111
+ data.tmax = Math.min(Math.max(pbjsTimeout - cfg.pbsBufferMs, cfg.pbsBufferMs), pbjsTimeout);
112
+
113
+ delete data.ext?.prebid?.aliases; // We don't need/want to send aliases to PBS
114
+ deepSetValue(data, 'ext.relevant', {
115
+ ...data.ext?.relevant,
116
+ adapter: true, // For internal analytics
117
+ });
118
+ deepSetValue(data, 'ext.prebid.storedrequest.id', cfg.accountId);
119
+ data.ext.prebid.passthrough = {
120
+ ...data.ext.prebid.passthrough,
121
+ relevant: { bidder }, // to find config for the right bidder-code in interpretResponse / getUserSyncs
122
+ };
123
+ return [{
124
+ method: 'POST',
125
+ url: `${cfg.pbsHost}/openrtb2/auction`,
126
+ data
127
+ }];
128
+ },
129
+
130
+ /** Read BidResponse from PBS and make necessary adjustments to not make it appear to come from unknown bidders */
131
+ interpretResponse(response, request) {
132
+ const resp = deepClone(response.body);
133
+ const { bidder } = request.data.ext.prebid.passthrough.relevant;
134
+
135
+ // Modify response times / errors for actual PBS bidders into a single value
136
+ const MODIFIERS = {
137
+ responsetimemillis: (values) => Math.max(...values),
138
+ errors: (values) => [].concat(...values),
139
+ };
140
+ Object.entries(MODIFIERS).forEach(([field, combineFn]) => {
141
+ const obj = resp.ext?.[field];
142
+ if (!isEmpty(obj)) {
143
+ resp.ext[field] = {[bidder]: combineFn(Object.values(obj))};
144
+ }
145
+ });
146
+
147
+ const bids = converter.fromORTB({response: resp, request: request.data}).bids;
148
+ return bids;
149
+ },
150
+
151
+ /** Do syncing, but avoid running the sync > 1 time for S2S bidders */
152
+ getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent) {
153
+ if (!syncOptions.iframeEnabled && !syncOptions.pixelEnabled) {
154
+ return [];
155
+ }
156
+ const syncs = [];
157
+ serverResponses.forEach(({ body }) => {
158
+ const { pbsHost, syncedBidders } = configByBidder[body.ext.prebid.passthrough.relevant.bidder] || {};
159
+ if (!pbsHost) {
160
+ return;
161
+ }
162
+ const { gdprApplies, consentString } = gdprConsent || {};
163
+ let bidders = Object.keys(body.ext?.responsetimemillis || {});
164
+ bidders = bidders.reduce((acc, curr) => {
165
+ if (!syncedBidders[curr]) {
166
+ acc.push(curr);
167
+ syncedBidders[curr] = true;
168
+ }
169
+ return acc;
170
+ }, []);
171
+ bidders = shuffle(bidders).slice(0, MAX_SYNC_COUNT); // Shuffle to not always leave out the same bidders
172
+ if (!bidders.length) {
173
+ return; // All bidders already synced
174
+ }
175
+ if (syncOptions.iframeEnabled) {
176
+ const params = {
177
+ endpoint: `${pbsHost}/cookie_sync`,
178
+ max_sync_count: bidders.length,
179
+ gdpr: gdprApplies ? 1 : 0,
180
+ gdpr_consent: consentString,
181
+ us_privacy: uspConsent,
182
+ bidders: bidders.join(','),
183
+ };
184
+ const qs = Object.entries(params)
185
+ .filter(([k, v]) => ![null, undefined, ''].includes(v))
186
+ .map(([k, v]) => `${k}=${encodeURIComponent(v.toString())}`)
187
+ .join('&');
188
+ syncs.push({ type: 'iframe', url: `${SYNC_HTML}?${qs}` });
189
+ } else { // Else, try to pixel-sync (for future-compatibility)
190
+ const pixels = deepAccess(body, `ext.relevant.sync`, []).filter(({ type }) => type === 'redirect');
191
+ syncs.push(...pixels.map(({ url }) => ({ type: 'image', url })));
192
+ }
193
+ });
194
+ return syncs;
195
+ },
196
+ };
197
+
198
+ registerBidder(spec);
@@ -0,0 +1,117 @@
1
+ # Overview
2
+
3
+ ```
4
+ Module Name: Relevant Digital Bid Adapter
5
+ Module Type: Bidder Adapter
6
+ Maintainer: support@relevant-digital.com
7
+ ```
8
+
9
+ # Description
10
+
11
+ This adapter is used for integration with providers using the **[Relevant Yield](https://www.relevant-digital.com/relevantyield)** platform. The provider will supply the necessary **pbsHost** and **accountId** settings along with the **placementId** bid parameters per ad unit.
12
+
13
+ # Example setup using pbjs.setConfig()
14
+ This is the recommended method to set the global configuration parameters.
15
+ ```javascript
16
+ pbjs.setConfig({
17
+ relevantdigital: {
18
+ pbsHost: 'pbs-example.relevant-digital.com',
19
+ accountId: '6204e5fa70e3ad10821b84ff',
20
+ },
21
+ });
22
+
23
+ var adUnits = [
24
+ {
25
+ code: 'test-div',
26
+ mediaTypes: { banner: { sizes: [[300, 250], [320, 320]] }},
27
+ bids: [
28
+ {
29
+ bidder: 'relevantdigital',
30
+ params: {
31
+ placementId: '6204e83a077c5825441b8508_620f9e8e4fe67c1f87cd30ed',
32
+ }
33
+ }
34
+ ],
35
+ }
36
+ ];
37
+ ```
38
+ # Example setup using only bid params
39
+ This method to set the global configuration parameters (like **pbsHost**) in **params** could simplify integration of a provider for some publishers. Setting different global config-parameters on different bids is not supported in general*, as the first settings found will be used and any subsequent global settings will be ignored.
40
+
41
+  * _The exception is `useSourceBidderCode` which can be overriden individually per ad unit._
42
+ ```javascript
43
+ var adUnits = [
44
+ {
45
+ code: 'test-div',
46
+ mediaTypes: { banner: { sizes: [[300, 250], [320, 320]] }},
47
+ bids: [
48
+ {
49
+ bidder: 'relevantdigital',
50
+ params: {
51
+ placementId: '6204e83a077c5825441b8508_620f9e8e4fe67c1f87cd30ed',
52
+ pbsHost: 'pbs-example.relevant-digital.com',
53
+ accountId: '6204e5fa70e3ad10821b84ff',
54
+ }
55
+ }
56
+ ],
57
+ }
58
+ ];
59
+ ```
60
+
61
+ # Example setup with multiple providers
62
+ **Notice:** Placements below are _not_ live test placements
63
+ ```javascript
64
+
65
+ pbjs.aliasBidder('relevantdigital', 'providerA');
66
+ pbjs.aliasBidder('relevantdigital', 'providerB');
67
+
68
+ pbjs.setConfig({
69
+ providerA: {
70
+ pbsHost: 'pbs-example-a.relevant-digital.com',
71
+ accountId: '620533ae7f5bbe1691bbb815',
72
+ },
73
+ providerB: {
74
+ pbsHost: 'pbs-example-b.relevant-digital.com',
75
+ accountId: '990533ae7f5bbe1691bbb815',
76
+ },
77
+ });
78
+
79
+ var adUnits = [
80
+ {
81
+ code: 'test-div',
82
+ mediaTypes: { banner: { sizes: [[300, 250], [320, 320]] }},
83
+ bids: [
84
+ {
85
+ bidder: 'providerA',
86
+ params: {
87
+ placementId: '610525862d7517bfd4bbb81e_620523b7d1dbed6b0fbbb817',
88
+ }
89
+ },
90
+ {
91
+ bidder: 'providerB',
92
+ params: {
93
+ placementId: '990525862d7517bfd4bbb81e_770523b7d1dbed6b0fbbb817',
94
+ }
95
+ },
96
+ ],
97
+ }
98
+ ];
99
+ ```
100
+
101
+ # Bid Parameters
102
+
103
+ | Name | Scope | Description | Example | Type |
104
+ |---------------|----------|---------------------------------------------------------|----------------------------|--------------|
105
+ | `placementId` | required | The placement id. | `'6204e83a077c5825441b8508_620f9e8e4fe67c1f87cd30ed'` | `String` |
106
+ | `pbsHost` | required if not set in config | Host name of the server. | `'pbs-example.relevant-digital.com'` | `String` |
107
+ | `accountId` | required if not set in config | The account id. | `'6204e5fa70e3ad10821b84ff'` | `String` |
108
+ | `useSourceBidderCode` | optional | Set to `true` in order to use the bidder code of the actual server-side bidder in bid responses. You **MUST** also use `allowAlternateBidderCodes: true` in `bidderSettings` if you enabled this - as otherwise the bids will be rejected.| `true` | `Boolean` |
109
+
110
+ # Config Parameters
111
+
112
+ | Name | Scope | Description | Example | Type |
113
+ |---------------|----------|---------------------------------------------------------|----------------------------|--------------|
114
+ | `pbsHost` | required if not set in bid parameters | Host name of the server. | `'pbs-example.relevant-digital.com'` | `String` |
115
+ | `accountId` | required if not set in bid parameters | The account id. | `'6204e5fa70e3ad10821b84ff'` | `String` |
116
+ | `pbsBufferMs` | optional | How much less in *milliseconds* the server's internal timeout should be compared to the normal Prebid timeout. Default is *250*. To be increased in cases of frequent timeouts. | `250` | `Integer` |
117
+ | `useSourceBidderCode` | optional | Set to `true` in order to use the bidder code of the actual server-side bidder in bid responses. You **MUST** also use `allowAlternateBidderCodes: true` in `bidderSettings` if you enabled this - as otherwise the bids will be rejected.| `true` | `Boolean` |
@@ -85,15 +85,12 @@ export const spec = {
85
85
  }
86
86
 
87
87
  const ortb2Params = bidderRequest?.ortb2 || {};
88
- if (ortb2Params.site) {
89
- mergeDeep(request, { site: ortb2Params.site });
90
- }
91
- if (ortb2Params.user) {
92
- mergeDeep(request, { user: ortb2Params.user });
93
- }
94
- if (ortb2Params.device) {
95
- mergeDeep(request, { device: ortb2Params.device });
96
- }
88
+ ['site', 'user', 'device', 'bcat', 'badv'].forEach(entry => {
89
+ const ortb2Param = ortb2Params[entry];
90
+ if (ortb2Param) {
91
+ mergeDeep(request, { [entry]: ortb2Param });
92
+ }
93
+ });
97
94
 
98
95
  let computedEndpointUrl = ENDPOINT_URL;
99
96
 
@@ -173,6 +173,10 @@ export const spec = {
173
173
  if (bidderRequest.uspConsent) {
174
174
  deepSetValue(sovrnBidReq, 'regs.ext.us_privacy', bidderRequest.uspConsent);
175
175
  }
176
+ if (bidderRequest.gppConsent) {
177
+ deepSetValue(sovrnBidReq, 'regs.gpp', bidderRequest.gppConsent.gppString);
178
+ deepSetValue(sovrnBidReq, 'regs.gpp_sid', bidderRequest.gppConsent.applicableSections);
179
+ }
176
180
 
177
181
  if (eids) {
178
182
  deepSetValue(sovrnBidReq, 'user.ext.eids', eids)
@@ -1,7 +1,6 @@
1
- import { deepAccess } from '../src/utils.js';
2
- import { config } from '../src/config.js';
3
- import { registerBidder } from '../src/adapters/bidderFactory.js';
4
- import { BANNER, VIDEO } from '../src/mediaTypes.js';
1
+ import {deepAccess} from '../src/utils.js';
2
+ import {registerBidder} from '../src/adapters/bidderFactory.js';
3
+ import {BANNER, VIDEO} from '../src/mediaTypes.js';
5
4
  import {includes} from '../src/polyfill.js';
6
5
 
7
6
  const BIDDER_CODE = 'stv';
@@ -128,7 +127,7 @@ export const spec = {
128
127
  dealId: dealId,
129
128
  currency: currency,
130
129
  netRevenue: netRevenue,
131
- ttl: config.getConfig('_bidderTimeout'),
130
+ ttl: 60,
132
131
  meta: {
133
132
  advertiserDomains: response.adomain || []
134
133
  }
@@ -9,7 +9,7 @@ const BIDDER_CODE = 'triplelift';
9
9
  const STR_ENDPOINT = 'https://tlx.3lift.com/header/auction?';
10
10
  const BANNER_TIME_TO_LIVE = 300;
11
11
  const VIDEO_TIME_TO_LIVE = 3600;
12
- let gdprApplies = true;
12
+ let gdprApplies = null;
13
13
  let consentString = null;
14
14
  export const storage = getStorageManager({bidderCode: BIDDER_CODE});
15
15
 
@@ -40,8 +40,12 @@ export const tripleliftAdapterSpec = {
40
40
  if (bidderRequest && bidderRequest.gdprConsent) {
41
41
  if (typeof bidderRequest.gdprConsent.gdprApplies !== 'undefined') {
42
42
  gdprApplies = bidderRequest.gdprConsent.gdprApplies;
43
- tlCall = tryAppendQueryString(tlCall, 'gdpr', gdprApplies.toString());
43
+ } else {
44
+ gdprApplies = true;
44
45
  }
46
+
47
+ tlCall = tryAppendQueryString(tlCall, 'gdpr', gdprApplies.toString());
48
+
45
49
  if (typeof bidderRequest.gdprConsent.consentString !== 'undefined') {
46
50
  consentString = bidderRequest.gdprConsent.consentString;
47
51
  tlCall = tryAppendQueryString(tlCall, 'cmp_cs', consentString);
@@ -87,7 +91,7 @@ export const tripleliftAdapterSpec = {
87
91
  syncEndpoint = tryAppendQueryString(syncEndpoint, 'src', 'prebid');
88
92
  }
89
93
 
90
- if (consentString !== null) {
94
+ if (consentString !== null || gdprApplies) {
91
95
  syncEndpoint = tryAppendQueryString(syncEndpoint, 'gdpr', gdprApplies);
92
96
  syncEndpoint = tryAppendQueryString(syncEndpoint, 'cmp_cs', consentString);
93
97
  }
@@ -130,8 +134,15 @@ function _buildPostBody(bidRequests, bidderRequest) {
130
134
  }
131
135
 
132
136
  if (!isEmpty(bidRequest.ortb2Imp)) {
137
+ // legacy method for extracting ortb2Imp.ext
133
138
  imp.fpd = _getAdUnitFpd(bidRequest.ortb2Imp);
139
+
140
+ // preferred method for extracting ortb2Imp.ext
141
+ if (!isEmpty(bidRequest.ortb2Imp.ext)) {
142
+ imp.ext = { ...bidRequest.ortb2Imp.ext };
143
+ }
134
144
  }
145
+
135
146
  return imp;
136
147
  });
137
148