prebid.js 5.16.0 → 5.20.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 (182) hide show
  1. package/.devcontainer/Dockerfile +11 -0
  2. package/.devcontainer/devcontainer.json +27 -0
  3. package/.devcontainer/postCreate.sh +6 -0
  4. package/browsers.json +1 -0
  5. package/integrationExamples/gpt/akamaidap_segments_example.html +132 -0
  6. package/modules/.submodules.json +1 -0
  7. package/modules/adfBidAdapter.js +21 -16
  8. package/modules/adgenerationBidAdapter.js +28 -4
  9. package/modules/adkernelBidAdapter.js +3 -1
  10. package/modules/admixerBidAdapter.js +11 -0
  11. package/modules/adnuntiusBidAdapter.js +1 -0
  12. package/modules/adtelligentBidAdapter.js +2 -1
  13. package/modules/airgridRtdProvider.js +1 -1
  14. package/modules/akamaiDapRtdProvider.js +474 -0
  15. package/modules/akamaiDapRtdProvider.md +47 -0
  16. package/modules/aolBidAdapter.js +2 -1
  17. package/modules/appnexusBidAdapter.js +5 -3
  18. package/modules/atsAnalyticsAdapter.js +89 -63
  19. package/modules/atsAnalyticsAdapter.md +1 -0
  20. package/modules/betweenBidAdapter.js +20 -3
  21. package/modules/bliinkBidAdapter.js +58 -32
  22. package/modules/bliinkBidAdapter.md +29 -6
  23. package/modules/browsiRtdProvider.js +106 -18
  24. package/modules/cleanioRtdProvider.js +192 -0
  25. package/modules/cleanioRtdProvider.md +59 -0
  26. package/modules/codefuelBidAdapter.js +183 -0
  27. package/modules/codefuelBidAdapter.md +111 -0
  28. package/modules/connectIdSystem.js +104 -0
  29. package/modules/connectIdSystem.md +33 -0
  30. package/modules/cwireBidAdapter.js +272 -0
  31. package/modules/cwireBidAdapter.md +43 -0
  32. package/modules/deepintentBidAdapter.js +106 -9
  33. package/modules/deepintentBidAdapter.md +36 -1
  34. package/modules/deltaprojectsBidAdapter.js +252 -0
  35. package/modules/deltaprojectsBidAdapter.md +32 -0
  36. package/modules/dgkeywordRtdProvider.js +0 -1
  37. package/modules/engageyaBidAdapter.js +157 -0
  38. package/modules/glimpseBidAdapter.js +160 -48
  39. package/modules/glimpseBidAdapter.md +11 -74
  40. package/modules/gridBidAdapter.js +1 -0
  41. package/modules/gridNMBidAdapter.js +7 -6
  42. package/modules/gumgumBidAdapter.js +16 -2
  43. package/modules/iasRtdProvider.js +83 -67
  44. package/modules/inskinBidAdapter.js +7 -3
  45. package/modules/ixBidAdapter.js +8 -1
  46. package/modules/jixieBidAdapter.js +8 -2
  47. package/modules/justpremiumBidAdapter.js +6 -1
  48. package/modules/kargoBidAdapter.js +14 -7
  49. package/modules/kargoBidAdapter.md +20 -0
  50. package/modules/limelightDigitalBidAdapter.js +22 -2
  51. package/modules/livewrappedAnalyticsAdapter.js +53 -3
  52. package/modules/mediakeysBidAdapter.js +405 -14
  53. package/modules/mediakeysBidAdapter.md +108 -0
  54. package/modules/multibid/index.js +3 -3
  55. package/modules/mytargetBidAdapter.js +112 -0
  56. package/modules/nativoBidAdapter.js +48 -29
  57. package/modules/nativoBidAdapter.md +0 -1
  58. package/modules/nextMillenniumBidAdapter.js +12 -3
  59. package/modules/nextrollBidAdapter.js +375 -0
  60. package/modules/nobidBidAdapter.js +2 -1
  61. package/modules/oguryBidAdapter.js +36 -7
  62. package/modules/openxBidAdapter.js +34 -22
  63. package/modules/operaadsBidAdapter.js +21 -1
  64. package/modules/otmBidAdapter.js +146 -0
  65. package/modules/otmBidAdapter.md +27 -26
  66. package/modules/outbrainBidAdapter.js +5 -0
  67. package/modules/pixfutureBidAdapter.js +24 -4
  68. package/modules/pixfutureBidAdapter.md +127 -0
  69. package/modules/playwireBidAdapter.md +61 -0
  70. package/modules/prebidServerBidAdapter/index.js +1 -1
  71. package/modules/proxistoreBidAdapter.js +4 -6
  72. package/modules/publinkIdSystem.js +17 -7
  73. package/modules/publinkIdSystem.md +7 -2
  74. package/modules/pubmaticBidAdapter.js +22 -6
  75. package/modules/pubmaticBidAdapter.md +1 -1
  76. package/modules/relaidoBidAdapter.js +8 -2
  77. package/modules/rtdModule/index.js +2 -2
  78. package/modules/sharethroughBidAdapter.js +12 -19
  79. package/modules/slimcutBidAdapter.js +121 -0
  80. package/modules/sonobiBidAdapter.js +7 -0
  81. package/modules/sortableBidAdapter.js +1 -0
  82. package/modules/spotxBidAdapter.js +15 -1
  83. package/modules/sspBCBidAdapter.js +207 -12
  84. package/modules/sspBCBidAdapter.md +1 -1
  85. package/modules/talkadsBidAdapter.js +129 -0
  86. package/modules/talkadsBidAdapter.md +60 -0
  87. package/modules/tappxBidAdapter.js +6 -5
  88. package/modules/teadsBidAdapter.js +3 -0
  89. package/modules/tripleliftBidAdapter.js +22 -5
  90. package/modules/trustxBidAdapter.js +17 -11
  91. package/modules/undertoneBidAdapter.js +9 -5
  92. package/modules/undertoneBidAdapter.md +5 -1
  93. package/modules/unicornBidAdapter.js +3 -3
  94. package/modules/userId/eids.js +18 -0
  95. package/modules/userId/eids.md +7 -0
  96. package/modules/userId/userId.md +12 -0
  97. package/modules/ventesBidAdapter.js +370 -0
  98. package/modules/ventesBidAdapter.md +94 -0
  99. package/modules/videobyteBidAdapter.js +13 -6
  100. package/modules/videobyteBidAdapter.md +49 -0
  101. package/modules/vidoomyBidAdapter.js +20 -12
  102. package/modules/visxBidAdapter.js +15 -22
  103. package/modules/yahoosspBidAdapter.js +637 -0
  104. package/modules/yahoosspBidAdapter.md +795 -0
  105. package/modules/yieldlabBidAdapter.js +48 -3
  106. package/modules/yieldlabBidAdapter.md +16 -1
  107. package/modules/yieldmoBidAdapter.js +20 -6
  108. package/modules/yieldmoSyntheticInventoryModule.js +46 -0
  109. package/modules/yieldmoSyntheticInventoryModule.md +68 -0
  110. package/package.json +1 -1
  111. package/src/adapterManager.js +5 -0
  112. package/src/adapters/bidderFactory.js +4 -3
  113. package/src/auction.js +11 -11
  114. package/src/constants.json +1 -0
  115. package/src/secureCreatives.js +6 -7
  116. package/src/targeting.js +11 -9
  117. package/test/.eslintrc.js +2 -1
  118. package/test/spec/modules/adfBidAdapter_spec.js +83 -29
  119. package/test/spec/modules/adgenerationBidAdapter_spec.js +121 -50
  120. package/test/spec/modules/adnuntiusBidAdapter_spec.js +68 -0
  121. package/test/spec/modules/adtelligentBidAdapter_spec.js +1 -0
  122. package/test/spec/modules/akamaiDapRtdProvider_spec.js +246 -0
  123. package/test/spec/modules/appnexusBidAdapter_spec.js +2 -1
  124. package/test/spec/modules/atsAnalyticsAdapter_spec.js +77 -9
  125. package/test/spec/modules/betweenBidAdapter_spec.js +41 -0
  126. package/test/spec/modules/bliinkBidAdapter_spec.js +87 -36
  127. package/test/spec/modules/browsiRtdProvider_spec.js +62 -7
  128. package/test/spec/modules/cleanioRtdProvider_spec.js +188 -0
  129. package/test/spec/modules/codefuelBidAdapter_spec.js +316 -0
  130. package/test/spec/modules/connectIdSystem_spec.js +189 -0
  131. package/test/spec/modules/cwireBidAdapter_spec.js +246 -0
  132. package/test/spec/modules/deepintentBidAdapter_spec.js +153 -3
  133. package/test/spec/modules/deltaprojectsBidAdapter_spec.js +399 -0
  134. package/test/spec/modules/engageyaBidAdapter_spec.js +286 -0
  135. package/test/spec/modules/glimpseBidAdapter_spec.js +302 -204
  136. package/test/spec/modules/gridNMBidAdapter_spec.js +40 -1
  137. package/test/spec/modules/gumgumBidAdapter_spec.js +23 -6
  138. package/test/spec/modules/iasRtdProvider_spec.js +71 -6
  139. package/test/spec/modules/ixBidAdapter_spec.js +13 -3
  140. package/test/spec/modules/jixieBidAdapter_spec.js +13 -11
  141. package/test/spec/modules/justpremiumBidAdapter_spec.js +9 -2
  142. package/test/spec/modules/limelightDigitalBidAdapter_spec.js +155 -1
  143. package/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +67 -12
  144. package/test/spec/modules/mediakeysBidAdapter_spec.js +406 -51
  145. package/test/spec/modules/multibid_spec.js +31 -31
  146. package/test/spec/modules/mytargetBidAdapter_spec.js +199 -0
  147. package/test/spec/modules/nativoBidAdapter_spec.js +50 -3
  148. package/test/spec/modules/nextMillenniumBidAdapter_spec.js +13 -1
  149. package/test/spec/modules/nextrollBidAdapter_spec.js +290 -0
  150. package/test/spec/modules/nobidBidAdapter_spec.js +65 -1
  151. package/test/spec/modules/oguryBidAdapter_spec.js +125 -37
  152. package/test/spec/modules/openxBidAdapter_spec.js +85 -13
  153. package/test/spec/modules/operaadsBidAdapter_spec.js +38 -6
  154. package/test/spec/modules/otmBidAdapter_spec.js +67 -0
  155. package/test/spec/modules/outbrainBidAdapter_spec.js +18 -0
  156. package/test/spec/modules/publinkIdSystem_spec.js +34 -15
  157. package/test/spec/modules/pubmaticBidAdapter_spec.js +217 -1
  158. package/test/spec/modules/relaidoBidAdapter_spec.js +21 -20
  159. package/test/spec/modules/sharethroughBidAdapter_spec.js +156 -136
  160. package/test/spec/modules/slimcutBidAdapter_spec.js +200 -0
  161. package/test/spec/modules/sonobiBidAdapter_spec.js +34 -1
  162. package/test/spec/modules/sortableBidAdapter_spec.js +11 -0
  163. package/test/spec/modules/spotxBidAdapter_spec.js +36 -0
  164. package/test/spec/modules/sspBCBidAdapter_spec.js +210 -62
  165. package/test/spec/modules/talkadsBidAdapter_spec.js +231 -0
  166. package/test/spec/modules/teadsBidAdapter_spec.js +132 -0
  167. package/test/spec/modules/tripleliftBidAdapter_spec.js +128 -0
  168. package/test/spec/modules/trustxBidAdapter_spec.js +38 -5
  169. package/test/spec/modules/undertoneBidAdapter_spec.js +52 -0
  170. package/test/spec/modules/unicornBidAdapter_spec.js +4 -4
  171. package/test/spec/modules/ventesBidAdapter_spec.js +845 -0
  172. package/test/spec/modules/videobyteBidAdapter_spec.js +2 -2
  173. package/test/spec/modules/visxBidAdapter_spec.js +48 -4
  174. package/test/spec/modules/yahoosspBidAdapter_spec.js +1332 -0
  175. package/test/spec/modules/yieldlabBidAdapter_spec.js +65 -1
  176. package/test/spec/modules/yieldmoBidAdapter_spec.js +30 -9
  177. package/test/spec/modules/yieldmoSyntheticInventoryModule_spec.js +89 -0
  178. package/test/spec/unit/core/adapterManager_spec.js +32 -0
  179. package/test/spec/unit/core/bidderFactory_spec.js +61 -1
  180. package/test/spec/unit/pbjs_api_spec.js +37 -2
  181. package/test/spec/unit/secureCreatives_spec.js +54 -25
  182. package/modules/turktelekomBidAdapter.md +0 -49
@@ -1,13 +1,38 @@
1
- import { generateUUID, deepSetValue, deepAccess, isArray } from '../src/utils.js';
1
+ import { generateUUID, deepSetValue, deepAccess, isArray, isInteger, logError, logWarn } from '../src/utils.js';
2
2
  import {registerBidder} from '../src/adapters/bidderFactory.js';
3
- import {BANNER} from '../src/mediaTypes.js';
3
+ import {BANNER, VIDEO} from '../src/mediaTypes.js';
4
4
  const BIDDER_CODE = 'deepintent';
5
5
  const BIDDER_ENDPOINT = 'https://prebid.deepintent.com/prebid';
6
6
  const USER_SYNC_URL = 'https://cdn.deepintent.com/syncpixel.html';
7
7
  const DI_M_V = '1.0.0';
8
+ export const ORTB_VIDEO_PARAMS = {
9
+ 'mimes': (value) => Array.isArray(value) && value.length > 0 && value.every(v => typeof v === 'string'),
10
+ 'minduration': (value) => isInteger(value),
11
+ 'maxduration': (value) => isInteger(value),
12
+ 'protocols': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 10),
13
+ 'w': (value) => isInteger(value),
14
+ 'h': (value) => isInteger(value),
15
+ 'startdelay': (value) => isInteger(value),
16
+ 'placement': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 5),
17
+ 'linearity': (value) => [1, 2].indexOf(value) !== -1,
18
+ 'skip': (value) => [0, 1].indexOf(value) !== -1,
19
+ 'skipmin': (value) => isInteger(value),
20
+ 'skipafter': (value) => isInteger(value),
21
+ 'sequence': (value) => isInteger(value),
22
+ 'battr': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 17),
23
+ 'maxextended': (value) => isInteger(value),
24
+ 'minbitrate': (value) => isInteger(value),
25
+ 'maxbitrate': (value) => isInteger(value),
26
+ 'boxingallowed': (value) => [0, 1].indexOf(value) !== -1,
27
+ 'playbackmethod': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 6),
28
+ 'playbackend': (value) => [1, 2, 3].indexOf(value) !== -1,
29
+ 'delivery': (value) => [1, 2, 3].indexOf(value) !== -1,
30
+ 'pos': (value) => [0, 1, 2, 3, 4, 5, 6, 7].indexOf(value) !== -1,
31
+ 'api': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 6)
32
+ };
8
33
  export const spec = {
9
34
  code: BIDDER_CODE,
10
- supportedMediaTypes: [BANNER],
35
+ supportedMediaTypes: [BANNER, VIDEO],
11
36
  aliases: [],
12
37
 
13
38
  // tagId is mandatory param
@@ -15,16 +40,38 @@ export const spec = {
15
40
  let valid = false;
16
41
  if (bid && bid.params && bid.params.tagId) {
17
42
  if (typeof bid.params.tagId === 'string' || bid.params.tagId instanceof String) {
18
- valid = true;
43
+ if (bid.hasOwnProperty('mediaTypes') && bid.mediaTypes.hasOwnProperty(VIDEO)) {
44
+ if (bid.mediaTypes[VIDEO].hasOwnProperty('context')) {
45
+ valid = true;
46
+ }
47
+ } else {
48
+ valid = true;
49
+ }
19
50
  }
20
51
  }
21
52
  return valid;
22
53
  },
23
- interpretResponse: function(bidResponse, request) {
54
+ interpretResponse: function(bidResponse, bidRequest) {
24
55
  let responses = [];
25
56
  if (bidResponse && bidResponse.body) {
26
- let bids = bidResponse.body.seatbid && bidResponse.body.seatbid[0] ? bidResponse.body.seatbid[0].bid : [];
27
- responses = bids.map(bid => formatResponse(bid))
57
+ try {
58
+ let bids = bidResponse.body.seatbid && bidResponse.body.seatbid[0] ? bidResponse.body.seatbid[0].bid : [];
59
+ if (bids) {
60
+ bids.forEach(bidObj => {
61
+ let newBid = formatResponse(bidObj);
62
+ let mediaType = _checkMediaType(bidObj);
63
+ if (mediaType === BANNER) {
64
+ newBid.mediaType = BANNER;
65
+ } else if (mediaType === VIDEO) {
66
+ newBid.mediaType = VIDEO;
67
+ newBid.vastXml = bidObj.adm;
68
+ }
69
+ responses.push(newBid);
70
+ });
71
+ }
72
+ } catch (err) {
73
+ logError(err);
74
+ }
28
75
  }
29
76
  return responses;
30
77
  },
@@ -73,6 +120,17 @@ export const spec = {
73
120
  }
74
121
 
75
122
  };
123
+ function _checkMediaType(bid) {
124
+ let videoRegex = new RegExp(/VAST\s+version/);
125
+ let mediaType;
126
+ if (bid.adm && bid.adm.indexOf('deepintent_wrapper') >= 0) {
127
+ mediaType = BANNER;
128
+ } else if (videoRegex.test(bid.adm)) {
129
+ mediaType = VIDEO;
130
+ }
131
+ return mediaType;
132
+ }
133
+
76
134
  function clean(obj) {
77
135
  for (let propName in obj) {
78
136
  if (obj[propName] === null || obj[propName] === undefined) {
@@ -100,16 +158,55 @@ function formatResponse(bid) {
100
158
  }
101
159
 
102
160
  function buildImpression(bid) {
103
- return {
161
+ let impression = {};
162
+ impression = {
104
163
  id: bid.bidId,
105
164
  tagid: bid.params.tagId || '',
106
165
  secure: window.location.protocol === 'https' ? 1 : 0,
107
- banner: buildBanner(bid),
108
166
  displaymanager: 'di_prebid',
109
167
  displaymanagerver: DI_M_V,
110
168
  ext: buildCustomParams(bid)
111
169
  };
170
+ if (deepAccess(bid, 'mediaTypes.banner')) {
171
+ impression['banner'] = buildBanner(bid);
172
+ }
173
+ if (deepAccess(bid, 'mediaTypes.video')) {
174
+ impression['video'] = _buildVideo(bid);
175
+ }
176
+ return impression;
112
177
  }
178
+
179
+ function _buildVideo(bid) {
180
+ const videoObj = {};
181
+ const videoAdUnitParams = deepAccess(bid, 'mediaTypes.video', {});
182
+ const videoBidderParams = deepAccess(bid, 'params.video', {});
183
+ const computedParams = {};
184
+
185
+ if (Array.isArray(videoAdUnitParams.playerSize)) {
186
+ const tempSize = (Array.isArray(videoAdUnitParams.playerSize[0])) ? videoAdUnitParams.playerSize[0] : videoAdUnitParams.playerSize;
187
+ computedParams.w = tempSize[0];
188
+ computedParams.h = tempSize[1];
189
+ }
190
+
191
+ const videoParams = {
192
+ ...computedParams,
193
+ ...videoAdUnitParams,
194
+ ...videoBidderParams
195
+ };
196
+
197
+ Object.keys(ORTB_VIDEO_PARAMS).forEach(paramName => {
198
+ if (videoParams.hasOwnProperty(paramName)) {
199
+ if (ORTB_VIDEO_PARAMS[paramName](videoParams[paramName])) {
200
+ videoObj[paramName] = videoParams[paramName];
201
+ } else {
202
+ logWarn(`The OpenRTB video param ${paramName} has been skipped due to misformating. Please refer to OpenRTB 2.5 spec.`);
203
+ }
204
+ }
205
+ });
206
+
207
+ return videoObj;
208
+ };
209
+
113
210
  function buildCustomParams(bid) {
114
211
  if (bid.params && bid.params.custom) {
115
212
  return {
@@ -8,7 +8,7 @@ Maintainer: prebid@deepintent.com
8
8
 
9
9
  # Description
10
10
 
11
- Deepintent currently supports the BANNER type ads through prebid js
11
+ Deepintent currently supports the BANNER and VIDEO type ads through prebid js
12
12
 
13
13
  Module that connects to Deepintent's demand sources.
14
14
 
@@ -40,6 +40,41 @@ Module that connects to Deepintent's demand sources.
40
40
  ];
41
41
  ```
42
42
 
43
+ # Sample Video Ad Unit
44
+ ```
45
+ var adVideoAdUnits = [
46
+ {
47
+ code: 'test-div-video',
48
+ mediaTypes: {
49
+ video: {
50
+ playerSize: [640, 480], // required
51
+ context: 'instream' //required
52
+ }
53
+ },
54
+ bids: [{
55
+ bidder: 'deepintent',
56
+ params: {
57
+ tagId: '1300', // Required parameter // required
58
+ video: {
59
+ mimes: ['video/mp4','video/x-flv'], // required
60
+ skippable: true, // optional
61
+ minduration: 5, // optional
62
+ maxduration: 30, // optional
63
+ startdelay: 5, // optional
64
+ playbackmethod: [1,3], // optional
65
+ api: [ 1, 2 ], // optional
66
+ protocols: [ 2, 3 ], // optional
67
+ battr: [ 13, 14 ], // optional
68
+ linearity: 1, // optional
69
+ placement: 2, // optional
70
+ minbitrate: 10, // optional
71
+ maxbitrate: 10 // optional
72
+ }
73
+ }
74
+ }]
75
+ }]
76
+ ```
77
+
43
78
  ###Recommended User Sync Configuration
44
79
 
45
80
  ```javascript
@@ -0,0 +1,252 @@
1
+ import { registerBidder } from '../src/adapters/bidderFactory.js';
2
+ import { BANNER } from '../src/mediaTypes.js';
3
+ import {
4
+ _each, _map, isFn, isNumber, createTrackPixelHtml, deepAccess, parseUrl, logWarn, logError
5
+ } from '../src/utils.js';
6
+ import {config} from '../src/config.js';
7
+
8
+ export const BIDDER_CODE = 'deltaprojects';
9
+ export const BIDDER_ENDPOINT_URL = 'https://d5p.de17a.com/dogfight/prebid';
10
+ export const USERSYNC_URL = 'https://userservice.de17a.com/getuid/prebid';
11
+
12
+ /** -- isBidRequestValid --**/
13
+ function isBidRequestValid(bid) {
14
+ if (!bid) return false;
15
+
16
+ if (bid.bidder !== BIDDER_CODE) return false;
17
+
18
+ // publisher id is required
19
+ const publisherId = deepAccess(bid, 'params.publisherId')
20
+ if (!publisherId) {
21
+ logError('Invalid bid request, missing publisher id in params');
22
+ return false;
23
+ }
24
+
25
+ return true;
26
+ }
27
+
28
+ /** -- Build requests --**/
29
+ function buildRequests(validBidRequests, bidderRequest) {
30
+ /** == shared ==**/
31
+ // -- build id
32
+ const id = bidderRequest.auctionId;
33
+
34
+ // -- build site
35
+ const loc = parseUrl(bidderRequest.refererInfo.referer);
36
+ const publisherId = setOnAny(validBidRequests, 'params.publisherId');
37
+ const siteId = setOnAny(validBidRequests, 'params.siteId');
38
+ const site = {
39
+ id: siteId,
40
+ domain: loc.hostname,
41
+ page: loc.href,
42
+ ref: loc.href,
43
+ publisher: { id: publisherId },
44
+ };
45
+
46
+ // -- build device
47
+ const ua = navigator.userAgent;
48
+ const device = {
49
+ ua,
50
+ w: screen.width,
51
+ h: screen.height
52
+ }
53
+
54
+ // -- build user, reg
55
+ let user = { ext: {} };
56
+ const regs = { ext: {} };
57
+ const gdprConsent = bidderRequest && bidderRequest.gdprConsent;
58
+ if (gdprConsent) {
59
+ user.ext = { consent: gdprConsent.consentString };
60
+ if (typeof gdprConsent.gdprApplies == 'boolean') {
61
+ regs.ext.gdpr = gdprConsent.gdprApplies ? 1 : 0
62
+ }
63
+ }
64
+
65
+ // -- build tmax
66
+ let tmax = (bidderRequest && bidderRequest.timeout > 0) ? bidderRequest.timeout : undefined;
67
+
68
+ // build bid specific
69
+ return validBidRequests.map(validBidRequest => {
70
+ const openRTBRequest = buildOpenRTBRequest(validBidRequest, id, site, device, user, tmax, regs);
71
+ return {
72
+ method: 'POST',
73
+ url: BIDDER_ENDPOINT_URL,
74
+ data: openRTBRequest,
75
+ options: { contentType: 'application/json' },
76
+ bids: [validBidRequest],
77
+ };
78
+ });
79
+ }
80
+
81
+ function buildOpenRTBRequest(validBidRequest, id, site, device, user, tmax, regs) {
82
+ // build cur
83
+ const currency = config.getConfig('currency.adServerCurrency') || deepAccess(validBidRequest, 'params.currency');
84
+ const cur = currency && [currency];
85
+
86
+ // build impression
87
+ const impression = buildImpression(validBidRequest, currency);
88
+
89
+ // build test
90
+ const test = deepAccess(validBidRequest, 'params.test') ? 1 : 0
91
+
92
+ const at = 1
93
+
94
+ // build source
95
+ const source = {
96
+ tid: validBidRequest.transactionId,
97
+ fd: 1,
98
+ }
99
+
100
+ return {
101
+ id,
102
+ at,
103
+ imp: [impression],
104
+ site,
105
+ device,
106
+ user,
107
+ test,
108
+ tmax,
109
+ cur,
110
+ source,
111
+ regs,
112
+ ext: {},
113
+ };
114
+ }
115
+
116
+ function buildImpression(bid, currency) {
117
+ const impression = {
118
+ id: bid.bidId,
119
+ tagid: bid.params.tagId,
120
+ ext: {},
121
+ };
122
+
123
+ const bannerMediaType = deepAccess(bid, `mediaTypes.${BANNER}`);
124
+ impression.banner = buildImpressionBanner(bid, bannerMediaType);
125
+
126
+ // bid floor
127
+ const bidFloor = getBidFloor(bid, BANNER, '*', currency);
128
+ if (bidFloor) {
129
+ impression.bidfloor = bidFloor.floor;
130
+ impression.bidfloorcur = bidFloor.currency;
131
+ }
132
+
133
+ return impression;
134
+ }
135
+
136
+ function buildImpressionBanner(bid, bannerMediaType) {
137
+ const bannerSizes = (bannerMediaType && bannerMediaType.sizes) || bid.sizes;
138
+ return {
139
+ format: _map(bannerSizes, ([width, height]) => ({ w: width, h: height })),
140
+ };
141
+ }
142
+
143
+ /** -- Interpret response --**/
144
+ function interpretResponse(serverResponse) {
145
+ if (!serverResponse.body) {
146
+ logWarn('Response body is invalid, return !!');
147
+ return [];
148
+ }
149
+
150
+ const { body: { id, seatbid, cur } } = serverResponse;
151
+ if (!id || !seatbid) {
152
+ logWarn('Id / seatbid of response is invalid, return !!');
153
+ return [];
154
+ }
155
+
156
+ const bidResponses = [];
157
+
158
+ _each(seatbid, seatbid => {
159
+ _each(seatbid.bid, bid => {
160
+ const bidObj = {
161
+ requestId: bid.impid,
162
+ cpm: parseFloat(bid.price),
163
+ width: parseInt(bid.w),
164
+ height: parseInt(bid.h),
165
+ creativeId: bid.crid || bid.id,
166
+ dealId: bid.dealid || null,
167
+ currency: cur,
168
+ netRevenue: true,
169
+ ttl: 60,
170
+ };
171
+
172
+ bidObj.mediaType = BANNER;
173
+ bidObj.ad = bid.adm;
174
+ if (bid.nurl) {
175
+ bidObj.ad += createTrackPixelHtml(decodeURIComponent(bid.nurl));
176
+ }
177
+ if (bid.ext) {
178
+ bidObj[BIDDER_CODE] = bid.ext;
179
+ }
180
+ bidResponses.push(bidObj);
181
+ });
182
+ });
183
+ return bidResponses;
184
+ }
185
+
186
+ /** -- On Bid Won -- **/
187
+ function onBidWon(bid) {
188
+ let cpm = bid.cpm;
189
+ if (bid.currency && bid.currency !== bid.originalCurrency && typeof bid.getCpmInNewCurrency === 'function') {
190
+ cpm = bid.getCpmInNewCurrency(bid.originalCurrency);
191
+ }
192
+ const wonPrice = Math.round(cpm * 1000000);
193
+ const wonPriceMacroPatten = /\$\{AUCTION_PRICE:B64\}/g;
194
+ bid.ad = bid.ad.replace(wonPriceMacroPatten, wonPrice);
195
+ }
196
+
197
+ /** -- Get user syncs --**/
198
+ function getUserSyncs(syncOptions, serverResponses, gdprConsent) {
199
+ const syncs = []
200
+
201
+ if (syncOptions.pixelEnabled) {
202
+ let gdprParams;
203
+ if (gdprConsent) {
204
+ if (typeof gdprConsent.gdprApplies === 'boolean') {
205
+ gdprParams = `?gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`;
206
+ } else {
207
+ gdprParams = `?gdpr_consent=${gdprConsent.consentString}`;
208
+ }
209
+ } else {
210
+ gdprParams = '';
211
+ }
212
+ syncs.push({
213
+ type: 'image',
214
+ url: USERSYNC_URL + gdprParams
215
+ });
216
+ }
217
+ return syncs;
218
+ }
219
+
220
+ /** -- Get bid floor --**/
221
+ export function getBidFloor(bid, mediaType, size, currency) {
222
+ if (isFn(bid.getFloor)) {
223
+ const bidFloorCurrency = currency || 'USD';
224
+ const bidFloor = bid.getFloor({currency: bidFloorCurrency, mediaType: mediaType, size: size});
225
+ if (isNumber(bidFloor.floor)) {
226
+ return bidFloor;
227
+ }
228
+ }
229
+ }
230
+
231
+ /** -- Helper methods --**/
232
+ function setOnAny(collection, key) {
233
+ for (let i = 0, result; i < collection.length; i++) {
234
+ result = deepAccess(collection[i], key);
235
+ if (result) {
236
+ return result;
237
+ }
238
+ }
239
+ }
240
+
241
+ /** -- Register -- */
242
+ export const spec = {
243
+ code: BIDDER_CODE,
244
+ supportedMediaTypes: [BANNER],
245
+ isBidRequestValid,
246
+ buildRequests,
247
+ interpretResponse,
248
+ onBidWon,
249
+ getUserSyncs,
250
+ };
251
+
252
+ registerBidder(spec);
@@ -0,0 +1,32 @@
1
+ # Overview
2
+
3
+ ```
4
+ Module Name: Delta Projects Bid Adapter
5
+ Module Type: Bidder Adapter
6
+ Maintainer: dev@deltaprojects.com
7
+ ```
8
+
9
+ # Description
10
+
11
+ Connects to Delta Projects DSP for bids.
12
+
13
+ # Test Parameters
14
+ ```
15
+ // define banner unit
16
+ var bannerUnit = {
17
+ code: 'div-gpt-ad-1460505748561-0',
18
+ mediaTypes: {
19
+ banner: {
20
+ sizes: [[300, 250], [300,600]],
21
+ }
22
+ },
23
+ // Replace this object to test a new Adapter!
24
+ bids: [{
25
+ bidder: 'deltaprojects',
26
+ params: {
27
+ publisherId: '4' //required
28
+ }
29
+ }]
30
+ };
31
+ ```
32
+
@@ -78,7 +78,6 @@ export function getDgKeywordsAndSet(reqBidsConfigObj, callback, moduleConfig, us
78
78
  }
79
79
  }, null, {
80
80
  withCredentials: true,
81
- contentType: 'application/json',
82
81
  });
83
82
  setTimeout(function () {
84
83
  if (!isFinish) {
@@ -0,0 +1,157 @@
1
+ import {
2
+ BANNER,
3
+ NATIVE
4
+ } from '../src/mediaTypes.js';
5
+ import { createTrackPixelHtml } from '../src/utils.js';
6
+
7
+ const {
8
+ registerBidder
9
+ } = require('../src/adapters/bidderFactory.js');
10
+ const BIDDER_CODE = 'engageya';
11
+ const ENDPOINT_URL = 'https://recs.engageya.com/rec-api/getrecs.json';
12
+ const ENDPOINT_METHOD = 'GET';
13
+
14
+ function getPageUrl() {
15
+ var pUrl = window.location.href;
16
+ if (isInIframe()) {
17
+ pUrl = document.referrer ? document.referrer : pUrl;
18
+ }
19
+ pUrl = encodeURIComponent(pUrl);
20
+ return pUrl;
21
+ }
22
+
23
+ function isInIframe() {
24
+ try {
25
+ var isInIframe = (window.self !== window.top);
26
+ } catch (e) {
27
+ isInIframe = true;
28
+ }
29
+ return isInIframe;
30
+ }
31
+
32
+ function getImageSrc(rec) {
33
+ return rec.thumbnail_path.indexOf('http') === -1 ? 'https:' + rec.thumbnail_path : rec.thumbnail_path;
34
+ }
35
+
36
+ function getImpressionTrackers(rec) {
37
+ if (!rec.trackers) {
38
+ return [];
39
+ }
40
+ const impressionTrackers = rec.trackers.impressionPixels || [];
41
+ const viewTrackers = rec.trackers.viewPixels || [];
42
+ return [...impressionTrackers, ...viewTrackers];
43
+ }
44
+
45
+ function parseNativeResponse(rec, response) {
46
+ return {
47
+ title: rec.title,
48
+ body: '',
49
+ image: {
50
+ url: getImageSrc(rec),
51
+ width: response.imageWidth,
52
+ height: response.imageHeight
53
+ },
54
+ privacyLink: '',
55
+ clickUrl: rec.clickUrl,
56
+ displayUrl: rec.url,
57
+ cta: '',
58
+ sponsoredBy: rec.displayName,
59
+ impressionTrackers: getImpressionTrackers(rec),
60
+ };
61
+ }
62
+
63
+ function parseBannerResponse(rec, response) {
64
+ if (rec.tag) {
65
+ return rec.tag;
66
+ }
67
+ let style;
68
+ try {
69
+ let additionalData = JSON.parse(response.widget.additionalData);
70
+ const css = additionalData.css || '';
71
+ style = css ? `<style>${css}</style>` : '';
72
+ } catch (e) {
73
+ style = '';
74
+ }
75
+ const title = rec.title && rec.title.trim() ? `<div class="eng_tag_ttl" style="display: none">${rec.title}</div>` : '';
76
+ const displayName = rec.displayName && title ? `<div class="eng_tag_brnd" style="display: none">${rec.displayName}</div>` : '';
77
+ const trackers = getImpressionTrackers(rec)
78
+ .map(createTrackPixelHtml)
79
+ .join('');
80
+ 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>`;
81
+ }
82
+
83
+ export const spec = {
84
+ code: BIDDER_CODE,
85
+ supportedMediaTypes: [BANNER, NATIVE],
86
+ isBidRequestValid: function (bid) {
87
+ return bid && bid.params && bid.params.hasOwnProperty('widgetId') && bid.params.hasOwnProperty('websiteId') && !isNaN(bid.params.widgetId) && !isNaN(bid.params.websiteId);
88
+ },
89
+
90
+ buildRequests: function (validBidRequests, bidderRequest) {
91
+ var bidRequests = [];
92
+ if (validBidRequests && validBidRequests.length > 0) {
93
+ validBidRequests.forEach(function (bidRequest) {
94
+ if (bidRequest.params) {
95
+ var mediaType = bidRequest.hasOwnProperty('nativeParams') ? 1 : 2;
96
+ var imageWidth = -1;
97
+ var imageHeight = -1;
98
+ if (bidRequest.sizes && bidRequest.sizes.length > 0) {
99
+ imageWidth = bidRequest.sizes[0][0];
100
+ imageHeight = bidRequest.sizes[0][1];
101
+ } else if (bidRequest.nativeParams && bidRequest.nativeParams.image && bidRequest.nativeParams.image.sizes) {
102
+ imageWidth = bidRequest.nativeParams.image.sizes[0];
103
+ imageHeight = bidRequest.nativeParams.image.sizes[1];
104
+ }
105
+
106
+ var widgetId = bidRequest.params.widgetId;
107
+ var websiteId = bidRequest.params.websiteId;
108
+ var pageUrl = (bidRequest.params.pageUrl && bidRequest.params.pageUrl != '[PAGE_URL]') ? bidRequest.params.pageUrl : '';
109
+ if (!pageUrl) {
110
+ pageUrl = (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer) ? bidderRequest.refererInfo.referer : getPageUrl();
111
+ }
112
+ var bidId = bidRequest.bidId;
113
+ var finalUrl = ENDPOINT_URL + '?pubid=0&webid=' + websiteId + '&wid=' + widgetId + '&url=' + pageUrl + '&ireqid=' + bidId + '&pbtpid=' + mediaType + '&imw=' + imageWidth + '&imh=' + imageHeight;
114
+ if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprApplies && bidderRequest.consentString) {
115
+ finalUrl += '&is_gdpr=1&gdpr_consent=' + bidderRequest.consentString;
116
+ }
117
+ bidRequests.push({
118
+ url: finalUrl,
119
+ method: ENDPOINT_METHOD,
120
+ data: ''
121
+ });
122
+ }
123
+ });
124
+ }
125
+
126
+ return bidRequests;
127
+ },
128
+
129
+ interpretResponse: function (serverResponse, bidRequest) {
130
+ if (!serverResponse.body || !serverResponse.body.recs || !serverResponse.body.recs.length) {
131
+ return [];
132
+ }
133
+ var response = serverResponse.body;
134
+ var isNative = response.pbtypeId == 1;
135
+ return response.recs.map(rec => {
136
+ let bid = {
137
+ requestId: response.ireqId,
138
+ cpm: rec.ecpm,
139
+ width: response.imageWidth,
140
+ height: response.imageHeight,
141
+ creativeId: rec.postId,
142
+ currency: 'USD',
143
+ netRevenue: false,
144
+ ttl: 360,
145
+ meta: { advertiserDomains: rec.domain ? [rec.domain] : [] },
146
+ }
147
+ if (isNative) {
148
+ bid.native = parseNativeResponse(rec, response);
149
+ } else {
150
+ bid.ad = parseBannerResponse(rec, response);
151
+ }
152
+ return bid;
153
+ });
154
+ }
155
+ };
156
+
157
+ registerBidder(spec);