prebid.js 7.46.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 (195) 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/criteoIdSystem.js +1 -1
  35. package/dist/cwireBidAdapter.js +1 -1
  36. package/dist/dependencies.json +4 -0
  37. package/dist/dspxBidAdapter.js +1 -1
  38. package/dist/emtvBidAdapter.js +1 -0
  39. package/dist/eplanningBidAdapter.js +1 -1
  40. package/dist/feedadBidAdapter.js +1 -1
  41. package/dist/finativeBidAdapter.js +1 -1
  42. package/dist/freewheel-sspBidAdapter.js +1 -1
  43. package/dist/glimpseBidAdapter.js +1 -1
  44. package/dist/gmosspBidAdapter.js +1 -1
  45. package/dist/goldbachBidAdapter.js +1 -1
  46. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  47. package/dist/greenbidsRtdProvider.js +1 -0
  48. package/dist/gridBidAdapter.js +1 -1
  49. package/dist/gumgumBidAdapter.js +1 -1
  50. package/dist/h12mediaBidAdapter.js +1 -1
  51. package/dist/id5IdSystem.js +1 -1
  52. package/dist/impactifyBidAdapter.js +1 -1
  53. package/dist/improvedigitalBidAdapter.js +1 -1
  54. package/dist/inmarBidAdapter.js +1 -1
  55. package/dist/insticatorBidAdapter.js +1 -1
  56. package/dist/iqmBidAdapter.js +1 -1
  57. package/dist/ixBidAdapter.js +1 -1
  58. package/dist/justpremiumBidAdapter.js +1 -1
  59. package/dist/kargoBidAdapter.js +1 -1
  60. package/dist/konduitAnalyticsAdapter.js +1 -1
  61. package/dist/kueezBidAdapter.js +1 -1
  62. package/dist/kueezRtbBidAdapter.js +1 -1
  63. package/dist/kulturemediaBidAdapter.js +1 -1
  64. package/dist/lassoBidAdapter.js +1 -1
  65. package/dist/lifestreetBidAdapter.js +1 -1
  66. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  67. package/dist/logicadBidAdapter.js +1 -1
  68. package/dist/loglyliftBidAdapter.js +1 -1
  69. package/dist/magniteAnalyticsAdapter.js +1 -1
  70. package/dist/malltvAnalyticsAdapter.js +1 -1
  71. package/dist/marsmediaBidAdapter.js +1 -1
  72. package/dist/mediafuseBidAdapter.js +1 -1
  73. package/dist/mediasquareBidAdapter.js +1 -1
  74. package/dist/mgidBidAdapter.js +1 -1
  75. package/dist/minutemediaBidAdapter.js +1 -1
  76. package/dist/minutemediaplusBidAdapter.js +1 -1
  77. package/dist/missenaBidAdapter.js +1 -1
  78. package/dist/nextMillenniumBidAdapter.js +1 -1
  79. package/dist/nexx360BidAdapter.js +1 -1
  80. package/dist/not-for-prod/prebid.js +142 -139
  81. package/dist/oguryBidAdapter.js +1 -1
  82. package/dist/onetagBidAdapter.js +1 -1
  83. package/dist/ooloAnalyticsAdapter.js +1 -1
  84. package/dist/optidigitalBidAdapter.js +1 -1
  85. package/dist/orbitsoftBidAdapter.js +1 -1
  86. package/dist/outbrainBidAdapter.js +1 -1
  87. package/dist/parrableIdSystem.js +1 -1
  88. package/dist/pixfutureBidAdapter.js +1 -1
  89. package/dist/prebid-core.js +1 -1
  90. package/dist/publinkIdSystem.js +1 -1
  91. package/dist/pubmaticBidAdapter.js +1 -1
  92. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  93. package/dist/pxyzBidAdapter.js +1 -1
  94. package/dist/quantcastBidAdapter.js +1 -1
  95. package/dist/radsBidAdapter.js +1 -1
  96. package/dist/readpeakBidAdapter.js +1 -1
  97. package/dist/relaidoBidAdapter.js +1 -1
  98. package/dist/relevantdigitalBidAdapter.js +1 -0
  99. package/dist/rhythmoneBidAdapter.js +1 -1
  100. package/dist/riseBidAdapter.js +1 -1
  101. package/dist/rtbhouseBidAdapter.js +1 -1
  102. package/dist/rubiconAnalyticsAdapter.js +1 -1
  103. package/dist/rubiconBidAdapter.js +1 -1
  104. package/dist/seedingAllianceBidAdapter.js +1 -1
  105. package/dist/seedtagBidAdapter.js +1 -1
  106. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  107. package/dist/sharethroughBidAdapter.js +1 -1
  108. package/dist/shinezBidAdapter.js +1 -1
  109. package/dist/smaatoBidAdapter.js +1 -1
  110. package/dist/smartadserverBidAdapter.js +1 -1
  111. package/dist/smartxBidAdapter.js +1 -1
  112. package/dist/smilewantedBidAdapter.js +1 -1
  113. package/dist/sonobiBidAdapter.js +1 -1
  114. package/dist/sovrnAnalyticsAdapter.js +1 -1
  115. package/dist/sovrnBidAdapter.js +1 -1
  116. package/dist/sspBCBidAdapter.js +1 -1
  117. package/dist/stvBidAdapter.js +1 -1
  118. package/dist/sublimeBidAdapter.js +1 -1
  119. package/dist/synacormediaBidAdapter.js +1 -1
  120. package/dist/targetVideoBidAdapter.js +1 -1
  121. package/dist/teadsBidAdapter.js +1 -1
  122. package/dist/trionBidAdapter.js +1 -1
  123. package/dist/tripleliftBidAdapter.js +1 -1
  124. package/dist/ttdBidAdapter.js +1 -1
  125. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  126. package/dist/uid2IdSystem.js +1 -1
  127. package/dist/underdogmediaBidAdapter.js +1 -1
  128. package/dist/undertoneBidAdapter.js +1 -1
  129. package/dist/userId.js +1 -1
  130. package/dist/vdoaiBidAdapter.js +1 -1
  131. package/dist/vidazooBidAdapter.js +1 -1
  132. package/dist/videobyteBidAdapter.js +1 -1
  133. package/dist/vidoomyBidAdapter.js +1 -1
  134. package/dist/visxBidAdapter.js +1 -1
  135. package/dist/vuukleBidAdapter.js +1 -1
  136. package/dist/widespaceBidAdapter.js +1 -1
  137. package/dist/winrBidAdapter.js +1 -1
  138. package/dist/wipesBidAdapter.js +1 -1
  139. package/dist/yahoosspBidAdapter.js +1 -1
  140. package/dist/yieldmoBidAdapter.js +1 -1
  141. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  142. package/dist/yieldoneBidAdapter.js +1 -1
  143. package/modules/ablidaBidAdapter.js +4 -5
  144. package/modules/admaticBidAdapter.js +32 -5
  145. package/modules/adrinoBidAdapter.js +11 -4
  146. package/modules/axonixBidAdapter.js +6 -6
  147. package/modules/connectIdSystem.js +5 -2
  148. package/modules/criteoBidAdapter.js +3 -5
  149. package/modules/criteoIdSystem.js +27 -14
  150. package/modules/dspxBidAdapter.js +2 -3
  151. package/modules/emtvBidAdapter.js +211 -0
  152. package/modules/emtvBidAdapter.md +79 -0
  153. package/modules/freewheel-sspBidAdapter.js +32 -7
  154. package/modules/greenbidsRtdProvider.js +110 -0
  155. package/modules/greenbidsRtdProvider.md +65 -0
  156. package/modules/impactifyBidAdapter.js +0 -1
  157. package/modules/iqmBidAdapter.js +1 -2
  158. package/modules/missenaBidAdapter.js +1 -1
  159. package/modules/nextMillenniumBidAdapter.js +2 -0
  160. package/modules/orbitsoftBidAdapter.js +1 -2
  161. package/modules/radsBidAdapter.js +3 -4
  162. package/modules/relevantdigitalBidAdapter.js +198 -0
  163. package/modules/relevantdigitalBidAdapter.md +117 -0
  164. package/modules/rtbhouseBidAdapter.js +9 -12
  165. package/modules/sovrnBidAdapter.js +4 -0
  166. package/modules/stvBidAdapter.js +4 -5
  167. package/modules/tripleliftBidAdapter.js +14 -3
  168. package/modules/ttdBidAdapter.js +73 -71
  169. package/modules/underdogmediaBidAdapter.js +9 -12
  170. package/modules/userId/index.js +1 -1
  171. package/modules/vdoaiBidAdapter.js +2 -3
  172. package/modules/vidoomyBidAdapter.js +19 -6
  173. package/modules/vidoomyBidAdapter.md +12 -2
  174. package/modules/wipesBidAdapter.js +2 -3
  175. package/modules/yieldmoBidAdapter.js +2 -2
  176. package/modules/yieldoneBidAdapter.js +3 -4
  177. package/package.json +1 -1
  178. package/test/spec/modules/adlooxAdServerVideo_spec.js +18 -35
  179. package/test/spec/modules/admaticBidAdapter_spec.js +164 -11
  180. package/test/spec/modules/adrinoBidAdapter_spec.js +50 -2
  181. package/test/spec/modules/connectIdSystem_spec.js +4 -4
  182. package/test/spec/modules/criteoBidAdapter_spec.js +56 -0
  183. package/test/spec/modules/criteoIdSystem_spec.js +99 -9
  184. package/test/spec/modules/emtvBidAdapter_spec.js +400 -0
  185. package/test/spec/modules/freewheel-sspBidAdapter_spec.js +31 -2
  186. package/test/spec/modules/greenbidsRtdProvider_spec.js +210 -0
  187. package/test/spec/modules/relevantdigitalBidAdapter_spec.js +295 -0
  188. package/test/spec/modules/rtbhouseBidAdapter_spec.js +24 -2
  189. package/test/spec/modules/sovrnBidAdapter_spec.js +65 -0
  190. package/test/spec/modules/tripleliftBidAdapter_spec.js +53 -8
  191. package/test/spec/modules/ttdBidAdapter_spec.js +20 -0
  192. package/test/spec/modules/vidoomyBidAdapter_spec.js +49 -0
  193. package/test/spec/modules/yieldmoBidAdapter_spec.js +2 -2
  194. package/test/spec/ortbConverter/userId_spec.js +12 -0
  195. package/test/spec/modules/realvuAnalyticsAdapter_spec.js +0 -189
@@ -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
 
@@ -479,7 +476,7 @@ function interpretNativeBid(serverBid) {
479
476
  function interpretNativeAd(adm) {
480
477
  const native = JSON.parse(adm).native;
481
478
  const result = {
482
- clickUrl: encodeURIComponent(native.link.url),
479
+ clickUrl: encodeURI(native.link.url),
483
480
  impressionTrackers: native.imptrackers
484
481
  };
485
482
  native.assets.forEach(asset => {
@@ -489,14 +486,14 @@ function interpretNativeAd(adm) {
489
486
  break;
490
487
  case OPENRTB.NATIVE.ASSET_ID.IMAGE:
491
488
  result.image = {
492
- url: encodeURIComponent(asset.img.url),
489
+ url: encodeURI(asset.img.url),
493
490
  width: asset.img.w,
494
491
  height: asset.img.h
495
492
  };
496
493
  break;
497
494
  case OPENRTB.NATIVE.ASSET_ID.ICON:
498
495
  result.icon = {
499
- url: encodeURIComponent(asset.img.url),
496
+ url: encodeURI(asset.img.url),
500
497
  width: asset.img.w,
501
498
  height: asset.img.h
502
499
  };
@@ -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
 
@@ -185,7 +185,7 @@ function getImpression(bidRequest) {
185
185
  if (mediaTypesBanner) {
186
186
  mediaTypes[BANNER] = banner(bidRequest);
187
187
  }
188
- if (mediaTypesVideo) {
188
+ if (FEATURES.VIDEO && mediaTypesVideo) {
189
189
  mediaTypes[VIDEO] = video(bidRequest);
190
190
  }
191
191
 
@@ -248,79 +248,81 @@ function banner(bid) {
248
248
  }
249
249
 
250
250
  function video(bid) {
251
- let minduration = utils.deepAccess(bid, 'mediaTypes.video.minduration');
252
- const maxduration = utils.deepAccess(bid, 'mediaTypes.video.maxduration');
253
- const playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize');
254
- const api = utils.deepAccess(bid, 'mediaTypes.video.api');
255
- const mimes = utils.deepAccess(bid, 'mediaTypes.video.mimes');
256
- const placement = utils.deepAccess(bid, 'mediaTypes.video.placement');
257
- const plcmt = utils.deepAccess(bid, 'mediaTypes.video.plcmt');
258
- const protocols = utils.deepAccess(bid, 'mediaTypes.video.protocols');
259
- const playbackmethod = utils.deepAccess(bid, 'mediaTypes.video.playbackmethod');
260
- const pos = utils.deepAccess(bid, 'mediaTypes.video.pos');
261
- const startdelay = utils.deepAccess(bid, 'mediaTypes.video.startdelay');
262
- const skip = utils.deepAccess(bid, 'mediaTypes.video.skip');
263
- const skipmin = utils.deepAccess(bid, 'mediaTypes.video.skipmin');
264
- const skipafter = utils.deepAccess(bid, 'mediaTypes.video.skipafter');
265
- const minbitrate = utils.deepAccess(bid, 'mediaTypes.video.minbitrate');
266
- const maxbitrate = utils.deepAccess(bid, 'mediaTypes.video.maxbitrate');
267
-
268
- if (!minduration || !utils.isInteger(minduration)) {
269
- minduration = 0;
270
- }
271
- let video = {
272
- minduration: minduration,
273
- maxduration: maxduration,
274
- api: api,
275
- mimes: mimes,
276
- placement: placement,
277
- protocols: protocols
278
- };
251
+ if (FEATURES.VIDEO) {
252
+ let minduration = utils.deepAccess(bid, 'mediaTypes.video.minduration');
253
+ const maxduration = utils.deepAccess(bid, 'mediaTypes.video.maxduration');
254
+ const playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize');
255
+ const api = utils.deepAccess(bid, 'mediaTypes.video.api');
256
+ const mimes = utils.deepAccess(bid, 'mediaTypes.video.mimes');
257
+ const placement = utils.deepAccess(bid, 'mediaTypes.video.placement');
258
+ const plcmt = utils.deepAccess(bid, 'mediaTypes.video.plcmt');
259
+ const protocols = utils.deepAccess(bid, 'mediaTypes.video.protocols');
260
+ const playbackmethod = utils.deepAccess(bid, 'mediaTypes.video.playbackmethod');
261
+ const pos = utils.deepAccess(bid, 'mediaTypes.video.pos');
262
+ const startdelay = utils.deepAccess(bid, 'mediaTypes.video.startdelay');
263
+ const skip = utils.deepAccess(bid, 'mediaTypes.video.skip');
264
+ const skipmin = utils.deepAccess(bid, 'mediaTypes.video.skipmin');
265
+ const skipafter = utils.deepAccess(bid, 'mediaTypes.video.skipafter');
266
+ const minbitrate = utils.deepAccess(bid, 'mediaTypes.video.minbitrate');
267
+ const maxbitrate = utils.deepAccess(bid, 'mediaTypes.video.maxbitrate');
268
+
269
+ if (!minduration || !utils.isInteger(minduration)) {
270
+ minduration = 0;
271
+ }
272
+ let video = {
273
+ minduration: minduration,
274
+ maxduration: maxduration,
275
+ api: api,
276
+ mimes: mimes,
277
+ placement: placement,
278
+ protocols: protocols
279
+ };
279
280
 
280
- if (typeof playerSize !== 'undefined') {
281
- if (utils.isArray(playerSize[0])) {
282
- video.w = parseInt(playerSize[0][0]);
283
- video.h = parseInt(playerSize[0][1]);
284
- } else if (utils.isNumber(playerSize[0])) {
285
- video.w = parseInt(playerSize[0]);
286
- video.h = parseInt(playerSize[1]);
281
+ if (typeof playerSize !== 'undefined') {
282
+ if (utils.isArray(playerSize[0])) {
283
+ video.w = parseInt(playerSize[0][0]);
284
+ video.h = parseInt(playerSize[0][1]);
285
+ } else if (utils.isNumber(playerSize[0])) {
286
+ video.w = parseInt(playerSize[0]);
287
+ video.h = parseInt(playerSize[1]);
288
+ }
287
289
  }
288
- }
289
290
 
290
- if (playbackmethod) {
291
- video.playbackmethod = playbackmethod;
292
- }
293
- if (plcmt) {
294
- video.plcmt = plcmt;
295
- }
296
- if (pos) {
297
- video.pos = pos;
298
- }
299
- if (startdelay && utils.isInteger(startdelay)) {
300
- video.startdelay = startdelay;
301
- }
302
- if (skip && (skip === 0 || skip === 1)) {
303
- video.skip = skip;
304
- }
305
- if (skipmin && utils.isInteger(skipmin)) {
306
- video.skipmin = skipmin;
307
- }
308
- if (skipafter && utils.isInteger(skipafter)) {
309
- video.skipafter = skipafter;
310
- }
311
- if (minbitrate && utils.isInteger(minbitrate)) {
312
- video.minbitrate = minbitrate;
313
- }
314
- if (maxbitrate && utils.isInteger(maxbitrate)) {
315
- video.maxbitrate = maxbitrate;
316
- }
291
+ if (playbackmethod) {
292
+ video.playbackmethod = playbackmethod;
293
+ }
294
+ if (plcmt) {
295
+ video.plcmt = plcmt;
296
+ }
297
+ if (pos) {
298
+ video.pos = pos;
299
+ }
300
+ if (startdelay && utils.isInteger(startdelay)) {
301
+ video.startdelay = startdelay;
302
+ }
303
+ if (skip && (skip === 0 || skip === 1)) {
304
+ video.skip = skip;
305
+ }
306
+ if (skipmin && utils.isInteger(skipmin)) {
307
+ video.skipmin = skipmin;
308
+ }
309
+ if (skipafter && utils.isInteger(skipafter)) {
310
+ video.skipafter = skipafter;
311
+ }
312
+ if (minbitrate && utils.isInteger(minbitrate)) {
313
+ video.minbitrate = minbitrate;
314
+ }
315
+ if (maxbitrate && utils.isInteger(maxbitrate)) {
316
+ video.maxbitrate = maxbitrate;
317
+ }
317
318
 
318
- const battr = utils.deepAccess(bid, 'ortb2Imp.battr');
319
- if (battr) {
320
- video.battr = battr;
321
- }
319
+ const battr = utils.deepAccess(bid, 'ortb2Imp.battr');
320
+ if (battr) {
321
+ video.battr = battr;
322
+ }
322
323
 
323
- return video;
324
+ return video;
325
+ }
324
326
  }
325
327
 
326
328
  export const spec = {
@@ -379,7 +381,7 @@ export const spec = {
379
381
  return false;
380
382
  }
381
383
 
382
- if (mediaTypesVideo) {
384
+ if (FEATURES.VIDEO && mediaTypesVideo) {
383
385
  if (!mediaTypesVideo.maxduration || !utils.isInteger(mediaTypesVideo.maxduration)) {
384
386
  utils.logWarn(BIDDER_CODE + ': mediaTypes.video.maxduration must be set to the maximum video ad duration in seconds');
385
387
  return false;
@@ -506,7 +508,7 @@ export const spec = {
506
508
  mediaType: BANNER
507
509
  }
508
510
  );
509
- } else if (bid.ext.mediatype === MEDIA_TYPE.VIDEO) {
511
+ } else if (FEATURES.VIDEO && bid.ext.mediatype === MEDIA_TYPE.VIDEO) {
510
512
  Object.assign(
511
513
  bidResponse,
512
514
  {
@@ -1,21 +1,18 @@
1
1
  import {
2
- logMessage,
2
+ deepAccess,
3
3
  flatten,
4
- parseSizesInput,
4
+ getWindowSelf,
5
+ getWindowTop,
5
6
  isGptPubadsDefined,
6
7
  isSlotMatchingAdUnitCode,
7
8
  logInfo,
9
+ logMessage,
8
10
  logWarn,
9
- getWindowSelf,
10
- getWindowTop,
11
- deepAccess
11
+ parseSizesInput
12
12
  } from '../src/utils.js';
13
- import {
14
- config
15
- } from '../src/config.js';
16
- import {
17
- registerBidder
18
- } from '../src/adapters/bidderFactory.js';
13
+ import {config} from '../src/config.js';
14
+ import {registerBidder} from '../src/adapters/bidderFactory.js';
15
+
19
16
  const BIDDER_CODE = 'underdogmedia';
20
17
  const UDM_ADAPTER_VERSION = '7.30V';
21
18
  const UDM_VENDOR_ID = '159';
@@ -377,7 +374,7 @@ function makeNotification(bid, mid, bidParam) {
377
374
  url += `;version=${UDM_ADAPTER_VERSION}`;
378
375
  url += ';cb=' + Math.random();
379
376
  url += ';qqq=' + (1 / bid.cpm);
380
- url += ';hbt=' + config.getConfig('_bidderTimeout');
377
+ url += ';hbt=' + config.getConfig('bidderTimeout');
381
378
  url += ';style=adapter';
382
379
  url += ';vis=' + encodeURIComponent(document.visibilityState);
383
380
 
@@ -1085,7 +1085,7 @@ module('userId', attachIdSystem);
1085
1085
 
1086
1086
  export function setOrtbUserExtEids(ortbRequest, bidderRequest, context) {
1087
1087
  const eids = deepAccess(context, 'bidRequests.0.userIdAsEids');
1088
- if (eids) {
1088
+ if (eids && Object.keys(eids).length > 0) {
1089
1089
  deepSetValue(ortbRequest, 'user.ext.eids', eids);
1090
1090
  }
1091
1091
  }