prebid.js 8.45.0 → 8.46.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 (203) hide show
  1. package/dist/33acrossAnalyticsAdapter.js +1 -1
  2. package/dist/33acrossBidAdapter.js +1 -1
  3. package/dist/33acrossIdSystem.js +1 -1
  4. package/dist/BTBidAdapter.js +1 -1
  5. package/dist/adagioAnalyticsAdapter.js +1 -1
  6. package/dist/adagioBidAdapter.js +1 -1
  7. package/dist/adbookpspBidAdapter.js +1 -1
  8. package/dist/adgenerationBidAdapter.js +1 -1
  9. package/dist/adnuntiusBidAdapter.js +1 -1
  10. package/dist/adqueryBidAdapter.js +1 -1
  11. package/dist/adrelevantisBidAdapter.js +1 -1
  12. package/dist/adstirBidAdapter.js +1 -1
  13. package/dist/adtrgtmeBidAdapter.js +1 -1
  14. package/dist/adxcgBidAdapter.js +1 -1
  15. package/dist/adyoulikeBidAdapter.js +1 -1
  16. package/dist/agmaAnalyticsAdapter.js +1 -1
  17. package/dist/ajaBidAdapter.js +1 -1
  18. package/dist/alkimiBidAdapter.js +1 -1
  19. package/dist/amxBidAdapter.js +1 -1
  20. package/dist/amxIdSystem.js +1 -1
  21. package/dist/appierAnalyticsAdapter.js +1 -1
  22. package/dist/appnexusBidAdapter.js +1 -1
  23. package/dist/asoBidAdapter.js +1 -1
  24. package/dist/axonixBidAdapter.js +1 -1
  25. package/dist/bidglassBidAdapter.js +1 -1
  26. package/dist/big-richmediaBidAdapter.js +1 -1
  27. package/dist/bridBidAdapter.js +1 -1
  28. package/dist/bridgewellBidAdapter.js +1 -1
  29. package/dist/brightMountainMediaBidAdapter.js +1 -1
  30. package/dist/carodaBidAdapter.js +1 -1
  31. package/dist/chtnwBidAdapter.js +1 -1
  32. package/dist/chunk-core.js +1 -1
  33. package/dist/concertBidAdapter.js +1 -1
  34. package/dist/connectadBidAdapter.js +1 -1
  35. package/dist/consumableBidAdapter.js +1 -1
  36. package/dist/conversantAnalyticsAdapter.js +1 -1
  37. package/dist/conversantBidAdapter.js +1 -1
  38. package/dist/craftBidAdapter.js +1 -1
  39. package/dist/criteoBidAdapter.js +1 -1
  40. package/dist/cwireBidAdapter.js +1 -1
  41. package/dist/dependencies.json +12 -3
  42. package/dist/dspxBidAdapter.js +1 -1
  43. package/dist/dxkultureBidAdapter.js +1 -1
  44. package/dist/engageyaBidAdapter.js +1 -1
  45. package/dist/eplanningBidAdapter.js +1 -1
  46. package/dist/euidIdSystem.js +1 -1
  47. package/dist/feedadBidAdapter.js +1 -1
  48. package/dist/finativeBidAdapter.js +1 -1
  49. package/dist/freewheel-sspBidAdapter.js +1 -1
  50. package/dist/gmosspBidAdapter.js +1 -1
  51. package/dist/goldbachBidAdapter.js +1 -1
  52. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  53. package/dist/greenbidsRtdProvider.js +1 -1
  54. package/dist/gridBidAdapter.js +1 -1
  55. package/dist/gumgumBidAdapter.js +1 -1
  56. package/dist/h12mediaBidAdapter.js +1 -1
  57. package/dist/hypelabBidAdapter.js +1 -1
  58. package/dist/id5IdSystem.js +1 -1
  59. package/dist/illuminBidAdapter.js +1 -1
  60. package/dist/imdsBidAdapter.js +1 -1
  61. package/dist/improvedigitalBidAdapter.js +1 -1
  62. package/dist/insticatorBidAdapter.js +1 -1
  63. package/dist/ixBidAdapter.js +1 -1
  64. package/dist/jixieBidAdapter.js +1 -1
  65. package/dist/justpremiumBidAdapter.js +1 -1
  66. package/dist/jwplayerBidAdapter.js +1 -0
  67. package/dist/kargoBidAdapter.js +1 -1
  68. package/dist/kimberliteBidAdapter.js +1 -1
  69. package/dist/konduitAnalyticsAdapter.js +1 -1
  70. package/dist/kueezBidAdapter.js +1 -1
  71. package/dist/kueezRtbBidAdapter.js +1 -1
  72. package/dist/lassoBidAdapter.js +1 -1
  73. package/dist/lifestreetBidAdapter.js +1 -1
  74. package/dist/liveIntentIdSystem.js +1 -1
  75. package/dist/logicadBidAdapter.js +1 -1
  76. package/dist/loglyliftBidAdapter.js +1 -1
  77. package/dist/luceadBidAdapter.js +1 -1
  78. package/dist/magniteAnalyticsAdapter.js +1 -1
  79. package/dist/malltvAnalyticsAdapter.js +1 -1
  80. package/dist/marsmediaBidAdapter.js +1 -1
  81. package/dist/mediafuseBidAdapter.js +1 -1
  82. package/dist/mediasquareBidAdapter.js +1 -1
  83. package/dist/mgidBidAdapter.js +1 -1
  84. package/dist/minutemediaBidAdapter.js +1 -1
  85. package/dist/minutemediaplusBidAdapter.js +1 -1
  86. package/dist/missenaBidAdapter.js +1 -1
  87. package/dist/nexx360BidAdapter.js +1 -1
  88. package/dist/not-for-prod/prebid.js +154 -152
  89. package/dist/oguryBidAdapter.js +1 -1
  90. package/dist/onetagBidAdapter.js +1 -1
  91. package/dist/ooloAnalyticsAdapter.js +1 -1
  92. package/dist/openwebBidAdapter.js +1 -1
  93. package/dist/openxBidAdapter.js +1 -1
  94. package/dist/optableBidAdapter.js +1 -0
  95. package/dist/optidigitalBidAdapter.js +1 -1
  96. package/dist/ortbConverter.js +1 -1
  97. package/dist/outbrainBidAdapter.js +1 -1
  98. package/dist/parrableIdSystem.js +1 -1
  99. package/dist/pixfutureBidAdapter.js +1 -1
  100. package/dist/publinkIdSystem.js +1 -1
  101. package/dist/publirBidAdapter.js +1 -1
  102. package/dist/pubmaticBidAdapter.js +1 -1
  103. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  104. package/dist/pxyzBidAdapter.js +1 -1
  105. package/dist/quantcastBidAdapter.js +1 -1
  106. package/dist/readpeakBidAdapter.js +1 -1
  107. package/dist/relaidoBidAdapter.js +1 -1
  108. package/dist/retailspotBidAdapter.js +1 -1
  109. package/dist/rhythmoneBidAdapter.js +1 -1
  110. package/dist/riseBidAdapter.js +1 -1
  111. package/dist/rubiconBidAdapter.js +1 -1
  112. package/dist/seedingAllianceBidAdapter.js +1 -1
  113. package/dist/seedtagBidAdapter.js +1 -1
  114. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  115. package/dist/sharethroughBidAdapter.js +1 -1
  116. package/dist/shinezBidAdapter.js +1 -1
  117. package/dist/shinezRtbBidAdapter.js +1 -1
  118. package/dist/sirdataRtdProvider.js +1 -1
  119. package/dist/smaatoBidAdapter.js +1 -1
  120. package/dist/smartadserverBidAdapter.js +1 -1
  121. package/dist/smartxBidAdapter.js +1 -1
  122. package/dist/smilewantedBidAdapter.js +1 -1
  123. package/dist/sonobiBidAdapter.js +1 -1
  124. package/dist/sovrnAnalyticsAdapter.js +1 -1
  125. package/dist/sovrnBidAdapter.js +1 -1
  126. package/dist/sspBCBidAdapter.js +1 -1
  127. package/dist/stnBidAdapter.js +1 -1
  128. package/dist/stroeerCoreBidAdapter.js +1 -1
  129. package/dist/stvBidAdapter.js +1 -1
  130. package/dist/sublimeBidAdapter.js +1 -1
  131. package/dist/taboolaBidAdapter.js +1 -1
  132. package/dist/tagorasBidAdapter.js +1 -1
  133. package/dist/targetVideoBidAdapter.js +1 -1
  134. package/dist/teadsBidAdapter.js +1 -1
  135. package/dist/themoneytizerBidAdapter.js +1 -1
  136. package/dist/trionBidAdapter.js +1 -1
  137. package/dist/tripleliftBidAdapter.js +1 -1
  138. package/dist/ttdBidAdapter.js +1 -1
  139. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  140. package/dist/uid2IdSystem.js +1 -1
  141. package/dist/underdogmediaBidAdapter.js +1 -1
  142. package/dist/undertoneBidAdapter.js +1 -1
  143. package/dist/unrulyBidAdapter.js +1 -1
  144. package/dist/viantOrtbBidAdapter.js +1 -1
  145. package/dist/vidazooBidAdapter.js +1 -1
  146. package/dist/videobyteBidAdapter.js +1 -1
  147. package/dist/visxBidAdapter.js +1 -1
  148. package/dist/vuukleBidAdapter.js +1 -1
  149. package/dist/widespaceBidAdapter.js +1 -1
  150. package/dist/winrBidAdapter.js +1 -1
  151. package/dist/yahoosspBidAdapter.js +1 -1
  152. package/dist/yandexAnalyticsAdapter.js +1 -1
  153. package/dist/yieldmoBidAdapter.js +1 -1
  154. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  155. package/integrationExamples/noadserver/jwplayerBidAdapter_sample.html +75 -0
  156. package/integrationExamples/realTimeData/jwplayerRtdProvider_example.html +7 -0
  157. package/integrationExamples/videoModule/jwplayer/bidMarkedAsUsed.html +7 -0
  158. package/integrationExamples/videoModule/jwplayer/bidRequestScheduling.html +9 -4
  159. package/integrationExamples/videoModule/jwplayer/bidsBackHandlerOverride.html +7 -0
  160. package/integrationExamples/videoModule/jwplayer/eventListeners.html +7 -0
  161. package/integrationExamples/videoModule/jwplayer/eventsUI.html +7 -0
  162. package/integrationExamples/videoModule/jwplayer/gamAdServerMediation.html +7 -0
  163. package/integrationExamples/videoModule/jwplayer/mediaMetadata.html +7 -0
  164. package/integrationExamples/videoModule/jwplayer/playlist.html +7 -0
  165. package/integrationExamples/videoModule/videojs/bidMarkedAsUsed.html +7 -0
  166. package/integrationExamples/videoModule/videojs/bidRequestScheduling.html +7 -0
  167. package/integrationExamples/videoModule/videojs/bidsBackHandlerOverride.html +7 -0
  168. package/integrationExamples/videoModule/videojs/eventListeners.html +7 -0
  169. package/integrationExamples/videoModule/videojs/eventsUI.html +7 -0
  170. package/integrationExamples/videoModule/videojs/gamAdServerMediation.html +7 -0
  171. package/integrationExamples/videoModule/videojs/mediaMetadata.html +7 -0
  172. package/integrationExamples/videoModule/videojs/playlist.html +7 -0
  173. package/libraries/ortbConverter/processors/banner.js +2 -2
  174. package/modules/adgenerationBidAdapter.js +6 -10
  175. package/modules/adnuntiusBidAdapter.js +5 -0
  176. package/modules/alkimiBidAdapter.js +48 -8
  177. package/modules/engageyaBidAdapter.js +1 -1
  178. package/modules/gumgumBidAdapter.js +1 -1
  179. package/modules/jwplayerBidAdapter.js +412 -0
  180. package/modules/jwplayerBidAdapter.md +72 -0
  181. package/modules/optableBidAdapter.js +42 -0
  182. package/modules/optableBidAdapter.md +41 -0
  183. package/modules/optidigitalBidAdapter.js +20 -4
  184. package/modules/pubmaticBidAdapter.js +21 -1
  185. package/modules/relaidoBidAdapter.js +70 -9
  186. package/modules/sirdataRtdProvider.js +33 -43
  187. package/modules/stroeerCoreBidAdapter.js +7 -5
  188. package/modules/viantOrtbBidAdapter.js +2 -0
  189. package/modules/yandexAnalyticsAdapter.js +6 -0
  190. package/package.json +1 -1
  191. package/src/utils.js +15 -2
  192. package/test/spec/modules/adgenerationBidAdapter_spec.js +6 -6
  193. package/test/spec/modules/adnuntiusBidAdapter_spec.js +18 -1
  194. package/test/spec/modules/alkimiBidAdapter_spec.js +11 -5
  195. package/test/spec/modules/gumgumBidAdapter_spec.js +1 -1
  196. package/test/spec/modules/jwplayerBidAdapter_spec.js +412 -0
  197. package/test/spec/modules/liveIntentIdSystem_spec.js +13 -15
  198. package/test/spec/modules/optableBidAdapter_spec.js +89 -0
  199. package/test/spec/modules/optidigitalBidAdapter_spec.js +34 -4
  200. package/test/spec/modules/pubmaticBidAdapter_spec.js +24 -1
  201. package/test/spec/modules/relaidoBidAdapter_spec.js +62 -0
  202. package/test/spec/modules/stroeerCoreBidAdapter_spec.js +21 -0
  203. package/test/spec/utils_spec.js +17 -1
@@ -1,12 +1,15 @@
1
1
  import {registerBidder} from '../src/adapters/bidderFactory.js';
2
2
  import {deepAccess, deepClone, getDNT, generateUUID, replaceAuctionPrice} from '../src/utils.js';
3
3
  import {ajax} from '../src/ajax.js';
4
+ import {getStorageManager} from '../src/storageManager.js';
4
5
  import {VIDEO, BANNER} from '../src/mediaTypes.js';
5
6
  import {config} from '../src/config.js';
6
7
 
7
8
  const BIDDER_CODE = 'alkimi';
8
9
  const GVLID = 1169;
10
+ const USER_ID_KEY = 'alkimiUserID';
9
11
  export const ENDPOINT = 'https://exchange.alkimi-onboarding.com/bid?prebid=true';
12
+ export const storage = getStorageManager({bidderCode: BIDDER_CODE});
10
13
 
11
14
  export const spec = {
12
15
  code: BIDDER_CODE,
@@ -43,11 +46,16 @@ export const spec = {
43
46
  bidIds.push(bidRequest.bidId)
44
47
  })
45
48
 
49
+ const ortb2 = bidderRequest.ortb2
50
+ const site = ortb2?.site
51
+
52
+ const id = getUserId()
46
53
  const alkimiConfig = config.getConfig('alkimi')
47
- const fullPageAuction = bidderRequest.ortb2?.source?.ext?.full_page_auction
48
- const source = fullPageAuction != undefined ? { ext: { full_page_auction: fullPageAuction } } : undefined
54
+ const fpa = ortb2?.source?.ext?.fpa
55
+ const source = fpa != undefined ? { ext: { fpa } } : undefined
49
56
  const walletID = alkimiConfig && alkimiConfig.walletID
50
- const user = walletID != undefined ? { ext: { walletID: walletID } } : undefined
57
+ const userParams = alkimiConfig && alkimiConfig.userParams
58
+ const user = (walletID != undefined || userParams != undefined || id != undefined) ? { id, ext: { walletID, userParams } } : undefined
51
59
 
52
60
  let payload = {
53
61
  requestId: generateUUID(),
@@ -66,11 +74,14 @@ export const spec = {
66
74
  source,
67
75
  user,
68
76
  site: {
69
- keywords: bidderRequest.ortb2?.site?.keywords
77
+ keywords: site?.keywords,
78
+ sectioncat: site?.sectioncat,
79
+ pagecat: site?.pagecat,
80
+ cat: site?.cat
70
81
  },
71
- at: bidderRequest.ortb2?.at,
72
- bcat: bidderRequest.ortb2?.bcat,
73
- wseat: bidderRequest.ortb2?.wseat
82
+ at: ortb2?.at,
83
+ bcat: ortb2?.bcat,
84
+ wseat: ortb2?.wseat
74
85
  }
75
86
  }
76
87
 
@@ -111,7 +122,7 @@ export const spec = {
111
122
  }
112
123
 
113
124
  const {prebidResponse} = serverBody;
114
- if (!prebidResponse || typeof prebidResponse !== 'object') {
125
+ if (!Array.isArray(prebidResponse)) {
115
126
  return [];
116
127
  }
117
128
 
@@ -141,6 +152,24 @@ export const spec = {
141
152
  return true;
142
153
  }
143
154
  return false;
155
+ },
156
+
157
+ getUserSyncs: function(syncOptions, serverResponses, gdprConsent) {
158
+ if (syncOptions.iframeEnabled && serverResponses.length > 0) {
159
+ const serverBody = serverResponses[0].body;
160
+ if (!serverBody || typeof serverBody !== 'object') return [];
161
+
162
+ const { iframeList } = serverBody;
163
+ if (!Array.isArray(iframeList)) return [];
164
+
165
+ const urls = [];
166
+ iframeList.forEach(url => {
167
+ urls.push({type: 'iframe', url});
168
+ })
169
+
170
+ return urls;
171
+ }
172
+ return [];
144
173
  }
145
174
  }
146
175
 
@@ -175,4 +204,15 @@ const getFormatType = bidRequest => {
175
204
  return formats
176
205
  }
177
206
 
207
+ const getUserId = () => {
208
+ if (storage.localStorageIsEnabled()) {
209
+ let userId = storage.getDataFromLocalStorage(USER_ID_KEY)
210
+ if (!userId) {
211
+ userId = generateUUID()
212
+ storage.setDataInLocalStorage(USER_ID_KEY, userId)
213
+ }
214
+ return userId
215
+ }
216
+ }
217
+
178
218
  registerBidder(spec);
@@ -81,7 +81,7 @@ function parseBannerResponse(rec, response) {
81
81
  const title = rec.title && rec.title.trim() ? `<div class="eng_tag_ttl" style="display: none">${rec.title}</div>` : '';
82
82
  const displayName = rec.displayName && title ? `<div class="eng_tag_brnd" style="display: none">${rec.displayName}</div>` : '';
83
83
  const trackers = getImpressionTrackers(rec, response)
84
- .map(createTrackPixelHtml)
84
+ .map((url) => createTrackPixelHtml(url))
85
85
  .join('');
86
86
  return `<html><body>${style}<div id="ENG_TAG"><a href="${rec.clickUrl}" target=_blank><img class="eng_tag_img" src="${getImageSrc(rec)}" style="width:${response.imageWidth}px;height:${response.imageHeight}px;" alt="${rec.title}"/>${displayName}${title}</a>${trackers}</div></body></html>`;
87
87
  }
@@ -424,7 +424,7 @@ function buildRequests(validBidRequests, bidderRequest) {
424
424
  }
425
425
  const dsa = deepAccess(bidderRequest, 'ortb2.regs.ext.dsa');
426
426
  if (dsa) {
427
- data.dsa = dsa
427
+ data.dsa = JSON.stringify(dsa)
428
428
  }
429
429
  if (coppa) {
430
430
  data.coppa = coppa;
@@ -0,0 +1,412 @@
1
+ import { registerBidder } from '../src/adapters/bidderFactory.js';
2
+ import { VIDEO } from '../src/mediaTypes.js';
3
+ import { isArray, isFn, deepAccess, deepSetValue, getDNT, logError, logWarn } from '../src/utils.js';
4
+ import { config } from '../src/config.js';
5
+ import { hasPurpose1Consent } from '../src/utils/gpdr.js';
6
+
7
+ const BIDDER_CODE = 'jwplayer';
8
+ const BASE_URL = 'https://vpb-server.jwplayer.com/';
9
+ const AUCTION_URL = BASE_URL + 'openrtb2/auction';
10
+ const USER_SYNC_URL = BASE_URL + 'setuid';
11
+ const GVLID = 1046;
12
+ const SUPPORTED_AD_TYPES = [VIDEO];
13
+
14
+ const VIDEO_ORTB_PARAMS = [
15
+ 'pos',
16
+ 'w',
17
+ 'h',
18
+ 'playbackend',
19
+ 'mimes',
20
+ 'minduration',
21
+ 'maxduration',
22
+ 'protocols',
23
+ 'startdelay',
24
+ 'placement',
25
+ 'plcmt',
26
+ 'skip',
27
+ 'skipafter',
28
+ 'minbitrate',
29
+ 'maxbitrate',
30
+ 'delivery',
31
+ 'playbackmethod',
32
+ 'api',
33
+ 'linearity'
34
+ ];
35
+
36
+ function getBidAdapter() {
37
+ function isBidRequestValid(bid) {
38
+ const params = bid && bid.params;
39
+ if (!params) {
40
+ return false;
41
+ }
42
+
43
+ return !!params.placementId && !!params.publisherId && !!params.siteId;
44
+ }
45
+
46
+ function buildRequests(bidRequests, bidderRequest) {
47
+ if (!bidRequests) {
48
+ return;
49
+ }
50
+
51
+ if (!hasContentUrl(bidderRequest.ortb2)) {
52
+ logError(`${BIDDER_CODE}: cannot bid without a valid Content URL. Please populate ortb2.site.content.url`);
53
+ return;
54
+ }
55
+
56
+ const warnings = getWarnings(bidderRequest);
57
+ warnings.forEach(warning => {
58
+ logWarn(`${BIDDER_CODE}: ${warning}`);
59
+ });
60
+
61
+ return bidRequests.map(bidRequest => {
62
+ const payload = buildRequest(bidRequest, bidderRequest);
63
+
64
+ return {
65
+ method: 'POST',
66
+ url: AUCTION_URL,
67
+ data: payload
68
+ }
69
+ });
70
+ }
71
+
72
+ function interpretResponse(serverResponse) {
73
+ const outgoingBidResponses = [];
74
+ const serverResponseBody = serverResponse.body;
75
+
76
+ logResponseWarnings(serverResponseBody);
77
+
78
+ const seatBids = serverResponseBody && serverResponseBody.seatbid;
79
+ if (!isArray(seatBids)) {
80
+ return outgoingBidResponses;
81
+ }
82
+
83
+ const cur = serverResponseBody.cur;
84
+
85
+ seatBids.forEach(seatBid => {
86
+ seatBid.bid.forEach(bid => {
87
+ const bidResponse = {
88
+ requestId: serverResponseBody.id,
89
+ cpm: bid.price,
90
+ currency: cur,
91
+ width: bid.w,
92
+ height: bid.h,
93
+ ad: bid.adm,
94
+ vastXml: bid.adm,
95
+ ttl: bid.ttl || 3600,
96
+ netRevenue: false,
97
+ creativeId: bid.adid,
98
+ dealId: bid.dealid,
99
+ meta: {
100
+ advertiserDomains: bid.adomain,
101
+ mediaType: VIDEO,
102
+ primaryCatId: bid.cat,
103
+ }
104
+ };
105
+
106
+ outgoingBidResponses.push(bidResponse);
107
+ });
108
+ });
109
+
110
+ return outgoingBidResponses;
111
+ }
112
+
113
+ function getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent) {
114
+ if (!hasPurpose1Consent(gdprConsent)) {
115
+ return [];
116
+ }
117
+
118
+ const userSyncs = [];
119
+ const consentQueryParams = getUserSyncConsentQueryParams(gdprConsent);
120
+ const url = `https://ib.adnxs.com/getuid?${USER_SYNC_URL}?bidder=jwplayer&uid=$UID&f=i` + consentQueryParams
121
+
122
+ if (syncOptions.iframeEnabled) {
123
+ userSyncs.push({
124
+ type: 'iframe',
125
+ url
126
+ });
127
+ }
128
+
129
+ if (syncOptions.pixelEnabled) {
130
+ userSyncs.push({
131
+ type: 'image',
132
+ url
133
+ });
134
+ }
135
+
136
+ return userSyncs;
137
+ }
138
+
139
+ return {
140
+ code: BIDDER_CODE,
141
+ gvlid: GVLID,
142
+ supportedMediaTypes: SUPPORTED_AD_TYPES,
143
+ isBidRequestValid,
144
+ buildRequests,
145
+ interpretResponse,
146
+ getUserSyncs
147
+ }
148
+
149
+ function getUserSyncConsentQueryParams(gdprConsent) {
150
+ if (!gdprConsent) {
151
+ return '';
152
+ }
153
+
154
+ const consentString = gdprConsent.consentString;
155
+ if (!consentString) {
156
+ return '';
157
+ }
158
+
159
+ let gdpr = 0;
160
+ const gdprApplies = gdprConsent.gdprApplies;
161
+ if (typeof gdprApplies === 'boolean') {
162
+ gdpr = Number(gdprApplies)
163
+ }
164
+
165
+ return `&gdpr=${gdpr}&gdpr_consent=${consentString}`;
166
+ }
167
+
168
+ function buildRequest(bidRequest, bidderRequest) {
169
+ const openrtbRequest = {
170
+ id: bidRequest.bidId,
171
+ imp: getRequestImpressions(bidRequest, bidderRequest),
172
+ site: getRequestSite(bidRequest, bidderRequest),
173
+ device: getRequestDevice(bidderRequest.ortb2),
174
+ user: getRequestUser(bidderRequest.ortb2),
175
+ };
176
+
177
+ // GDPR Consent Params
178
+ if (bidderRequest.gdprConsent) {
179
+ deepSetValue(openrtbRequest, 'user.ext.consent', bidderRequest.gdprConsent.consentString);
180
+ deepSetValue(openrtbRequest, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0));
181
+ }
182
+
183
+ // CCPA
184
+ if (bidderRequest.uspConsent) {
185
+ deepSetValue(openrtbRequest, 'regs.ext.us_privacy', bidderRequest.uspConsent);
186
+ }
187
+
188
+ if (bidRequest.schain) {
189
+ deepSetValue(openrtbRequest, 'source.schain', bidRequest.schain);
190
+ }
191
+
192
+ openrtbRequest.tmax = bidderRequest.timeout || 200;
193
+
194
+ return JSON.stringify(openrtbRequest);
195
+ }
196
+
197
+ function getRequestImpressions(bidRequest) {
198
+ const impressionObject = {
199
+ id: bidRequest.adUnitCode,
200
+ };
201
+
202
+ impressionObject.video = getImpressionVideo(bidRequest);
203
+
204
+ const bidFloorData = getBidFloorData(bidRequest);
205
+ if (bidFloorData) {
206
+ impressionObject.bidfloor = bidFloorData.floor;
207
+ impressionObject.bidfloorcur = bidFloorData.currency;
208
+ }
209
+
210
+ impressionObject.ext = getImpressionExtension(bidRequest);
211
+
212
+ return [impressionObject];
213
+ }
214
+
215
+ function getImpressionVideo(bidRequest) {
216
+ const videoParams = deepAccess(bidRequest, 'mediaTypes.video', {});
217
+
218
+ const video = {};
219
+
220
+ VIDEO_ORTB_PARAMS.forEach((param) => {
221
+ if (videoParams.hasOwnProperty(param)) {
222
+ video[param] = videoParams[param];
223
+ }
224
+ });
225
+
226
+ setPlayerSize(video, videoParams);
227
+
228
+ if (!videoParams.plcmt) {
229
+ logWarn(`${BIDDER_CODE}: Please set a value to mediaTypes.video.plcmt`);
230
+ }
231
+
232
+ return video;
233
+ }
234
+
235
+ function getImpressionExtension(bidRequest) {
236
+ return {
237
+ prebid: {
238
+ bidder: {
239
+ jwplayer: {
240
+ placementId: bidRequest.params.placementId
241
+ }
242
+ }
243
+ }
244
+ };
245
+ }
246
+
247
+ function setPlayerSize(videoImp, videoParams) {
248
+ if (videoImp.w !== undefined && videoImp.h !== undefined) {
249
+ return;
250
+ }
251
+
252
+ const playerSize = getNormalizedPlayerSize(videoParams.playerSize);
253
+ if (!playerSize.length) {
254
+ logWarn(logWarn(`${BIDDER_CODE}: Video size has not been set. Please set values in video.h and video.w`));
255
+ return;
256
+ }
257
+
258
+ if (videoImp.w === undefined) {
259
+ videoImp.w = playerSize[0];
260
+ }
261
+
262
+ if (videoImp.h === undefined) {
263
+ videoImp.h = playerSize[1];
264
+ }
265
+ }
266
+
267
+ function getNormalizedPlayerSize(playerSize) {
268
+ if (!Array.isArray(playerSize)) {
269
+ return [];
270
+ }
271
+
272
+ if (Array.isArray(playerSize[0])) {
273
+ playerSize = playerSize[0];
274
+ }
275
+
276
+ if (playerSize.length < 2) {
277
+ return [];
278
+ }
279
+
280
+ return playerSize;
281
+ }
282
+
283
+ function getBidFloorData(bidRequest) {
284
+ const { params } = bidRequest;
285
+ const currency = params.currency || 'USD';
286
+
287
+ let floorData;
288
+ if (isFn(bidRequest.getFloor)) {
289
+ const bidFloorRequest = {
290
+ currency: currency,
291
+ mediaType: VIDEO,
292
+ size: '*'
293
+ };
294
+ floorData = bidRequest.getFloor(bidFloorRequest);
295
+ } else if (params.bidFloor) {
296
+ floorData = { floor: params.bidFloor, currency: currency };
297
+ }
298
+
299
+ return floorData;
300
+ }
301
+
302
+ function getRequestSite(bidRequest, bidderRequest) {
303
+ const site = bidderRequest.ortb2.site || {};
304
+
305
+ site.domain = site.domain || config.publisherDomain || window.location.hostname;
306
+ site.page = site.page || config.pageUrl || window.location.href;
307
+
308
+ const referer = bidderRequest.refererInfo && bidderRequest.refererInfo.referer;
309
+ if (!site.ref && referer) {
310
+ site.ref = referer;
311
+ }
312
+
313
+ const jwplayerPublisherExtChain = 'publisher.ext.jwplayer.';
314
+
315
+ deepSetValue(site, jwplayerPublisherExtChain + 'publisherId', bidRequest.params.publisherId);
316
+ deepSetValue(site, jwplayerPublisherExtChain + 'siteId', bidRequest.params.siteId);
317
+
318
+ return site;
319
+ }
320
+
321
+ function getRequestDevice(ortb2) {
322
+ const device = Object.assign({
323
+ h: screen.height,
324
+ w: screen.width,
325
+ ua: navigator.userAgent,
326
+ dnt: getDNT() ? 1 : 0,
327
+ js: 1
328
+ }, ortb2.device || {})
329
+
330
+ const language = getLanguage();
331
+ if (!device.language && language) {
332
+ device.language = language;
333
+ }
334
+
335
+ return device;
336
+ }
337
+
338
+ function getLanguage() {
339
+ const navigatorLanguage = navigator.language;
340
+ if (!navigatorLanguage) {
341
+ return;
342
+ }
343
+
344
+ const languageCodeSegments = navigatorLanguage.split('-');
345
+ if (!languageCodeSegments.length) {
346
+ return;
347
+ }
348
+
349
+ return languageCodeSegments[0];
350
+ }
351
+
352
+ function getRequestUser(ortb2) {
353
+ const user = ortb2.user || {};
354
+ if (config.getConfig('coppa') === true) {
355
+ user.coppa = true;
356
+ }
357
+
358
+ return user;
359
+ }
360
+
361
+ function hasContentUrl(ortb2) {
362
+ const site = ortb2.site;
363
+ const content = site && site.content;
364
+ return !!(content && content.url);
365
+ }
366
+
367
+ function getWarnings(bidderRequest) {
368
+ const content = bidderRequest.ortb2.site.content;
369
+ const contentChain = 'ortb2.site.content.';
370
+ const warnings = [];
371
+ if (!content.id) {
372
+ warnings.push(getMissingFieldMessage(contentChain + 'id'));
373
+ }
374
+
375
+ if (!content.title) {
376
+ warnings.push(getMissingFieldMessage(contentChain + 'title'));
377
+ }
378
+
379
+ if (!content.ext || !content.ext.description) {
380
+ warnings.push(getMissingFieldMessage(contentChain + 'ext.description'));
381
+ }
382
+
383
+ return warnings;
384
+ }
385
+
386
+ function getMissingFieldMessage(fieldName) {
387
+ return `Optional field ${fieldName} is not populated; we recommend populating for maximum performance.`
388
+ }
389
+
390
+ function logResponseWarnings(serverResponseBody) {
391
+ const warningPayload = deepAccess(serverResponseBody, 'ext.warnings');
392
+ if (!warningPayload) {
393
+ return;
394
+ }
395
+
396
+ const warningCategories = Object.keys(warningPayload);
397
+ warningCategories.forEach(category => {
398
+ const warnings = warningPayload[category];
399
+ if (!isArray(warnings)) {
400
+ return;
401
+ }
402
+
403
+ warnings.forEach(warning => {
404
+ logWarn(`${BIDDER_CODE}: [Bid Response][Warning Code: ${warning.code}] ${warning.message}`);
405
+ });
406
+ });
407
+ }
408
+ }
409
+
410
+ export const spec = getBidAdapter();
411
+
412
+ registerBidder(spec);
@@ -0,0 +1,72 @@
1
+ # Overview
2
+
3
+ ```
4
+ Module Name: JWPlayer Bid Adapter
5
+ Module Type: Bidder Adapter
6
+ Maintainer: boost-engineering@jwplayer.com
7
+ ```
8
+
9
+ # Description
10
+
11
+ Connects to JWPlayer's demand sources.
12
+
13
+ JWPlayer bid adapter supports Video (instream and outstream).
14
+
15
+ # Sample Ad Unit
16
+
17
+ ```markdown
18
+ const adUnit = {
19
+ code: 'test-ad-unit',
20
+ mediaTypes: {
21
+ video: {
22
+ pos: 0,
23
+ w: 640,
24
+ h: 480,
25
+ mimes : ['video/x-ms-wmv', 'video/mp4'],
26
+ minduration : 0,
27
+ maxduration: 60,
28
+ protocols : [2,3,7,5,6,8],
29
+ startdelay: 0,
30
+ placement: 1,
31
+ plcmt: 1,
32
+ skip: 1,
33
+ skipafter: 10,
34
+ playbackmethod: [3],
35
+ api: [2],
36
+ linearity: 1
37
+ }
38
+ },
39
+ bids: [{
40
+ bidder: 'jwplayer',
41
+ params: {
42
+ publisherId: 'test-publisher-id',
43
+ siteId: 'test-site-id',
44
+ placementId: 'test-placement-id'
45
+ }
46
+ }]
47
+ };
48
+ ```
49
+
50
+ # Sample ortb2 config
51
+
52
+ ```markdown
53
+ pbjs.setConfig({
54
+ ortb2: {
55
+ site: {
56
+ publisher: {
57
+ id: 'test-publisher-id'
58
+ },
59
+ content: {
60
+ id: 'test-media-id',
61
+ url: 'test.mp4',
62
+ title: 'title of my media',
63
+ ext: {
64
+ description: 'description of my media'
65
+ }
66
+ },
67
+ domain: 'test-domain.com',
68
+ page: 'https://www.test-domain.com/test.html',
69
+ }
70
+ }
71
+ }
72
+ ```
@@ -0,0 +1,42 @@
1
+ import * as utils from '../src/utils.js';
2
+ import { registerBidder } from '../src/adapters/bidderFactory.js';
3
+ import { config } from '../src/config.js';
4
+ import { BANNER } from '../src/mediaTypes.js';
5
+ import { ortbConverter } from '../libraries/ortbConverter/converter.js'
6
+ const converter = ortbConverter({
7
+ context: { netRevenue: true, ttl: 300 },
8
+ imp(buildImp, bidRequest, context) {
9
+ const imp = buildImp(bidRequest, context);
10
+ utils.mergeDeep(imp, {
11
+ tagid: bidRequest.params.site,
12
+ });
13
+ return imp;
14
+ }
15
+ });
16
+ const BIDDER_CODE = 'optable';
17
+ const DEFAULT_REGION = 'ca'
18
+ const DEFAULT_ORIGIN = 'https://ads.optable.co'
19
+
20
+ export const spec = {
21
+ code: BIDDER_CODE,
22
+ isBidRequestValid: function(bid) { return !!bid.params?.site },
23
+ buildRequests: function(bidRequests, bidderRequest) {
24
+ const region = config.getConfig('optable.region') ?? DEFAULT_REGION
25
+ const origin = config.getConfig('optable.origin') ?? DEFAULT_ORIGIN
26
+ const requestURL = `${origin}/${region}/ortb2/v1/ssp/bid`
27
+ const data = converter.toORTB({ bidRequests, bidderRequest, context: { mediaType: BANNER } });
28
+
29
+ return { method: 'POST', url: requestURL, data }
30
+ },
31
+ interpretResponse: function(response, request) {
32
+ const bids = converter.fromORTB({ response: response.body, request: request.data }).bids
33
+ const auctionConfigs = (response.body.ext?.optable?.fledge?.auctionconfigs ?? []).map((cfg) => {
34
+ const { impid, ...config } = cfg;
35
+ return { bidId: impid, config }
36
+ })
37
+
38
+ return { bids, fledgeAuctionConfigs: auctionConfigs }
39
+ },
40
+ supportedMediaTypes: [BANNER]
41
+ }
42
+ registerBidder(spec);
@@ -0,0 +1,41 @@
1
+ # Overview
2
+
3
+ ```
4
+ Module Name: Optable Bidder Adapter
5
+ Module Type: Bidder Adapter
6
+ Maintainer: prebid@optable.co
7
+ ```
8
+
9
+ # Description
10
+
11
+ Module that connects to Optable's demand sources.
12
+
13
+ # Bid Parameters
14
+ ## Banner
15
+
16
+ | Name | Scope | Type | Description | Example
17
+ | ---- | ----- | ---- | ----------- | -------
18
+ | `site` | required | String | Optable site ID provided by your Optable representative. | "aaaaaaaa"
19
+
20
+ ## Video
21
+
22
+ Not supported at the moment.
23
+
24
+ # Example
25
+ ```javascript
26
+ var adUnits = [
27
+ {
28
+ code: 'test-div',
29
+ sizes: [[728, 90]], // a display size
30
+ mediaTypes: {'banner': {}},
31
+ bids: [
32
+ {
33
+ bidder: 'optable',
34
+ params: {
35
+ site: 'aaaaaaaa',
36
+ },
37
+ },
38
+ ],
39
+ },
40
+ ];
41
+ ```