prebid.js 5.17.0 → 6.0.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 (145) hide show
  1. package/.babelrc.js +3 -6
  2. package/README.md +3 -1
  3. package/browsers.json +1 -8
  4. package/integrationExamples/gpt/akamaidap_segments_example.html +132 -0
  5. package/modules/.submodules.json +1 -0
  6. package/modules/adfBidAdapter.js +21 -16
  7. package/modules/adgenerationBidAdapter.js +28 -4
  8. package/modules/adkernelBidAdapter.js +2 -1
  9. package/modules/admixerBidAdapter.js +11 -0
  10. package/modules/adtelligentBidAdapter.js +2 -1
  11. package/modules/airgridRtdProvider.js +1 -1
  12. package/modules/akamaiDapRtdProvider.js +474 -0
  13. package/modules/akamaiDapRtdProvider.md +47 -0
  14. package/modules/aolBidAdapter.js +2 -1
  15. package/modules/appnexusBidAdapter.js +5 -3
  16. package/modules/atsAnalyticsAdapter.js +67 -46
  17. package/modules/atsAnalyticsAdapter.md +1 -0
  18. package/modules/betweenBidAdapter.js +20 -3
  19. package/modules/bliinkBidAdapter.js +58 -32
  20. package/modules/bliinkBidAdapter.md +29 -6
  21. package/modules/browsiRtdProvider.js +106 -18
  22. package/modules/cleanioRtdProvider.js +192 -0
  23. package/modules/cleanioRtdProvider.md +59 -0
  24. package/modules/codefuelBidAdapter.js +183 -0
  25. package/modules/codefuelBidAdapter.md +111 -0
  26. package/modules/connectIdSystem.js +104 -0
  27. package/modules/connectIdSystem.md +33 -0
  28. package/modules/cwireBidAdapter.js +272 -0
  29. package/modules/cwireBidAdapter.md +43 -0
  30. package/modules/deepintentBidAdapter.js +106 -9
  31. package/modules/deepintentBidAdapter.md +36 -1
  32. package/modules/deltaprojectsBidAdapter.js +252 -0
  33. package/modules/deltaprojectsBidAdapter.md +32 -0
  34. package/modules/dgkeywordRtdProvider.js +0 -1
  35. package/modules/engageyaBidAdapter.js +157 -0
  36. package/modules/gridBidAdapter.js +1 -0
  37. package/modules/gumgumBidAdapter.js +8 -0
  38. package/modules/inskinBidAdapter.js +7 -3
  39. package/modules/ixBidAdapter.js +8 -1
  40. package/modules/jixieBidAdapter.js +8 -2
  41. package/modules/justpremiumBidAdapter.js +6 -1
  42. package/modules/limelightDigitalBidAdapter.js +22 -2
  43. package/modules/livewrappedAnalyticsAdapter.js +53 -3
  44. package/modules/mediakeysBidAdapter.js +2 -1
  45. package/modules/multibid/index.js +3 -3
  46. package/modules/nativoBidAdapter.js +6 -2
  47. package/modules/nextMillenniumBidAdapter.js +12 -3
  48. package/modules/oguryBidAdapter.js +36 -7
  49. package/modules/openxBidAdapter.js +34 -22
  50. package/modules/operaadsBidAdapter.js +21 -1
  51. package/modules/otmBidAdapter.js +146 -0
  52. package/modules/otmBidAdapter.md +27 -26
  53. package/modules/outbrainBidAdapter.js +5 -0
  54. package/modules/pixfutureBidAdapter.js +24 -4
  55. package/modules/pixfutureBidAdapter.md +127 -0
  56. package/modules/playwireBidAdapter.md +61 -0
  57. package/modules/prebidServerBidAdapter/index.js +1 -1
  58. package/modules/proxistoreBidAdapter.js +4 -6
  59. package/modules/publinkIdSystem.js +11 -6
  60. package/modules/pubmaticBidAdapter.js +9 -0
  61. package/modules/pubmaticBidAdapter.md +1 -1
  62. package/modules/rtdModule/index.js +2 -2
  63. package/modules/sonobiBidAdapter.js +7 -0
  64. package/modules/sortableBidAdapter.js +1 -0
  65. package/modules/talkadsBidAdapter.js +129 -0
  66. package/modules/talkadsBidAdapter.md +60 -0
  67. package/modules/teadsBidAdapter.js +3 -0
  68. package/modules/tripleliftBidAdapter.js +22 -5
  69. package/modules/trustxBidAdapter.js +8 -6
  70. package/modules/undertoneBidAdapter.js +9 -5
  71. package/modules/undertoneBidAdapter.md +5 -1
  72. package/modules/unicornBidAdapter.js +3 -3
  73. package/modules/userId/eids.js +18 -0
  74. package/modules/userId/eids.md +7 -0
  75. package/modules/userId/userId.md +12 -0
  76. package/modules/ventesBidAdapter.js +370 -0
  77. package/modules/ventesBidAdapter.md +94 -0
  78. package/modules/videobyteBidAdapter.js +13 -6
  79. package/modules/videobyteBidAdapter.md +49 -0
  80. package/modules/visxBidAdapter.js +15 -22
  81. package/modules/yahoosspBidAdapter.js +637 -0
  82. package/modules/yahoosspBidAdapter.md +795 -0
  83. package/modules/yieldlabBidAdapter.js +48 -3
  84. package/modules/yieldlabBidAdapter.md +16 -1
  85. package/modules/yieldmoSyntheticInventoryModule.js +46 -0
  86. package/modules/yieldmoSyntheticInventoryModule.md +68 -0
  87. package/package.json +1 -1
  88. package/src/adapterManager.js +5 -0
  89. package/src/adapters/bidderFactory.js +4 -3
  90. package/src/auction.js +11 -11
  91. package/src/constants.json +1 -0
  92. package/src/secureCreatives.js +6 -7
  93. package/src/targeting.js +11 -9
  94. package/test/spec/modules/adfBidAdapter_spec.js +83 -29
  95. package/test/spec/modules/adgenerationBidAdapter_spec.js +121 -50
  96. package/test/spec/modules/adtelligentBidAdapter_spec.js +1 -0
  97. package/test/spec/modules/akamaiDapRtdProvider_spec.js +246 -0
  98. package/test/spec/modules/appnexusBidAdapter_spec.js +2 -1
  99. package/test/spec/modules/atsAnalyticsAdapter_spec.js +42 -9
  100. package/test/spec/modules/betweenBidAdapter_spec.js +41 -0
  101. package/test/spec/modules/bliinkBidAdapter_spec.js +87 -36
  102. package/test/spec/modules/browsiRtdProvider_spec.js +62 -7
  103. package/test/spec/modules/cleanioRtdProvider_spec.js +188 -0
  104. package/test/spec/modules/codefuelBidAdapter_spec.js +316 -0
  105. package/test/spec/modules/connectIdSystem_spec.js +189 -0
  106. package/test/spec/modules/cwireBidAdapter_spec.js +246 -0
  107. package/test/spec/modules/deepintentBidAdapter_spec.js +153 -3
  108. package/test/spec/modules/deltaprojectsBidAdapter_spec.js +399 -0
  109. package/test/spec/modules/engageyaBidAdapter_spec.js +286 -0
  110. package/test/spec/modules/gumgumBidAdapter_spec.js +5 -1
  111. package/test/spec/modules/ixBidAdapter_spec.js +13 -3
  112. package/test/spec/modules/jixieBidAdapter_spec.js +13 -11
  113. package/test/spec/modules/justpremiumBidAdapter_spec.js +9 -2
  114. package/test/spec/modules/limelightDigitalBidAdapter_spec.js +155 -1
  115. package/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +67 -12
  116. package/test/spec/modules/multibid_spec.js +31 -31
  117. package/test/spec/modules/nextMillenniumBidAdapter_spec.js +13 -1
  118. package/test/spec/modules/oguryBidAdapter_spec.js +125 -37
  119. package/test/spec/modules/openxBidAdapter_spec.js +85 -13
  120. package/test/spec/modules/operaadsBidAdapter_spec.js +38 -6
  121. package/test/spec/modules/otmBidAdapter_spec.js +67 -0
  122. package/test/spec/modules/outbrainBidAdapter_spec.js +18 -0
  123. package/test/spec/modules/publinkIdSystem_spec.js +6 -6
  124. package/test/spec/modules/pubmaticBidAdapter_spec.js +39 -1
  125. package/test/spec/modules/sonobiBidAdapter_spec.js +34 -1
  126. package/test/spec/modules/sortableBidAdapter_spec.js +11 -0
  127. package/test/spec/modules/talkadsBidAdapter_spec.js +231 -0
  128. package/test/spec/modules/teadsBidAdapter_spec.js +132 -0
  129. package/test/spec/modules/tripleliftBidAdapter_spec.js +128 -0
  130. package/test/spec/modules/trustxBidAdapter_spec.js +3 -3
  131. package/test/spec/modules/undertoneBidAdapter_spec.js +52 -0
  132. package/test/spec/modules/unicornBidAdapter_spec.js +4 -4
  133. package/test/spec/modules/ventesBidAdapter_spec.js +845 -0
  134. package/test/spec/modules/videobyteBidAdapter_spec.js +2 -2
  135. package/test/spec/modules/visxBidAdapter_spec.js +48 -4
  136. package/test/spec/modules/yahoosspBidAdapter_spec.js +1332 -0
  137. package/test/spec/modules/yieldlabBidAdapter_spec.js +65 -1
  138. package/test/spec/modules/yieldmoSyntheticInventoryModule_spec.js +89 -0
  139. package/test/spec/unit/core/adapterManager_spec.js +32 -0
  140. package/test/spec/unit/core/bidderFactory_spec.js +61 -1
  141. package/test/spec/unit/pbjs_api_spec.js +37 -2
  142. package/test/spec/unit/secureCreatives_spec.js +54 -25
  143. package/wdio.conf.js +1 -1
  144. package/modules/turktelekomBidAdapter.md +0 -49
  145. package/yarn.lock +0 -13122
@@ -3,6 +3,7 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'
3
3
  import find from 'core-js-pure/features/array/find.js'
4
4
  import { VIDEO, BANNER } from '../src/mediaTypes.js'
5
5
  import { Renderer } from '../src/Renderer.js'
6
+ import { config } from '../src/config.js';
6
7
 
7
8
  const ENDPOINT = 'https://ad.yieldlab.net'
8
9
  const BIDDER_CODE = 'yieldlab'
@@ -52,6 +53,11 @@ export const spec = {
52
53
  if (bid.schain && isPlainObject(bid.schain) && Array.isArray(bid.schain.nodes)) {
53
54
  query.schain = createSchainString(bid.schain)
54
55
  }
56
+
57
+ const iabContent = getContentObject(bid)
58
+ if (iabContent) {
59
+ query.iab_content = createIabContentString(iabContent)
60
+ }
55
61
  })
56
62
 
57
63
  if (bidderRequest) {
@@ -105,6 +111,7 @@ export const spec = {
105
111
  const gdprApplies = reqParams.gdpr ? '&gdpr=' + reqParams.gdpr : ''
106
112
  const gdprConsent = reqParams.consent ? '&consent=' + reqParams.consent : ''
107
113
  const pvId = matchedBid.pvid !== undefined ? '&pvid=' + matchedBid.pvid : ''
114
+ const iabContent = reqParams.iab_content ? '&iab_content=' + reqParams.iab_content : ''
108
115
 
109
116
  const bidResponse = {
110
117
  requestId: bidRequest.bidId,
@@ -117,7 +124,7 @@ export const spec = {
117
124
  netRevenue: false,
118
125
  ttl: BID_RESPONSE_TTL_SEC,
119
126
  referrer: '',
120
- ad: `<script src="${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.supplyId}/?ts=${timestamp}${extId}${gdprApplies}${gdprConsent}${pvId}"></script>`,
127
+ ad: `<script src="${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.supplyId}/?ts=${timestamp}${extId}${gdprApplies}${gdprConsent}${pvId}${iabContent}"></script>`,
121
128
  meta: {
122
129
  advertiserDomains: (matchedBid.advertiser) ? matchedBid.advertiser : 'n/a'
123
130
  }
@@ -130,7 +137,7 @@ export const spec = {
130
137
  bidResponse.height = playersize[1]
131
138
  }
132
139
  bidResponse.mediaType = VIDEO
133
- bidResponse.vastUrl = `${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.supplyId}/?ts=${timestamp}${extId}${gdprApplies}${gdprConsent}${pvId}`
140
+ bidResponse.vastUrl = `${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.supplyId}/?ts=${timestamp}${extId}${gdprApplies}${gdprConsent}${pvId}${iabContent}`
134
141
  if (isOutstream(bidRequest)) {
135
142
  const renderer = Renderer.install({
136
143
  id: bidRequest.bidId,
@@ -211,7 +218,7 @@ function createQueryString (obj) {
211
218
  for (var p in obj) {
212
219
  if (obj.hasOwnProperty(p)) {
213
220
  let val = obj[p]
214
- if (p !== 'schain') {
221
+ if (p !== 'schain' && p !== 'iab_content') {
215
222
  str.push(encodeURIComponent(p) + '=' + encodeURIComponent(val))
216
223
  } else {
217
224
  str.push(p + '=' + val)
@@ -253,6 +260,44 @@ function createSchainString (schain) {
253
260
  return `${ver},${complete}${nodesString}`
254
261
  }
255
262
 
263
+ /**
264
+ * Get content object from bid request
265
+ * First get content from bidder params;
266
+ * If not provided in bidder params, get from first party data under 'ortb2.site.content' or 'ortb2.app.content'
267
+ * @param {Object} bid
268
+ * @returns {Object}
269
+ */
270
+ function getContentObject(bid) {
271
+ if (bid.params.iabContent && isPlainObject(bid.params.iabContent)) {
272
+ return bid.params.iabContent
273
+ }
274
+
275
+ const globalContent = config.getConfig('ortb2.site') ? config.getConfig('ortb2.site.content')
276
+ : config.getConfig('ortb2.app.content')
277
+ if (globalContent && isPlainObject(globalContent)) {
278
+ return globalContent
279
+ }
280
+ return undefined
281
+ }
282
+
283
+ /**
284
+ * Creates a string for iab_content object
285
+ * @param {Object} iabContent
286
+ * @returns {String}
287
+ */
288
+ function createIabContentString(iabContent) {
289
+ const arrKeys = ['keywords', 'cat']
290
+ let str = []
291
+ for (let key in iabContent) {
292
+ if (iabContent.hasOwnProperty(key)) {
293
+ const value = (arrKeys.indexOf(key) !== -1 && Array.isArray(iabContent[key]))
294
+ ? iabContent[key].map(node => encodeURIComponent(node)).join('|') : encodeURIComponent(iabContent[key])
295
+ str.push(''.concat(key, ':', value))
296
+ }
297
+ }
298
+ return encodeURIComponent(str.join(','))
299
+ }
300
+
256
301
  /**
257
302
  * Encodes URI Component with exlamation mark included. Needed for schain object.
258
303
  * @param {String} str
@@ -25,7 +25,22 @@ Module that connects to Yieldlab's demand sources
25
25
  key1: "value1",
26
26
  key2: "value2"
27
27
  },
28
- extId: "abc"
28
+ extId: "abc",
29
+ iabContent: {
30
+ id: "some_id",
31
+ episode: "1",
32
+ title: "some title",
33
+ series: "some series",
34
+ season: "s1",
35
+ artist: "John Doe",
36
+ genre: "some genre",
37
+ isrc: "CC-XXX-YY-NNNNN",
38
+ url: "http://foo_url.de",
39
+ cat: ["IAB1-1", "IAB1-2", "IAB2-10"],
40
+ context: "7",
41
+ keywords: ["k1", "k2"],
42
+ live: "0"
43
+ }
29
44
  }
30
45
  }]
31
46
  }, {
@@ -0,0 +1,46 @@
1
+ import { config } from '../src/config.js';
2
+ import { isGptPubadsDefined } from '../src/utils.js';
3
+
4
+ export const MODULE_NAME = 'Yieldmo Synthetic Inventory Module';
5
+
6
+ export function init(config) {
7
+ validateConfig(config);
8
+
9
+ if (!isGptPubadsDefined()) {
10
+ window.googletag = window.googletag || {};
11
+ window.googletag.cmd = window.googletag.cmd || [];
12
+ }
13
+
14
+ const googletag = window.googletag;
15
+ const containerName = 'ym_sim_container_' + config.placementId;
16
+
17
+ googletag.cmd.push(() => {
18
+ if (window.document.body) {
19
+ googletagCmd(config, containerName, googletag);
20
+ } else {
21
+ window.document.addEventListener('DOMContentLoaded', () => googletagCmd(config, containerName, googletag));
22
+ }
23
+ });
24
+ }
25
+
26
+ export function validateConfig(config) {
27
+ if (!('placementId' in config)) {
28
+ throw new Error(`${MODULE_NAME}: placementId required`);
29
+ }
30
+ if (!('adUnitPath' in config)) {
31
+ throw new Error(`${MODULE_NAME}: adUnitPath required`);
32
+ }
33
+ }
34
+
35
+ function googletagCmd(config, containerName, googletag) {
36
+ const gamContainer = window.document.createElement('div');
37
+ gamContainer.id = containerName;
38
+ window.document.body.appendChild(gamContainer);
39
+ googletag.defineSlot(config.adUnitPath, [1, 1], containerName)
40
+ .addService(googletag.pubads())
41
+ .setTargeting('ym_sim_p_id', config.placementId);
42
+ googletag.enableServices();
43
+ googletag.display(containerName);
44
+ }
45
+
46
+ config.getConfig('yieldmo_synthetic_inventory', config => init(config.yieldmo_synthetic_inventory));
@@ -0,0 +1,68 @@
1
+ # Yieldmo Synthetic Inventory Module
2
+
3
+ ## Overview
4
+
5
+ This module enables publishers to set up Yieldmo Synthetic Outstream ads on their pages.
6
+
7
+ If publishers will enable this module and provide placementId and Google Ad Manager ad unit path, this module will create a placement on the page and inject Yieldmo SDK into this placement. Publisher will then need to get a placement id from their Yieldmo account manager (accounts email) and setup corresponding ad units on the GAM ad server.
8
+
9
+ ## Integration
10
+
11
+ Build the Yieldmo Synthetic Inventory Module into the Prebid.js package with:
12
+
13
+ ```
14
+ gulp build --modules=yieldmoSyntheticInventoryModule,...
15
+ ```
16
+
17
+ ## Module Configuration
18
+
19
+ ```js
20
+ pbjs.que.push(function() {
21
+ pbjs.setConfig({
22
+ yieldmo_synthetic_inventory: {
23
+ placementId: '1234567890',
24
+ adUnitPath: '/1234567/ad_unit_name_used_in_gam'
25
+ }
26
+ });
27
+ });
28
+ ```
29
+
30
+ ### Configuration Parameters
31
+
32
+ |Name |Scope |Description | Example| Type
33
+ | :------------ | :------------ | :------------ | :------------ | :------------ |
34
+ |placementId | required | Yieldmo placement ID | '1234567890' | string
35
+ |adUnitPath | required | Google Ad Manager ad unit path | '/6355419/ad_unit_name_used_in_gam' | string
36
+
37
+ ### How to get ad unit path
38
+
39
+ Ad unit path follows the format /network-code/[parent-ad-unit-code/.../]ad-unit-code, where:
40
+
41
+ - network-code is a unique identifier for the Ad Manager network the ad unit belongs to
42
+ - parent-ad-unit-code are the codes of all parent ad units (only applies to non-top level ad units)
43
+ - ad-unit-code is the code for the ad unit to be displayed
44
+
45
+ Note that all ad unit codes included in the ad unit path must adhere to the [formatting rules](https://support.google.com/admanager/answer/1628457#ad-unit-codes) specified by Ad Manager.
46
+
47
+ Another and probably the easiest way to get an ad unit path is to get it from the google ad manager ad unit document header generated tag:
48
+
49
+ ```js
50
+ googletag.defineSlot('/1234567/ad_unit_name_used_in_gam', [1, 1], 'ad-container-id').addService(googletag.pubads());
51
+ ```
52
+
53
+ ### How to get Yieldmo placement id
54
+
55
+ Please reach out to your Yieldmo account's person or email to support@yieldmo.com
56
+
57
+ ### Google Ad Manager setup
58
+
59
+ Yieldmo Synthetic Inventory Module is designed to be used along with Google Ad Manager. GAM should be set as usual, but there are a few requirements:
60
+
61
+ - Ad unit size should be 1x1
62
+ - Creative should NOT be served into a SafeFrame and also should have 1x1 size
63
+ - Synthetic Inventory Universal Tag should be used as 3rd party creative code
64
+ ### Synthetic Inventory Universal Tag
65
+
66
+ ```js
67
+ <div id="ym_%%PATTERN:ym_sim_p_id%%" class="ym"></div><script type="text/javascript">(function(e,t){if(t._ym===void 0){t._ym="";var m=e.createElement("script");m.type="text/javascript",m.async=!0,m.src="//static.yieldmo.com/ym."+Math.round(5*Math.random()/3)+".js",(e.getElementsByTagName("head")[0]||e.getElementsByTagName("body")[0]).appendChild(m)}else t._ym instanceof String||void 0===t._ym.chkPls||t._ym.chkPls()})(document,window);</script>
68
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prebid.js",
3
- "version": "5.17.0",
3
+ "version": "6.0.0",
4
4
  "description": "Header Bidding Management Library",
5
5
  "main": "src/prebid.js",
6
6
  "scripts": {
@@ -621,4 +621,9 @@ adapterManager.callBidViewableBidder = function(bidder, bid) {
621
621
  tryCallBidderMethod(bidder, 'onBidViewable', bid);
622
622
  };
623
623
 
624
+ adapterManager.callBidderError = function(bidder, error, bidderRequest) {
625
+ const param = { error, bidderRequest };
626
+ tryCallBidderMethod(bidder, 'onBidderError', param);
627
+ };
628
+
624
629
  export default adapterManager;
@@ -335,10 +335,11 @@ export function newBidder(spec) {
335
335
 
336
336
  // If the server responds with an error, there's not much we can do. Log it, and make sure to
337
337
  // call onResponse() so that we're one step closer to calling done().
338
- function onFailure(err) {
338
+ function onFailure(errorMessage, error) {
339
339
  onTimelyResponse(spec.code);
340
-
341
- logError(`Server call for ${spec.code} failed: ${err}. Continuing without bids.`);
340
+ adapterManager.callBidderError(spec.code, error, bidderRequest)
341
+ events.emit(CONSTANTS.EVENTS.BIDDER_ERROR, { error, bidderRequest });
342
+ logError(`Server call for ${spec.code} failed: ${errorMessage} ${error.status}. Continuing without bids.`);
342
343
  onResponse();
343
344
  }
344
345
  }
package/src/auction.js CHANGED
@@ -613,7 +613,8 @@ export const getPriceGranularity = (mediaType, bidReq) => {
613
613
  * @returns {function}
614
614
  */
615
615
  export const getPriceByGranularity = (granularity) => {
616
- return (bid) => {
616
+ return (bid, bidReq) => {
617
+ granularity = granularity || getPriceGranularity(bid.mediaType, bidReq);
617
618
  if (granularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) {
618
619
  return bid.pbAg;
619
620
  } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) {
@@ -646,14 +647,14 @@ export const getAdvertiserDomain = () => {
646
647
  * @param {BidRequest} bidReq
647
648
  * @returns {*}
648
649
  */
649
- export function getStandardBidderSettings(mediaType, bidderCode, bidReq) {
650
+ export function getStandardBidderSettings(mediaType, bidderCode) {
650
651
  // factory for key value objs
651
652
  function createKeyVal(key, value) {
652
653
  return {
653
654
  key,
654
655
  val: (typeof value === 'function')
655
- ? function (bidResponse) {
656
- return value(bidResponse);
656
+ ? function (bidResponse, bidReq) {
657
+ return value(bidResponse, bidReq);
657
658
  }
658
659
  : function (bidResponse) {
659
660
  return getValue(bidResponse, value);
@@ -661,7 +662,6 @@ export function getStandardBidderSettings(mediaType, bidderCode, bidReq) {
661
662
  };
662
663
  }
663
664
  const TARGETING_KEYS = CONSTANTS.TARGETING_KEYS;
664
- const granularity = getPriceGranularity(mediaType, bidReq);
665
665
 
666
666
  let bidderSettings = $$PREBID_GLOBAL$$.bidderSettings;
667
667
  if (!bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]) {
@@ -671,7 +671,7 @@ export function getStandardBidderSettings(mediaType, bidderCode, bidReq) {
671
671
  bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING] = [
672
672
  createKeyVal(TARGETING_KEYS.BIDDER, 'bidderCode'),
673
673
  createKeyVal(TARGETING_KEYS.AD_ID, 'adId'),
674
- createKeyVal(TARGETING_KEYS.PRICE_BUCKET, getPriceByGranularity(granularity)),
674
+ createKeyVal(TARGETING_KEYS.PRICE_BUCKET, getPriceByGranularity()),
675
675
  createKeyVal(TARGETING_KEYS.SIZE, 'size'),
676
676
  createKeyVal(TARGETING_KEYS.DEAL, 'dealId'),
677
677
  createKeyVal(TARGETING_KEYS.SOURCE, 'source'),
@@ -716,12 +716,12 @@ export function getKeyValueTargetingPairs(bidderCode, custBidObj, bidReq) {
716
716
  // 1) set the keys from "standard" setting or from prebid defaults
717
717
  if (bidderSettings) {
718
718
  // initialize default if not set
719
- const standardSettings = getStandardBidderSettings(custBidObj.mediaType, bidderCode, bidReq);
720
- setKeys(keyValues, standardSettings, custBidObj);
719
+ const standardSettings = getStandardBidderSettings(custBidObj.mediaType, bidderCode);
720
+ setKeys(keyValues, standardSettings, custBidObj, bidReq);
721
721
 
722
722
  // 2) set keys from specific bidder setting override if they exist
723
723
  if (bidderCode && bidderSettings[bidderCode] && bidderSettings[bidderCode][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) {
724
- setKeys(keyValues, bidderSettings[bidderCode], custBidObj);
724
+ setKeys(keyValues, bidderSettings[bidderCode], custBidObj, bidReq);
725
725
  custBidObj.sendStandardTargeting = bidderSettings[bidderCode].sendStandardTargeting;
726
726
  }
727
727
  }
@@ -734,7 +734,7 @@ export function getKeyValueTargetingPairs(bidderCode, custBidObj, bidReq) {
734
734
  return keyValues;
735
735
  }
736
736
 
737
- function setKeys(keyValues, bidderSettings, custBidObj) {
737
+ function setKeys(keyValues, bidderSettings, custBidObj, bidReq) {
738
738
  var targeting = bidderSettings[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING];
739
739
  custBidObj.size = custBidObj.getSize();
740
740
 
@@ -748,7 +748,7 @@ function setKeys(keyValues, bidderSettings, custBidObj) {
748
748
 
749
749
  if (isFn(value)) {
750
750
  try {
751
- value = value(custBidObj);
751
+ value = value(custBidObj, bidReq);
752
752
  } catch (e) {
753
753
  logError('bidmanager', 'ERROR', e);
754
754
  }
@@ -32,6 +32,7 @@
32
32
  "NO_BID": "noBid",
33
33
  "BID_WON": "bidWon",
34
34
  "BIDDER_DONE": "bidderDone",
35
+ "BIDDER_ERROR": "bidderError",
35
36
  "SET_TARGETING": "setTargeting",
36
37
  "BEFORE_REQUEST_BIDS": "beforeRequestBids",
37
38
  "BEFORE_BIDDER_HTTP": "beforeBidderHttp",
@@ -60,7 +60,6 @@ export function receiveMessage(ev) {
60
60
  if (data.action === 'assetRequest') {
61
61
  const message = getAssetMessage(data, adObject);
62
62
  ev.source.postMessage(JSON.stringify(message), ev.origin);
63
- return;
64
63
  } else if (data.action === 'allAssetRequest') {
65
64
  const message = getAllAssetsMessage(data, adObject);
66
65
  ev.source.postMessage(JSON.stringify(message), ev.origin);
@@ -68,13 +67,13 @@ export function receiveMessage(ev) {
68
67
  adObject.height = data.height;
69
68
  adObject.width = data.width;
70
69
  resizeRemoteCreative(adObject);
71
- }
72
-
73
- const trackerType = fireNativeTrackers(data, adObject);
74
- if (trackerType === 'click') { return; }
70
+ } else {
71
+ const trackerType = fireNativeTrackers(data, adObject);
72
+ if (trackerType === 'click') { return; }
75
73
 
76
- auctionManager.addWinningBid(adObject);
77
- events.emit(BID_WON, adObject);
74
+ auctionManager.addWinningBid(adObject);
75
+ events.emit(BID_WON, adObject);
76
+ }
78
77
  }
79
78
  }
80
79
  }
package/src/targeting.js CHANGED
@@ -123,17 +123,19 @@ export function newTargeting(auctionManager) {
123
123
  if (isGptPubadsDefined()) {
124
124
  const adUnitCodes = getAdUnitCodes(adUnitCode);
125
125
  const adUnits = auctionManager.getAdUnits().filter(adUnit => includes(adUnitCodes, adUnit.code));
126
+ let unsetKeys = pbTargetingKeys.reduce((reducer, key) => {
127
+ reducer[key] = null;
128
+ return reducer;
129
+ }, {});
126
130
  window.googletag.pubads().getSlots().forEach(slot => {
127
131
  let customSlotMatchingFunc = isFn(customSlotMatching) && customSlotMatching(slot);
128
- pbTargetingKeys.forEach(function(key) {
129
- // reset only registered adunits
130
- adUnits.forEach(function(unit) {
131
- if (unit.code === slot.getAdUnitPath() ||
132
- unit.code === slot.getSlotElementId() ||
133
- (isFn(customSlotMatchingFunc) && customSlotMatchingFunc(unit.code))) {
134
- slot.setTargeting(key, null);
135
- }
136
- });
132
+ // reset only registered adunits
133
+ adUnits.forEach(unit => {
134
+ if (unit.code === slot.getAdUnitPath() ||
135
+ unit.code === slot.getSlotElementId() ||
136
+ (isFn(customSlotMatchingFunc) && customSlotMatchingFunc(unit.code))) {
137
+ slot.updateTargetingFromMap(unsetKeys);
138
+ }
137
139
  });
138
140
  });
139
141
  }
@@ -29,11 +29,34 @@ describe('Adf adapter', function () {
29
29
 
30
30
  it('should return true when required params found', function () {
31
31
  assert(spec.isBidRequestValid(bid));
32
+
33
+ bid.params = {
34
+ inv: 1234,
35
+ mname: 'some-placement'
36
+ };
37
+ assert(spec.isBidRequestValid(bid));
38
+
39
+ bid.params = {
40
+ mid: 4332,
41
+ inv: 1234,
42
+ mname: 'some-placement'
43
+ };
44
+ assert(spec.isBidRequestValid(bid));
32
45
  });
33
46
 
34
47
  it('should return false when required params are missing', function () {
35
48
  bid.params = { adxDomain: 'adx.adform.net' };
36
49
  assert.isFalse(spec.isBidRequestValid(bid));
50
+
51
+ bid.params = {
52
+ mname: 'some-placement'
53
+ };
54
+ assert.isFalse(spec.isBidRequestValid(bid));
55
+
56
+ bid.params = {
57
+ inv: 1234
58
+ };
59
+ assert.isFalse(spec.isBidRequestValid(bid));
37
60
  });
38
61
  });
39
62
 
@@ -331,6 +354,30 @@ describe('Adf adapter', function () {
331
354
  }
332
355
  });
333
356
 
357
+ describe('dynamic placement tag', function () {
358
+ it('should add imp parameters correctly', function () {
359
+ const validBidRequests = [
360
+ { bidId: 'bidId', params: { inv: 1000, mname: 'placement' }, mediaTypes: {video: {}} },
361
+ { bidId: 'bidId', params: { mid: 1234, inv: 1002, mname: 'placement2' }, mediaTypes: {video: {}} },
362
+ { bidId: 'bidId', params: { mid: 1234 }, mediaTypes: {video: {}} }
363
+ ];
364
+ const [ imp1, imp2, imp3 ] = getRequestImps(validBidRequests);
365
+
366
+ assert.equal(imp1.ext.bidder.inv, 1000);
367
+ assert.equal(imp1.ext.bidder.mname, 'placement');
368
+ assert.equal('tagid' in imp1, false);
369
+
370
+ assert.equal(imp2.ext.bidder.inv, 1002);
371
+ assert.equal(imp2.ext.bidder.mname, 'placement2');
372
+ assert.equal(imp2.tagid, 1234);
373
+
374
+ assert.ok(imp3.ext.bidder);
375
+ assert.equal('inv' in imp3.ext.bidder, false);
376
+ assert.equal('mname' in imp3.ext.bidder, false);
377
+ assert.equal(imp3.tagid, 1234);
378
+ });
379
+ });
380
+
334
381
  describe('price floors', function () {
335
382
  it('should not add if floors module not configured', function () {
336
383
  const validBidRequests = [{ bidId: 'bidId', params: {mid: 1000}, mediaTypes: {video: {}} }];
@@ -376,18 +423,14 @@ describe('Adf adapter', function () {
376
423
  return {
377
424
  currency: currency,
378
425
  floor
379
- }
426
+ };
380
427
  }
381
428
  };
382
429
  }
383
-
384
- function getRequestImps(validBidRequests) {
385
- return JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }).data).imp;
386
- }
387
430
  });
388
431
 
389
432
  describe('multiple media types', function () {
390
- it('should use single media type for bidding', function () {
433
+ it('should use all configured media types for bidding', function () {
391
434
  let validBidRequests = [{
392
435
  bidId: 'bidId',
393
436
  params: { mid: 1000 },
@@ -414,20 +457,23 @@ describe('Adf adapter', function () {
414
457
  banner: {
415
458
  sizes: [[100, 100], [200, 300]]
416
459
  },
417
- native: {}
460
+ native: {},
461
+ video: {}
418
462
  }
419
463
  }];
420
- let [ banner, video, native ] = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }).data).imp;
421
-
422
- assert.ok(banner.banner);
423
- assert.equal(banner.video, undefined);
424
- assert.equal(banner.native, undefined);
425
- assert.ok(video.video);
426
- assert.equal(video.banner, undefined);
427
- assert.equal(video.native, undefined);
428
- assert.ok(native.native);
429
- assert.equal(native.video, undefined);
430
- assert.equal(native.banner, undefined);
464
+ let [ first, second, third ] = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }).data).imp;
465
+
466
+ assert.ok(first.banner);
467
+ assert.ok(first.video);
468
+ assert.equal(first.native, undefined);
469
+
470
+ assert.ok(second.video);
471
+ assert.equal(second.banner, undefined);
472
+ assert.equal(second.native, undefined);
473
+
474
+ assert.ok(third.native);
475
+ assert.ok(third.video);
476
+ assert.ok(third.banner);
431
477
  });
432
478
  });
433
479
 
@@ -626,6 +672,10 @@ describe('Adf adapter', function () {
626
672
  });
627
673
  });
628
674
  });
675
+
676
+ function getRequestImps(validBidRequests) {
677
+ return JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }).data).imp;
678
+ }
629
679
  });
630
680
 
631
681
  describe('interpretResponse', function () {
@@ -754,7 +804,12 @@ describe('Adf adapter', function () {
754
804
  imptrackers: ['imptrackers url1', 'imptrackers url2']
755
805
  },
756
806
  dealid: 'deal-id',
757
- adomain: [ 'demo.com' ]
807
+ adomain: [ 'demo.com' ],
808
+ ext: {
809
+ prebid: {
810
+ type: 'native'
811
+ }
812
+ }
758
813
  }
759
814
  ]
760
815
  }],
@@ -767,7 +822,6 @@ describe('Adf adapter', function () {
767
822
  {
768
823
  bidId: 'bidId1',
769
824
  params: { mid: 1000 },
770
- mediaType: 'native',
771
825
  nativeParams: {
772
826
  title: { required: true, len: 140 },
773
827
  image: { required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif'] },
@@ -899,7 +953,7 @@ describe('Adf adapter', function () {
899
953
  let serverResponse = {
900
954
  body: {
901
955
  seatbid: [{
902
- bid: [{ impid: '1', adm: '<banner>' }]
956
+ bid: [{ impid: '1', adm: '<banner>', ext: { prebid: { type: 'banner' } } }]
903
957
  }]
904
958
  }
905
959
  };
@@ -908,8 +962,7 @@ describe('Adf adapter', function () {
908
962
  bids: [
909
963
  {
910
964
  bidId: 'bidId1',
911
- params: { mid: 1000 },
912
- mediaType: 'banner'
965
+ params: { mid: 1000 }
913
966
  }
914
967
  ]
915
968
  };
@@ -917,6 +970,8 @@ describe('Adf adapter', function () {
917
970
  bids = spec.interpretResponse(serverResponse, bidRequest);
918
971
  assert.equal(bids.length, 1);
919
972
  assert.equal(bids[0].ad, '<banner>');
973
+ assert.equal(bids[0].mediaType, 'banner');
974
+ assert.equal(bids[0].meta.mediaType, 'banner');
920
975
  });
921
976
  });
922
977
 
@@ -925,7 +980,7 @@ describe('Adf adapter', function () {
925
980
  let serverResponse = {
926
981
  body: {
927
982
  seatbid: [{
928
- bid: [{ impid: '1', adm: '<vast>' }]
983
+ bid: [{ impid: '1', adm: '<vast>', ext: { prebid: { type: 'video' } } }]
929
984
  }]
930
985
  }
931
986
  };
@@ -934,8 +989,7 @@ describe('Adf adapter', function () {
934
989
  bids: [
935
990
  {
936
991
  bidId: 'bidId1',
937
- params: { mid: 1000 },
938
- mediaType: 'video'
992
+ params: { mid: 1000 }
939
993
  }
940
994
  ]
941
995
  };
@@ -943,13 +997,15 @@ describe('Adf adapter', function () {
943
997
  bids = spec.interpretResponse(serverResponse, bidRequest);
944
998
  assert.equal(bids.length, 1);
945
999
  assert.equal(bids[0].vastXml, '<vast>');
1000
+ assert.equal(bids[0].mediaType, 'video');
1001
+ assert.equal(bids[0].meta.mediaType, 'video');
946
1002
  });
947
1003
 
948
1004
  it('should add renderer for outstream bids', function () {
949
1005
  let serverResponse = {
950
1006
  body: {
951
1007
  seatbid: [{
952
- bid: [{ impid: '1', adm: '<vast>' }, { impid: '2', adm: '<vast>' }]
1008
+ bid: [{ impid: '1', adm: '<vast>', ext: { prebid: { type: 'video' } } }, { impid: '2', adm: '<vast>', ext: { prebid: { type: 'video' } } }]
953
1009
  }]
954
1010
  }
955
1011
  };
@@ -959,7 +1015,6 @@ describe('Adf adapter', function () {
959
1015
  {
960
1016
  bidId: 'bidId1',
961
1017
  params: { mid: 1000 },
962
- mediaType: 'video',
963
1018
  mediaTypes: {
964
1019
  video: {
965
1020
  context: 'outstream'
@@ -969,7 +1024,6 @@ describe('Adf adapter', function () {
969
1024
  {
970
1025
  bidId: 'bidId2',
971
1026
  params: { mid: 1000 },
972
- mediaType: 'video',
973
1027
  mediaTypes: {
974
1028
  video: {
975
1029
  constext: 'instream'