prebid.js 5.20.0 → 6.3.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 (168) hide show
  1. package/.babelrc.js +1 -10
  2. package/README.md +4 -2
  3. package/browsers.json +13 -37
  4. package/gulpfile.js +1 -8
  5. package/integrationExamples/gpt/weboramaRtdProvider_example.html +23 -14
  6. package/karma.conf.maker.js +1 -1
  7. package/modules/33acrossBidAdapter.js +189 -102
  8. package/modules/adagioBidAdapter.js +1 -1
  9. package/modules/addefendBidAdapter.js +1 -0
  10. package/modules/adheseBidAdapter.js +7 -2
  11. package/modules/adkernelBidAdapter.js +1 -0
  12. package/modules/adlivetechBidAdapter.md +61 -0
  13. package/modules/admanBidAdapter.js +1 -0
  14. package/modules/admixerBidAdapter.js +3 -2
  15. package/modules/adnuntiusBidAdapter.js +5 -2
  16. package/modules/adomikAnalyticsAdapter.js +10 -4
  17. package/modules/adplusBidAdapter.js +203 -0
  18. package/modules/adplusBidAdapter.md +39 -0
  19. package/modules/adxcgBidAdapter.js +311 -359
  20. package/modules/adxcgBidAdapter.md +22 -21
  21. package/modules/adyoulikeBidAdapter.js +7 -2
  22. package/modules/appnexusBidAdapter.js +23 -3
  23. package/modules/beachfrontBidAdapter.js +14 -17
  24. package/modules/beopBidAdapter.js +5 -3
  25. package/modules/codefuelBidAdapter.js +1 -3
  26. package/modules/codefuelBidAdapter.md +3 -3
  27. package/modules/colossussspBidAdapter.js +7 -0
  28. package/modules/craftBidAdapter.js +5 -3
  29. package/modules/criteoBidAdapter.js +1 -1
  30. package/modules/cwireBidAdapter.js +3 -0
  31. package/modules/datablocksBidAdapter.js +3 -3
  32. package/modules/dchain.js +149 -0
  33. package/modules/dchain.md +45 -0
  34. package/modules/deepintentBidAdapter.js +1 -1
  35. package/modules/dspxBidAdapter.js +1 -1
  36. package/modules/emx_digitalBidAdapter.js +9 -1
  37. package/modules/engageyaBidAdapter.js +68 -54
  38. package/modules/freewheel-sspBidAdapter.js +6 -0
  39. package/modules/futureads.md +48 -0
  40. package/modules/glimpseBidAdapter.js +44 -16
  41. package/modules/goldbachBidAdapter.js +1176 -0
  42. package/modules/goldbachBidAdapter.md +151 -0
  43. package/modules/gptPreAuction.js +11 -5
  44. package/modules/gridBidAdapter.js +1 -1
  45. package/modules/gumgumBidAdapter.js +7 -3
  46. package/modules/id5IdSystem.md +6 -6
  47. package/modules/imRtdProvider.js +31 -0
  48. package/modules/intersectionRtdProvider.js +114 -0
  49. package/modules/invibesBidAdapter.js +15 -9
  50. package/modules/ipromBidAdapter.js +79 -0
  51. package/modules/ixBidAdapter.js +166 -21
  52. package/modules/kinessoIdSystem.js +1 -1
  53. package/modules/limelightDigitalBidAdapter.js +2 -1
  54. package/modules/lotamePanoramaIdSystem.js +80 -8
  55. package/modules/luponmediaBidAdapter.js +570 -0
  56. package/modules/mediasquareBidAdapter.js +1 -9
  57. package/modules/merkleIdSystem.js +5 -0
  58. package/modules/missenaBidAdapter.js +89 -0
  59. package/modules/nativoBidAdapter.js +27 -1
  60. package/modules/nextMillenniumBidAdapter.js +29 -1
  61. package/modules/oguryBidAdapter.js +2 -1
  62. package/modules/openxBidAdapter.js +6 -1
  63. package/modules/prebidServerBidAdapter/index.js +19 -15
  64. package/modules/pubmaticBidAdapter.js +5 -3
  65. package/modules/relaidoBidAdapter.js +86 -65
  66. package/modules/richaudienceBidAdapter.js +2 -3
  67. package/modules/rtdModule/index.js +48 -18
  68. package/modules/rubiconBidAdapter.js +10 -8
  69. package/modules/saambaaBidAdapter.js +420 -0
  70. package/modules/saambaaBidAdapter.md +65 -68
  71. package/modules/seedtagBidAdapter.js +6 -0
  72. package/modules/sharedIdSystem.js +27 -1
  73. package/modules/smaatoBidAdapter.js +9 -1
  74. package/modules/smartxBidAdapter.js +17 -1
  75. package/modules/sspBCBidAdapter.js +34 -3
  76. package/modules/tappxBidAdapter.js +3 -1
  77. package/modules/targetVideoBidAdapter.js +187 -0
  78. package/modules/targetVideoBidAdapter.md +34 -0
  79. package/modules/trustxBidAdapter.js +10 -1
  80. package/modules/undertoneBidAdapter.js +8 -1
  81. package/modules/userId/index.js +27 -2
  82. package/modules/ventes.md +71 -0
  83. package/modules/ventesBidAdapter.js +104 -64
  84. package/modules/ventesBidAdapter.md +0 -1
  85. package/modules/vidoomyBidAdapter.js +65 -108
  86. package/modules/visxBidAdapter.js +20 -3
  87. package/modules/visxBidAdapter.md +4 -6
  88. package/modules/weboramaRtdProvider.js +288 -73
  89. package/modules/weboramaRtdProvider.md +27 -10
  90. package/modules/yahoosspBidAdapter.js +5 -1
  91. package/modules/yahoosspBidAdapter.md +1 -1
  92. package/modules/yieldlabBidAdapter.js +41 -10
  93. package/modules/yieldlabBidAdapter.md +91 -48
  94. package/modules/yieldoneBidAdapter.js +115 -11
  95. package/modules/zetaSspBidAdapter.md +33 -1
  96. package/modules/zeta_global_sspBidAdapter.js +22 -1
  97. package/package.json +6 -1
  98. package/plugins/pbjsGlobals.js +28 -1
  99. package/src/adapterManager.js +14 -8
  100. package/src/auction.js +3 -2
  101. package/src/prebid.js +1 -2
  102. package/src/targeting.js +24 -3
  103. package/src/utils.js +41 -7
  104. package/test/spec/integration/faker/googletag.js +6 -0
  105. package/test/spec/modules/33acrossBidAdapter_spec.js +300 -78
  106. package/test/spec/modules/adheseBidAdapter_spec.js +27 -1
  107. package/test/spec/modules/adnuntiusBidAdapter_spec.js +35 -0
  108. package/test/spec/modules/adomikAnalyticsAdapter_spec.js +3 -1
  109. package/test/spec/modules/adplusBidAdapter_spec.js +213 -0
  110. package/test/spec/modules/adxcgBidAdapter_spec.js +820 -571
  111. package/test/spec/modules/adyoulikeBidAdapter_spec.js +26 -0
  112. package/test/spec/modules/appnexusBidAdapter_spec.js +63 -1
  113. package/test/spec/modules/beachfrontBidAdapter_spec.js +65 -1
  114. package/test/spec/modules/codefuelBidAdapter_spec.js +1 -1
  115. package/test/spec/modules/colossussspBidAdapter_spec.js +9 -0
  116. package/test/spec/modules/cwireBidAdapter_spec.js +10 -8
  117. package/test/spec/modules/datablocksBidAdapter_spec.js +3 -3
  118. package/test/spec/modules/dchain_spec.js +329 -0
  119. package/test/spec/modules/emx_digitalBidAdapter_spec.js +10 -0
  120. package/test/spec/modules/engageyaBidAdapter_spec.js +231 -95
  121. package/test/spec/modules/eplanningBidAdapter_spec.js +8 -8
  122. package/test/spec/modules/freewheel-sspBidAdapter_spec.js +19 -0
  123. package/test/spec/modules/glimpseBidAdapter_spec.js +33 -0
  124. package/test/spec/modules/goldbachBidAdapter_spec.js +1359 -0
  125. package/test/spec/modules/gptPreAuction_spec.js +58 -4
  126. package/test/spec/modules/gumgumBidAdapter_spec.js +6 -0
  127. package/test/spec/modules/imRtdProvider_spec.js +25 -0
  128. package/test/spec/modules/intersectionRtdProvider_spec.js +141 -0
  129. package/test/spec/modules/invibesBidAdapter_spec.js +29 -4
  130. package/test/spec/modules/ipromBidAdapter_spec.js +195 -0
  131. package/test/spec/modules/ixBidAdapter_spec.js +285 -2
  132. package/test/spec/modules/konduitWrapper_spec.js +0 -1
  133. package/test/spec/modules/limelightDigitalBidAdapter_spec.js +10 -7
  134. package/test/spec/modules/lotamePanoramaIdSystem_spec.js +227 -0
  135. package/test/spec/modules/luponmediaBidAdapter_spec.js +412 -0
  136. package/test/spec/modules/mediasquareBidAdapter_spec.js +4 -4
  137. package/test/spec/modules/merkleIdSystem_spec.js +18 -0
  138. package/test/spec/modules/missenaBidAdapter_spec.js +134 -0
  139. package/test/spec/modules/nativoBidAdapter_spec.js +35 -18
  140. package/test/spec/modules/nextMillenniumBidAdapter_spec.js +18 -0
  141. package/test/spec/modules/oguryBidAdapter_spec.js +13 -11
  142. package/test/spec/modules/openxBidAdapter_spec.js +5 -0
  143. package/test/spec/modules/prebidServerBidAdapter_spec.js +62 -2
  144. package/test/spec/modules/pubmaticBidAdapter_spec.js +1 -1
  145. package/test/spec/modules/realTimeDataModule_spec.js +135 -49
  146. package/test/spec/modules/relaidoBidAdapter_spec.js +71 -63
  147. package/test/spec/modules/richaudienceBidAdapter_spec.js +2 -2
  148. package/test/spec/modules/rubiconBidAdapter_spec.js +17 -0
  149. package/test/spec/modules/seedtagBidAdapter_spec.js +3 -0
  150. package/test/spec/modules/sharedIdSystem_spec.js +52 -6
  151. package/test/spec/modules/smaatoBidAdapter_spec.js +61 -0
  152. package/test/spec/modules/smartxBidAdapter_spec.js +9 -0
  153. package/test/spec/modules/sspBCBidAdapter_spec.js +33 -3
  154. package/test/spec/modules/tappxBidAdapter_spec.js +4 -0
  155. package/test/spec/modules/targetVideoBidAdapter_spec.js +96 -0
  156. package/test/spec/modules/trustxBidAdapter_spec.js +42 -0
  157. package/test/spec/modules/userId_spec.js +51 -0
  158. package/test/spec/modules/vidoomyBidAdapter_spec.js +32 -13
  159. package/test/spec/modules/visxBidAdapter_spec.js +121 -5
  160. package/test/spec/modules/weboramaRtdProvider_spec.js +408 -214
  161. package/test/spec/modules/yahoosspBidAdapter_spec.js +28 -1
  162. package/test/spec/modules/yieldlabBidAdapter_spec.js +81 -0
  163. package/test/spec/modules/yieldoneBidAdapter_spec.js +299 -53
  164. package/test/spec/modules/zeta_global_sspBidAdapter_spec.js +33 -1
  165. package/test/spec/unit/core/adapterManager_spec.js +24 -6
  166. package/test/spec/unit/core/targeting_spec.js +116 -0
  167. package/test/spec/utils_spec.js +38 -0
  168. package/wdio.conf.js +1 -1
package/.babelrc.js CHANGED
@@ -14,16 +14,7 @@ module.exports = {
14
14
  [
15
15
  useLocal('@babel/preset-env'),
16
16
  {
17
- "targets": {
18
- "browsers": [
19
- "chrome >= 75",
20
- "safari >=10",
21
- "edge >= 70",
22
- "ff >= 70",
23
- "ie >= 11",
24
- "ios >= 11"
25
- ]
26
- }
17
+ "useBuiltIns": "entry"
27
18
  }
28
19
  ]
29
20
  ],
package/README.md CHANGED
@@ -59,6 +59,8 @@ module.exports = {
59
59
  loader: 'babel-loader',
60
60
  // presets and plugins for Prebid.js must be manually specified separate from your other babel rule.
61
61
  // this can be accomplished by requiring prebid's .babelrc.js file (requires Babel 7 and Node v8.9.0+)
62
+ // as of Prebid 6, babelrc.js only targets modern browsers. One can change the targets and build for
63
+ // older browsers if they prefer, but integration tests on ie11 were removed in Prebid.js 6.0
62
64
  options: require('prebid.js/.babelrc.js')
63
65
  }
64
66
  }
@@ -272,7 +274,7 @@ As you make code changes, the bundles will be rebuilt and the page reloaded auto
272
274
 
273
275
  ## Contribute
274
276
 
275
- Many SSPs, bidders, and publishers have contributed to this project. [Hundreds of bidders](https://github.com/prebid/Prebid.js/tree/master/src/adapters) are supported by Prebid.js.
277
+ Many SSPs, bidders, and publishers have contributed to this project. [Hundreds of bidders](https://github.com/prebid/Prebid.js/tree/master/modules) are supported by Prebid.js.
276
278
 
277
279
  For guidelines, see [Contributing](./CONTRIBUTING.md).
278
280
 
@@ -314,7 +316,7 @@ For instructions on writing tests for Prebid.js, see [Testing Prebid.js](http://
314
316
 
315
317
  ### Supported Browsers
316
318
 
317
- Prebid.js is supported on IE11 and modern browsers.
319
+ Prebid.js is supported on IE11 and modern browsers until 5.x. 6.x+ transpiles to target >0.25%; not Opera Mini; not IE11.
318
320
 
319
321
  ### Governance
320
322
  Review our governance model [here](https://github.com/prebid/Prebid.js/tree/master/governance.md).
package/browsers.json CHANGED
@@ -1,73 +1,49 @@
1
1
  {
2
- "bs_edge_17_windows_10": {
2
+ "bs_edge_latest_windows_10": {
3
3
  "base": "BrowserStack",
4
4
  "os_version": "10",
5
5
  "browser": "edge",
6
- "browser_version": "17.0",
6
+ "browser_version": "latest",
7
7
  "device": null,
8
8
  "os": "Windows"
9
9
  },
10
- "bs_edge_90_windows_10": {
11
- "base": "BrowserStack",
12
- "os_version": "10",
13
- "browser": "edge",
14
- "browser_version": "90.0",
15
- "device": null,
16
- "os": "Windows"
17
- },
18
- "bs_ie_11_windows_10": {
19
- "base": "BrowserStack",
20
- "os_version": "10",
21
- "browser": "ie",
22
- "browser_version": "11.0",
23
- "device": null,
24
- "os": "Windows"
25
- },
26
- "bs_chrome_90_windows_10": {
10
+ "bs_chrome_latest_windows_10": {
27
11
  "base": "BrowserStack",
28
12
  "os_version": "10",
29
13
  "browser": "chrome",
30
- "browser_version": "90.0",
14
+ "browser_version": "latest",
31
15
  "device": null,
32
16
  "os": "Windows"
33
17
  },
34
- "bs_chrome_79_windows_10": {
18
+ "bs_chrome_87_windows_10": {
35
19
  "base": "BrowserStack",
36
20
  "os_version": "10",
37
21
  "browser": "chrome",
38
- "browser_version": "79.0",
39
- "device": null,
40
- "os": "Windows"
41
- },
42
- "bs_firefox_88_windows_10": {
43
- "base": "BrowserStack",
44
- "os_version": "10",
45
- "browser": "firefox",
46
- "browser_version": "88.0",
22
+ "browser_version": "87.0",
47
23
  "device": null,
48
24
  "os": "Windows"
49
25
  },
50
- "bs_firefox_72_windows_10": {
26
+ "bs_firefox_latest_windows_10": {
51
27
  "base": "BrowserStack",
52
28
  "os_version": "10",
53
29
  "browser": "firefox",
54
- "browser_version": "72.0",
30
+ "browser_version": "latest",
55
31
  "device": null,
56
32
  "os": "Windows"
57
33
  },
58
- "bs_safari_14_mac_bigsur": {
34
+ "bs_safari_latest_mac_bigsur": {
59
35
  "base": "BrowserStack",
60
36
  "os_version": "Big Sur",
61
37
  "browser": "safari",
62
- "browser_version": "14.0",
38
+ "browser_version": "latest",
63
39
  "device": null,
64
40
  "os": "OS X"
65
41
  },
66
- "bs_safari_12_mac_mojave": {
42
+ "bs_safari_15_catalina": {
67
43
  "base": "BrowserStack",
68
- "os_version": "Mojave",
44
+ "os_version": "Catalina",
69
45
  "browser": "safari",
70
- "browser_version": "12.0",
46
+ "browser_version": "13.1",
71
47
  "device": null,
72
48
  "os": "OS X"
73
49
  }
package/gulpfile.js CHANGED
@@ -76,6 +76,7 @@ function lint(done) {
76
76
  'modules/**/*.js',
77
77
  'test/**/*.js',
78
78
  'plugins/**/*.js',
79
+ '!plugins/**/node_modules/**',
79
80
  './*.js'
80
81
  ], { base: './' })
81
82
  .pipe(gulpif(argv.nolintfix, eslint(), eslint({ fix: true })))
@@ -140,12 +141,6 @@ function watch(done) {
140
141
  done();
141
142
  };
142
143
 
143
- function makeModuleList(modules) {
144
- return modules.map(module => {
145
- return '"' + module + '"'
146
- });
147
- }
148
-
149
144
  function makeDevpackPkg() {
150
145
  var cloned = _.cloneDeep(webpackConfig);
151
146
  cloned.devtool = 'source-map';
@@ -157,7 +152,6 @@ function makeDevpackPkg() {
157
152
  return gulp.src([].concat(moduleSources, analyticsSources, 'src/prebid.js'))
158
153
  .pipe(helpers.nameModules(externalModules))
159
154
  .pipe(webpackStream(cloned, webpack))
160
- .pipe(replace(/('|")v\$prebid\.modulesList\$('|")/g, makeModuleList(externalModules)))
161
155
  .pipe(gulp.dest('build/dev'))
162
156
  .pipe(connect.reload());
163
157
  }
@@ -175,7 +169,6 @@ function makeWebpackPkg() {
175
169
  .pipe(helpers.nameModules(externalModules))
176
170
  .pipe(webpackStream(cloned, webpack))
177
171
  .pipe(terser())
178
- .pipe(replace(/('|")v\$prebid\.modulesList\$('|")/g, makeModuleList(externalModules)))
179
172
  .pipe(gulpif(file => file.basename === 'prebid-core.js', header(banner, { prebid: prebid })))
180
173
  .pipe(gulp.dest('build/dist'));
181
174
  }
@@ -17,22 +17,31 @@
17
17
  debug: true,
18
18
  realTimeData: {
19
19
  auctionDelay: 1000,
20
- dataProviders: [
21
- {
20
+ dataProviders: [{
22
21
  name: "weborama",
23
22
  waitForIt: true,
24
23
  params: {
25
- weboCtxConf: {
26
- setTargeting: true,
27
- token: "to-be-defined",
28
- targetURL: "https://prebid.org/",
29
- defaultProfile: {
30
- webo_ctx: ['moon']
31
- }
32
- }
33
- }
34
- }
35
- ]
24
+ weboCtxConf: {
25
+ token: "to-be-defined", // mandatory
26
+ targetURL: "https://prebid.org", // default is document.URL
27
+ setPrebidTargeting: true, // default
28
+ sendToBidders: true, // default
29
+ defaultProfile: { // optional
30
+ webo_ctx: ['moon'],
31
+ webo_ds: ['bar']
32
+ }
33
+ },
34
+ weboUserDataConf: {
35
+ setPrebidTargeting: true, // default
36
+ sendToBidders: true, // default
37
+ defaultProfile: { // optional
38
+ webo_cs: ['Red'],
39
+ webo_audiences: ['bam']
40
+ },
41
+ localStorageProfileKey: 'webo_wam2gam_entry' // default
42
+ }
43
+ }
44
+ }]
36
45
  }
37
46
  });
38
47
  });
@@ -54,7 +63,7 @@
54
63
  }
55
64
  },
56
65
  bids: [{
57
- bidder: 'appnexus',
66
+ bidder: 'smartadserver',
58
67
  params: {
59
68
  placementId: 1
60
69
  }
@@ -166,7 +166,7 @@ module.exports = function(codeCoverage, browserstack, watchMode, file) {
166
166
  browserNoActivityTimeout: 3e5, // default 10000
167
167
  captureTimeout: 3e5, // default 60000,
168
168
  browserDisconnectTolerance: 3,
169
- concurrency: 5,
169
+ concurrency: 6,
170
170
 
171
171
  plugins: plugins
172
172
  }
@@ -1,11 +1,20 @@
1
1
  import { registerBidder } from '../src/adapters/bidderFactory.js';
2
2
  import { config } from '../src/config.js';
3
3
  import {
4
- deepAccess, uniques, isArray, getWindowTop, isGptPubadsDefined, isSlotMatchingAdUnitCode, logInfo, logWarn,
5
- getWindowSelf
4
+ deepAccess,
5
+ uniques,
6
+ isArray,
7
+ getWindowTop,
8
+ isGptPubadsDefined,
9
+ isSlotMatchingAdUnitCode,
10
+ logInfo,
11
+ logWarn,
12
+ getWindowSelf,
13
+ mergeDeep,
6
14
  } from '../src/utils.js';
7
- import {BANNER, VIDEO} from '../src/mediaTypes.js';
15
+ import { BANNER, VIDEO } from '../src/mediaTypes.js';
8
16
 
17
+ // **************************** UTILS *************************** //
9
18
  const BIDDER_CODE = '33across';
10
19
  const END_POINT = 'https://ssc.33across.com/api/v1/hb';
11
20
  const SYNC_ENDPOINT = 'https://ssc-cms.33across.com/ps/?m=xch&rt=html&ru=deb';
@@ -42,6 +51,14 @@ const adapterState = {
42
51
 
43
52
  const NON_MEASURABLE = 'nm';
44
53
 
54
+ function getTTXConfig() {
55
+ const ttxSettings = Object.assign({},
56
+ config.getConfig('ttxSettings')
57
+ );
58
+
59
+ return ttxSettings;
60
+ }
61
+
45
62
  // **************************** VALIDATION *************************** //
46
63
  function isBidRequestValid(bid) {
47
64
  return (
@@ -74,6 +91,7 @@ function _validateGUID(bid) {
74
91
 
75
92
  function _validateBanner(bid) {
76
93
  const banner = deepAccess(bid, 'mediaTypes.banner');
94
+
77
95
  // If there's no banner no need to validate against banner rules
78
96
  if (banner === undefined) {
79
97
  return true;
@@ -140,91 +158,125 @@ function _validateVideo(bid) {
140
158
  // NOTE: With regards to gdrp consent data, the server will independently
141
159
  // infer the gdpr applicability therefore, setting the default value to false
142
160
  function buildRequests(bidRequests, bidderRequest) {
161
+ const {
162
+ ttxSettings,
163
+ gdprConsent,
164
+ uspConsent,
165
+ pageUrl
166
+ } = _buildRequestParams(bidRequests, bidderRequest);
167
+
168
+ const groupedRequests = _buildRequestGroups(ttxSettings, bidRequests);
169
+
170
+ const serverRequests = [];
171
+
172
+ for (const key in groupedRequests) {
173
+ serverRequests.push(
174
+ _createServerRequest({
175
+ bidRequests: groupedRequests[key],
176
+ gdprConsent,
177
+ uspConsent,
178
+ pageUrl,
179
+ ttxSettings
180
+ })
181
+ )
182
+ }
183
+
184
+ return serverRequests;
185
+ }
186
+
187
+ function _buildRequestParams(bidRequests, bidderRequest) {
188
+ const ttxSettings = getTTXConfig();
189
+
143
190
  const gdprConsent = Object.assign({
144
191
  consentString: undefined,
145
192
  gdprApplies: false
146
193
  }, bidderRequest && bidderRequest.gdprConsent);
147
194
 
148
195
  const uspConsent = bidderRequest && bidderRequest.uspConsent;
196
+
149
197
  const pageUrl = (bidderRequest && bidderRequest.refererInfo) ? (bidderRequest.refererInfo.referer) : (undefined);
150
198
 
151
199
  adapterState.uniqueSiteIds = bidRequests.map(req => req.params.siteId).filter(uniques);
152
200
 
153
- return bidRequests.map(bidRequest => _createServerRequest(
154
- {
155
- bidRequest,
156
- gdprConsent,
157
- uspConsent,
158
- pageUrl
159
- })
160
- );
201
+ return {
202
+ ttxSettings,
203
+ gdprConsent,
204
+ uspConsent,
205
+ pageUrl
206
+ }
207
+ }
208
+
209
+ function _buildRequestGroups(ttxSettings, bidRequests) {
210
+ const bidRequestsComplete = bidRequests.map(_inferProduct);
211
+ const enableSRAMode = ttxSettings && ttxSettings.enableSRAMode;
212
+ const keyFunc = (enableSRAMode === true) ? _getSRAKey : _getMRAKey;
213
+
214
+ return _groupBidRequests(bidRequestsComplete, keyFunc);
215
+ }
216
+
217
+ function _groupBidRequests(bidRequests, keyFunc) {
218
+ const groupedRequests = {};
219
+
220
+ bidRequests.forEach((req) => {
221
+ const key = keyFunc(req);
222
+
223
+ groupedRequests[key] = groupedRequests[key] || [];
224
+ groupedRequests[key].push(req);
225
+ });
226
+
227
+ return groupedRequests;
228
+ }
229
+
230
+ function _getSRAKey(bidRequest) {
231
+ return `${bidRequest.params.siteId}:${bidRequest.params.productId}`;
232
+ }
233
+
234
+ function _getMRAKey(bidRequest) {
235
+ return `${bidRequest.bidId}`;
161
236
  }
162
237
 
163
238
  // Infer the necessary data from valid bid for a minimal ttxRequest and create HTTP request
164
- // NOTE: At this point, TTX only accepts request for a single impression
165
- function _createServerRequest({bidRequest, gdprConsent = {}, uspConsent, pageUrl}) {
239
+ function _createServerRequest({ bidRequests, gdprConsent = {}, uspConsent, pageUrl, ttxSettings }) {
166
240
  const ttxRequest = {};
167
- const params = bidRequest.params;
241
+ const { siteId, test } = bidRequests[0].params;
168
242
 
169
243
  /*
170
244
  * Infer data for the request payload
171
245
  */
172
- ttxRequest.imp = [{}];
246
+ ttxRequest.imp = [];
173
247
 
174
- if (deepAccess(bidRequest, 'mediaTypes.banner')) {
175
- ttxRequest.imp[0].banner = {
176
- ..._buildBannerORTB(bidRequest)
177
- }
178
- }
179
-
180
- if (deepAccess(bidRequest, 'mediaTypes.video')) {
181
- ttxRequest.imp[0].video = _buildVideoORTB(bidRequest);
182
- }
183
-
184
- ttxRequest.imp[0].ext = {
185
- ttx: {
186
- prod: _getProduct(bidRequest)
187
- }
188
- };
248
+ bidRequests.forEach((req) => {
249
+ ttxRequest.imp.push(_buildImpORTB(req));
250
+ });
189
251
 
190
- ttxRequest.site = { id: params.siteId };
252
+ ttxRequest.site = { id: siteId };
191
253
 
192
254
  if (pageUrl) {
193
255
  ttxRequest.site.page = pageUrl;
194
256
  }
195
257
 
196
- // Go ahead send the bidId in request to 33exchange so it's kept track of in the bid response and
197
- // therefore in ad targetting process
198
- ttxRequest.id = bidRequest.bidId;
258
+ ttxRequest.id = bidRequests[0].auctionId;
199
259
 
200
260
  if (gdprConsent.consentString) {
201
- ttxRequest.user = setExtension(
202
- ttxRequest.user,
203
- 'consent',
204
- gdprConsent.consentString
205
- )
261
+ ttxRequest.user = setExtensions(ttxRequest.user, {
262
+ 'consent': gdprConsent.consentString
263
+ });
206
264
  }
207
265
 
208
- if (Array.isArray(bidRequest.userIdAsEids) && bidRequest.userIdAsEids.length > 0) {
209
- ttxRequest.user = setExtension(
210
- ttxRequest.user,
211
- 'eids',
212
- bidRequest.userIdAsEids
213
- )
266
+ if (Array.isArray(bidRequests[0].userIdAsEids) && bidRequests[0].userIdAsEids.length > 0) {
267
+ ttxRequest.user = setExtensions(ttxRequest.user, {
268
+ 'eids': bidRequests[0].userIdAsEids
269
+ });
214
270
  }
215
271
 
216
- ttxRequest.regs = setExtension(
217
- ttxRequest.regs,
218
- 'gdpr',
219
- Number(gdprConsent.gdprApplies)
220
- );
272
+ ttxRequest.regs = setExtensions(ttxRequest.regs, {
273
+ 'gdpr': Number(gdprConsent.gdprApplies)
274
+ });
221
275
 
222
276
  if (uspConsent) {
223
- ttxRequest.regs = setExtension(
224
- ttxRequest.regs,
225
- 'us_privacy',
226
- uspConsent
227
- )
277
+ ttxRequest.regs = setExtensions(ttxRequest.regs, {
278
+ 'us_privacy': uspConsent
279
+ });
228
280
  }
229
281
 
230
282
  ttxRequest.ext = {
@@ -237,16 +289,14 @@ function _createServerRequest({bidRequest, gdprConsent = {}, uspConsent, pageUrl
237
289
  }
238
290
  };
239
291
 
240
- if (bidRequest.schain) {
241
- ttxRequest.source = setExtension(
242
- ttxRequest.source,
243
- 'schain',
244
- bidRequest.schain
245
- )
292
+ if (bidRequests[0].schain) {
293
+ ttxRequest.source = setExtensions(ttxRequest.source, {
294
+ 'schain': bidRequests[0].schain
295
+ });
246
296
  }
247
297
 
248
298
  // Finally, set the openRTB 'test' param if this is to be a test bid
249
- if (params.test === 1) {
299
+ if (test === 1) {
250
300
  ttxRequest.test = 1;
251
301
  }
252
302
 
@@ -259,8 +309,7 @@ function _createServerRequest({bidRequest, gdprConsent = {}, uspConsent, pageUrl
259
309
  };
260
310
 
261
311
  // Allow the ability to configure the HB endpoint for testing purposes.
262
- const ttxSettings = config.getConfig('ttxSettings');
263
- const url = (ttxSettings && ttxSettings.url) || `${END_POINT}?guid=${params.siteId}`;
312
+ const url = (ttxSettings && ttxSettings.url) || `${END_POINT}?guid=${siteId}`;
264
313
 
265
314
  // Return the server request
266
315
  return {
@@ -272,14 +321,36 @@ function _createServerRequest({bidRequest, gdprConsent = {}, uspConsent, pageUrl
272
321
  }
273
322
 
274
323
  // BUILD REQUESTS: SET EXTENSIONS
275
- function setExtension(obj = {}, key, value) {
276
- return Object.assign({}, obj, {
277
- ext: Object.assign({}, obj.ext, {
278
- [key]: value
279
- })
324
+ function setExtensions(obj = {}, extFields) {
325
+ return mergeDeep({}, obj, {
326
+ 'ext': extFields
280
327
  });
281
328
  }
282
329
 
330
+ // BUILD REQUESTS: IMP
331
+ function _buildImpORTB(bidRequest) {
332
+ const imp = {
333
+ id: bidRequest.bidId,
334
+ ext: {
335
+ ttx: {
336
+ prod: deepAccess(bidRequest, 'params.productId')
337
+ }
338
+ }
339
+ };
340
+
341
+ if (deepAccess(bidRequest, 'mediaTypes.banner')) {
342
+ imp.banner = {
343
+ ..._buildBannerORTB(bidRequest)
344
+ }
345
+ }
346
+
347
+ if (deepAccess(bidRequest, 'mediaTypes.video')) {
348
+ imp.video = _buildVideoORTB(bidRequest);
349
+ }
350
+
351
+ return imp;
352
+ }
353
+
283
354
  // BUILD REQUESTS: SIZE INFERENCE
284
355
  function _transformSizes(sizes) {
285
356
  if (isArray(sizes) && sizes.length === 2 && !isArray(sizes[0])) {
@@ -297,6 +368,14 @@ function _getSize(size) {
297
368
  }
298
369
 
299
370
  // BUILD REQUESTS: PRODUCT INFERENCE
371
+ function _inferProduct(bidRequest) {
372
+ return mergeDeep({}, bidRequest, {
373
+ params: {
374
+ productId: _getProduct(bidRequest)
375
+ }
376
+ });
377
+ }
378
+
300
379
  function _getProduct(bidRequest) {
301
380
  const { params, mediaTypes } = bidRequest;
302
381
 
@@ -367,7 +446,7 @@ function _buildVideoORTB(bidRequest) {
367
446
 
368
447
  const video = {}
369
448
 
370
- const {w, h} = _getSize(videoParams.playerSize[0]);
449
+ const { w, h } = _getSize(videoParams.playerSize[0]);
371
450
  video.w = w;
372
451
  video.h = h;
373
452
 
@@ -388,11 +467,11 @@ function _buildVideoORTB(bidRequest) {
388
467
  if (product === PRODUCT.INSTREAM) {
389
468
  video.startdelay = video.startdelay || 0;
390
469
  video.placement = 1;
391
- };
470
+ }
392
471
 
393
472
  // bidfloors
394
473
  if (typeof bidRequest.getFloor === 'function') {
395
- const bidfloors = _getBidFloors(bidRequest, {w: video.w, h: video.h}, VIDEO);
474
+ const bidfloors = _getBidFloors(bidRequest, { w: video.w, h: video.h }, VIDEO);
396
475
 
397
476
  if (bidfloors) {
398
477
  Object.assign(video, {
@@ -404,6 +483,7 @@ function _buildVideoORTB(bidRequest) {
404
483
  });
405
484
  }
406
485
  }
486
+
407
487
  return video;
408
488
  }
409
489
 
@@ -556,54 +636,61 @@ function _isIframe() {
556
636
  }
557
637
 
558
638
  // **************************** INTERPRET RESPONSE ******************************** //
559
- // NOTE: At this point, the response from 33exchange will only ever contain one bid
560
- // i.e. the highest bid
561
639
  function interpretResponse(serverResponse, bidRequest) {
562
- const bidResponses = [];
563
-
564
- // If there are bids, look at the first bid of the first seatbid (see NOTE above for assumption about ttx)
565
- if (serverResponse.body.seatbid.length > 0 && serverResponse.body.seatbid[0].bid.length > 0) {
566
- bidResponses.push(_createBidResponse(serverResponse.body));
567
- }
568
-
569
- return bidResponses;
640
+ const { seatbid, cur = 'USD' } = serverResponse.body;
641
+
642
+ if (!isArray(seatbid)) {
643
+ return [];
644
+ }
645
+
646
+ // Pick seats with valid bids and convert them into an Array of responses
647
+ // in format expected by Prebid Core
648
+ return seatbid
649
+ .filter((seat) => (
650
+ isArray(seat.bid) &&
651
+ seat.bid.length > 0
652
+ ))
653
+ .reduce((acc, seat) => {
654
+ return acc.concat(
655
+ seat.bid.map((bid) => _createBidResponse(bid, cur))
656
+ );
657
+ }, []);
570
658
  }
571
659
 
572
- // All this assumes that only one bid is ever returned by ttx
573
- function _createBidResponse(response) {
660
+ function _createBidResponse(bid, cur) {
574
661
  const isADomainPresent =
575
- response.seatbid[0].bid[0].adomain && response.seatbid[0].bid[0].adomain.length;
576
- const bid = {
577
- requestId: response.id,
662
+ bid.adomain && bid.adomain.length;
663
+ const bidResponse = {
664
+ requestId: bid.impid,
578
665
  bidderCode: BIDDER_CODE,
579
- cpm: response.seatbid[0].bid[0].price,
580
- width: response.seatbid[0].bid[0].w,
581
- height: response.seatbid[0].bid[0].h,
582
- ad: response.seatbid[0].bid[0].adm,
583
- ttl: response.seatbid[0].bid[0].ttl || 60,
584
- creativeId: response.seatbid[0].bid[0].crid,
585
- mediaType: deepAccess(response.seatbid[0].bid[0], 'ext.ttx.mediaType', BANNER),
586
- currency: response.cur,
666
+ cpm: bid.price,
667
+ width: bid.w,
668
+ height: bid.h,
669
+ ad: bid.adm,
670
+ ttl: bid.ttl || 60,
671
+ creativeId: bid.crid,
672
+ mediaType: deepAccess(bid, 'ext.ttx.mediaType', BANNER),
673
+ currency: cur,
587
674
  netRevenue: true
588
675
  }
589
676
 
590
677
  if (isADomainPresent) {
591
- bid.meta = {
592
- advertiserDomains: response.seatbid[0].bid[0].adomain
678
+ bidResponse.meta = {
679
+ advertiserDomains: bid.adomain
593
680
  };
594
681
  }
595
682
 
596
- if (bid.mediaType === VIDEO) {
597
- const vastType = deepAccess(response.seatbid[0].bid[0], 'ext.ttx.vastType', 'xml');
683
+ if (bidResponse.mediaType === VIDEO) {
684
+ const vastType = deepAccess(bid, 'ext.ttx.vastType', 'xml');
598
685
 
599
686
  if (vastType === 'xml') {
600
- bid.vastXml = bid.ad;
687
+ bidResponse.vastXml = bidResponse.ad;
601
688
  } else {
602
- bid.vastUrl = bid.ad;
689
+ bidResponse.vastUrl = bidResponse.ad;
603
690
  }
604
691
  }
605
692
 
606
- return bid;
693
+ return bidResponse;
607
694
  }
608
695
 
609
696
  // **************************** USER SYNC *************************** //
@@ -308,7 +308,7 @@ function getElementFromTopWindow(element, currentWindow) {
308
308
  function autoDetectAdUnitElementIdFromGpt(adUnitCode) {
309
309
  const autoDetectedAdUnit = getGptSlotInfoForAdUnitCode(adUnitCode);
310
310
 
311
- if (autoDetectedAdUnit && autoDetectedAdUnit.divId) {
311
+ if (autoDetectedAdUnit.divId) {
312
312
  return autoDetectedAdUnit.divId;
313
313
  }
314
314
  };
@@ -19,6 +19,7 @@ export const spec = {
19
19
  v: $$PREBID_GLOBAL$$.version,
20
20
  auctionId: false,
21
21
  pageId: false,
22
+ gdpr_applies: bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies ? bidderRequest.gdprConsent.gdprApplies : 'true',
22
23
  gdpr_consent: bidderRequest.gdprConsent && bidderRequest.gdprConsent.consentString ? bidderRequest.gdprConsent.consentString : '',
23
24
  referer: bidderRequest.refererInfo.referer,
24
25
  bids: [],