prebid.js 5.18.0 → 6.1.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 (150) hide show
  1. package/.babelrc.js +1 -10
  2. package/README.md +3 -1
  3. package/browsers.json +1 -8
  4. package/gulpfile.js +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/adheseBidAdapter.js +7 -2
  9. package/modules/adkernelBidAdapter.js +1 -0
  10. package/modules/adlivetechBidAdapter.md +61 -0
  11. package/modules/adomikAnalyticsAdapter.js +10 -4
  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/appnexusBidAdapter.js +9 -3
  17. package/modules/atsAnalyticsAdapter.js +67 -46
  18. package/modules/atsAnalyticsAdapter.md +1 -0
  19. package/modules/betweenBidAdapter.js +20 -3
  20. package/modules/browsiRtdProvider.js +106 -18
  21. package/modules/cleanioRtdProvider.js +192 -0
  22. package/modules/cleanioRtdProvider.md +59 -0
  23. package/modules/codefuelBidAdapter.js +181 -0
  24. package/modules/codefuelBidAdapter.md +111 -0
  25. package/modules/connectIdSystem.js +104 -0
  26. package/modules/connectIdSystem.md +33 -0
  27. package/modules/datablocksBidAdapter.js +3 -3
  28. package/modules/deepintentBidAdapter.js +107 -10
  29. package/modules/deepintentBidAdapter.md +36 -1
  30. package/modules/deltaprojectsBidAdapter.js +252 -0
  31. package/modules/deltaprojectsBidAdapter.md +32 -0
  32. package/modules/engageyaBidAdapter.js +171 -0
  33. package/modules/glimpseBidAdapter.js +31 -16
  34. package/modules/gptPreAuction.js +11 -5
  35. package/modules/gridBidAdapter.js +1 -0
  36. package/modules/gumgumBidAdapter.js +8 -0
  37. package/modules/id5IdSystem.md +6 -6
  38. package/modules/imRtdProvider.js +31 -0
  39. package/modules/inskinBidAdapter.js +7 -3
  40. package/modules/ixBidAdapter.js +174 -22
  41. package/modules/jixieBidAdapter.js +8 -2
  42. package/modules/justpremiumBidAdapter.js +6 -1
  43. package/modules/limelightDigitalBidAdapter.js +22 -2
  44. package/modules/livewrappedAnalyticsAdapter.js +49 -1
  45. package/modules/merkleIdSystem.js +5 -0
  46. package/modules/multibid/index.js +3 -3
  47. package/modules/nativoBidAdapter.js +32 -2
  48. package/modules/nextMillenniumBidAdapter.js +12 -3
  49. package/modules/oguryBidAdapter.js +16 -2
  50. package/modules/openxBidAdapter.js +40 -23
  51. package/modules/operaadsBidAdapter.js +21 -1
  52. package/modules/otmBidAdapter.js +146 -0
  53. package/modules/otmBidAdapter.md +27 -26
  54. package/modules/outbrainBidAdapter.js +5 -0
  55. package/modules/playwireBidAdapter.md +61 -0
  56. package/modules/prebidServerBidAdapter/index.js +3 -3
  57. package/modules/publinkIdSystem.js +11 -6
  58. package/modules/pubmaticBidAdapter.js +2 -0
  59. package/modules/rtdModule/index.js +2 -2
  60. package/modules/saambaaBidAdapter.js +420 -0
  61. package/modules/saambaaBidAdapter.md +65 -68
  62. package/modules/seedtagBidAdapter.js +6 -0
  63. package/modules/smaatoBidAdapter.js +6 -1
  64. package/modules/sonobiBidAdapter.js +7 -0
  65. package/modules/sortableBidAdapter.js +1 -0
  66. package/modules/sspBCBidAdapter.js +34 -3
  67. package/modules/teadsBidAdapter.js +3 -0
  68. package/modules/tripleliftBidAdapter.js +22 -5
  69. package/modules/trustxBidAdapter.js +18 -7
  70. package/modules/undertoneBidAdapter.js +9 -5
  71. package/modules/undertoneBidAdapter.md +5 -1
  72. package/modules/userId/eids.js +18 -0
  73. package/modules/userId/eids.md +7 -0
  74. package/modules/userId/userId.md +12 -0
  75. package/modules/ventesBidAdapter.js +370 -0
  76. package/modules/ventesBidAdapter.md +94 -0
  77. package/modules/videobyteBidAdapter.js +13 -6
  78. package/modules/videobyteBidAdapter.md +49 -0
  79. package/modules/vidoomyBidAdapter.js +51 -100
  80. package/modules/visxBidAdapter.js +1 -1
  81. package/modules/yahoosspBidAdapter.js +6 -6
  82. package/modules/yieldlabBidAdapter.js +41 -10
  83. package/modules/yieldlabBidAdapter.md +91 -48
  84. package/modules/yieldmoSyntheticInventoryModule.js +46 -0
  85. package/modules/yieldmoSyntheticInventoryModule.md +68 -0
  86. package/package.json +6 -1
  87. package/src/adapterManager.js +19 -8
  88. package/src/adapters/bidderFactory.js +4 -3
  89. package/src/auction.js +11 -11
  90. package/src/constants.json +1 -0
  91. package/src/secureCreatives.js +6 -7
  92. package/src/targeting.js +11 -9
  93. package/test/spec/modules/adfBidAdapter_spec.js +83 -29
  94. package/test/spec/modules/adheseBidAdapter_spec.js +27 -1
  95. package/test/spec/modules/adomikAnalyticsAdapter_spec.js +3 -1
  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 +16 -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/browsiRtdProvider_spec.js +62 -7
  102. package/test/spec/modules/cleanioRtdProvider_spec.js +188 -0
  103. package/test/spec/modules/codefuelBidAdapter_spec.js +316 -0
  104. package/test/spec/modules/connectIdSystem_spec.js +189 -0
  105. package/test/spec/modules/datablocksBidAdapter_spec.js +3 -3
  106. package/test/spec/modules/deepintentBidAdapter_spec.js +153 -3
  107. package/test/spec/modules/deltaprojectsBidAdapter_spec.js +399 -0
  108. package/test/spec/modules/engageyaBidAdapter_spec.js +422 -0
  109. package/test/spec/modules/eplanningBidAdapter_spec.js +8 -8
  110. package/test/spec/modules/glimpseBidAdapter_spec.js +33 -0
  111. package/test/spec/modules/gptPreAuction_spec.js +58 -4
  112. package/test/spec/modules/gumgumBidAdapter_spec.js +5 -1
  113. package/test/spec/modules/imRtdProvider_spec.js +25 -0
  114. package/test/spec/modules/ixBidAdapter_spec.js +298 -5
  115. package/test/spec/modules/jixieBidAdapter_spec.js +13 -11
  116. package/test/spec/modules/justpremiumBidAdapter_spec.js +9 -2
  117. package/test/spec/modules/konduitWrapper_spec.js +0 -1
  118. package/test/spec/modules/limelightDigitalBidAdapter_spec.js +155 -1
  119. package/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +52 -7
  120. package/test/spec/modules/merkleIdSystem_spec.js +18 -0
  121. package/test/spec/modules/multibid_spec.js +31 -31
  122. package/test/spec/modules/nativoBidAdapter_spec.js +35 -18
  123. package/test/spec/modules/nextMillenniumBidAdapter_spec.js +13 -1
  124. package/test/spec/modules/oguryBidAdapter_spec.js +66 -23
  125. package/test/spec/modules/openxBidAdapter_spec.js +90 -13
  126. package/test/spec/modules/operaadsBidAdapter_spec.js +38 -6
  127. package/test/spec/modules/otmBidAdapter_spec.js +67 -0
  128. package/test/spec/modules/outbrainBidAdapter_spec.js +18 -0
  129. package/test/spec/modules/prebidServerBidAdapter_spec.js +19 -2
  130. package/test/spec/modules/publinkIdSystem_spec.js +6 -6
  131. package/test/spec/modules/seedtagBidAdapter_spec.js +3 -0
  132. package/test/spec/modules/smaatoBidAdapter_spec.js +30 -0
  133. package/test/spec/modules/sonobiBidAdapter_spec.js +34 -1
  134. package/test/spec/modules/sortableBidAdapter_spec.js +11 -0
  135. package/test/spec/modules/sspBCBidAdapter_spec.js +33 -3
  136. package/test/spec/modules/teadsBidAdapter_spec.js +132 -0
  137. package/test/spec/modules/tripleliftBidAdapter_spec.js +128 -0
  138. package/test/spec/modules/trustxBidAdapter_spec.js +45 -3
  139. package/test/spec/modules/undertoneBidAdapter_spec.js +52 -0
  140. package/test/spec/modules/ventesBidAdapter_spec.js +845 -0
  141. package/test/spec/modules/videobyteBidAdapter_spec.js +2 -2
  142. package/test/spec/modules/vidoomyBidAdapter_spec.js +32 -13
  143. package/test/spec/modules/visxBidAdapter_spec.js +1 -1
  144. package/test/spec/modules/yieldlabBidAdapter_spec.js +81 -0
  145. package/test/spec/modules/yieldmoSyntheticInventoryModule_spec.js +89 -0
  146. package/test/spec/unit/core/adapterManager_spec.js +56 -6
  147. package/test/spec/unit/core/bidderFactory_spec.js +61 -1
  148. package/test/spec/unit/pbjs_api_spec.js +37 -2
  149. package/test/spec/unit/secureCreatives_spec.js +54 -25
  150. package/wdio.conf.js +1 -1
@@ -9,7 +9,17 @@ const ENDPOINT = `https://d.vidoomy.com/api/rtbserver/prebid/`;
9
9
  const BIDDER_CODE = 'vidoomy';
10
10
  const GVLID = 380;
11
11
 
12
- const COOKIE_SYNC_JSON = 'https://vpaid.vidoomy.com/sync/urls.json';
12
+ const COOKIE_SYNC_FALLBACK_URLS = [
13
+ 'https://x.bidswitch.net/sync?ssp=vidoomy',
14
+ 'https://ib.adnxs.com/getuid?https%3A%2F%2Fa-prebid.vidoomy.com%2Fsetuid%3Fbidder%3Dadnxs%26gdpr%3D{{GDPR}}%26gdpr_consent%3D{{GDPR_CONSENT}}%26uid%3D%24UID',
15
+ 'https://pixel-sync.sitescout.com/dmp/pixelSync?nid=120&redir=https%3A%2F%2Fa.vidoomy.com%2Fapi%2Frtbserver%2Fcookie%3Fi%3DCEN%26uid%3D%7BuserId%7D',
16
+ 'https://sync.1rx.io/usersync2/vidoomy?redir=https%3A%2F%2Fa.vidoomy.com%2Fapi%2Frtbserver%2Fcookie%3Fi%3DUN%26uid%3D%5BRX_UUID%5D',
17
+ 'https://rtb.openx.net/sync/prebid?gdpr={{GDPR}}&gdpr_consent={{GDPR_CONSENT}}&r=https%3A%2F%2Fa-prebid.vidoomy.com%2Fsetuid%3Fbidder%3Dopenx%26uid%3D$%7BUID%7D',
18
+ 'https://ads.pubmatic.com/AdServer/js/user_sync.html?gdpr={{GDPR}}&gdpr_consent={{GDPR_CONSENT}}&us_privacy=&predirect=https%3A%2F%2Fa-prebid.vidoomy.com%2Fsetuid%3Fbidder%3Dpubmatic%26gdpr%3D{{GDPR}}%26gdpr_consent%3D{{GDPR_CONSENT}}%26uid%3D',
19
+ 'https://cm.adform.net/cookie?redirect_url=https%3A%2F%2Fa-prebid.vidoomy.com%2Fsetuid%3Fbidder%3Dadf%26gdpr%3D{{GDPR}}%26gdpr_consent%3D{{GDPR_CONSENT}}%26uid%3D%24UID',
20
+ 'https://ups.analytics.yahoo.com/ups/58531/occ?gdpr={{GDPR}}&gdpr_consent={{GDPR_CONSENT}}',
21
+ 'https://ap.lijit.com/pixel?redir=https%3A%2F%2Fa-prebid.vidoomy.com%2Fsetuid%3Fbidder%3Dsovrn%26gdpr%3D{{GDPR}}%26gdpr_consent%3D{{GDPR_CONSENT}}%26uid%3D%24UID'
22
+ ];
13
23
 
14
24
  const isBidRequestValid = bid => {
15
25
  if (!bid.params) {
@@ -36,7 +46,7 @@ const isBidRequestValid = bid => {
36
46
  };
37
47
 
38
48
  const isBidResponseValid = bid => {
39
- if (!bid.requestId || !bid.cpm || !bid.ttl || !bid.currency) {
49
+ if (!bid || !bid.requestId || !bid.cpm || !bid.ttl || !bid.currency) {
40
50
  return false;
41
51
  }
42
52
  switch (bid.mediaType) {
@@ -67,35 +77,33 @@ const buildRequests = (validBidRequests, bidderRequest) => {
67
77
 
68
78
  const videoContext = deepAccess(bid, 'mediaTypes.video.context');
69
79
 
70
- const queryParams = [];
71
- queryParams.push(['id', bid.params.id]);
72
- queryParams.push(['adtype', adType]);
73
- queryParams.push(['w', w]);
74
- queryParams.push(['h', h]);
75
- queryParams.push(['pos', parseInt(bid.params.position) || 1]);
76
- queryParams.push(['ua', navigator.userAgent]);
77
- queryParams.push(['l', navigator.language && navigator.language.indexOf('-') !== -1 ? navigator.language.split('-')[0] : '']);
78
- queryParams.push(['dt', /Mobi/.test(navigator.userAgent) ? 2 : 1]);
79
- queryParams.push(['pid', bid.params.pid]);
80
- queryParams.push(['requestId', bid.bidId]);
81
- queryParams.push(['d', getDomainWithoutSubdomain(hostname)]);
82
- queryParams.push(['sp', encodeURIComponent(aElement.href)]);
80
+ const queryParams = {
81
+ id: bid.params.id,
82
+ adtype: adType,
83
+ w,
84
+ h,
85
+ pos: parseInt(bid.params.position) || 1,
86
+ ua: navigator.userAgent,
87
+ l: navigator.language && navigator.language.indexOf('-') !== -1 ? navigator.language.split('-')[0] : '',
88
+ dt: /Mobi/.test(navigator.userAgent) ? 2 : 1,
89
+ pid: bid.params.pid,
90
+ requestId: bid.bidId,
91
+ d: getDomainWithoutSubdomain(hostname),
92
+ sp: encodeURIComponent(aElement.href),
93
+ usp: bidderRequest.uspConsent || '',
94
+ coppa: !!config.getConfig('coppa'),
95
+ videoContext: videoContext || ''
96
+ };
97
+
83
98
  if (bidderRequest.gdprConsent) {
84
- queryParams.push(['gdpr', bidderRequest.gdprConsent.gdprApplies]);
85
- queryParams.push(['gdprcs', bidderRequest.gdprConsent.consentString]);
99
+ queryParams.gdpr = bidderRequest.gdprConsent.gdprApplies;
100
+ queryParams.gdprcs = bidderRequest.gdprConsent.consentString;
86
101
  }
87
- queryParams.push(['usp', bidderRequest.uspConsent || '']);
88
- queryParams.push(['coppa', !!config.getConfig('coppa')]);
89
-
90
- const rawQueryParams = queryParams.map(qp => qp.join('=')).join('&');
91
102
 
92
- cookieSync(bidderRequest)
93
-
94
- const url = `${ENDPOINT}?${rawQueryParams}`;
95
103
  return {
96
104
  method: 'GET',
97
- url: url,
98
- data: {videoContext}
105
+ url: ENDPOINT,
106
+ data: queryParams
99
107
  }
100
108
  });
101
109
  return serverRequests;
@@ -117,6 +125,7 @@ const render = (bid) => {
117
125
  const interpretResponse = (serverResponse, bidRequest) => {
118
126
  try {
119
127
  let responseBody = serverResponse.body;
128
+ if (!responseBody) return;
120
129
  if (responseBody.mediaType === 'video') {
121
130
  responseBody.ad = responseBody.vastUrl;
122
131
  const videoContext = bidRequest.data.videoContext;
@@ -185,6 +194,21 @@ const interpretResponse = (serverResponse, bidRequest) => {
185
194
  }
186
195
  };
187
196
 
197
+ function getUserSyncs (syncOptions, responses, gdprConsent, uspConsent) {
198
+ if (syncOptions.iframeEnabled || syncOptions.pixelEnabled) {
199
+ const pixelType = syncOptions.pixelEnabled ? 'image' : 'iframe';
200
+ const urls = deepAccess(responses, '0.body.pixels') || COOKIE_SYNC_FALLBACK_URLS;
201
+
202
+ return [].concat(urls).map(url => ({
203
+ type: pixelType,
204
+ url: url
205
+ .replace('{{GDPR}}', gdprConsent ? gdprConsent.gdprApplies : '0')
206
+ .replace('{{GDPR_CONSENT}}', gdprConsent ? encodeURIComponent(gdprConsent.consentString) : '')
207
+ .replace('{{USP_CONSENT}}', uspConsent ? encodeURIComponent(uspConsent) : '')
208
+ }));
209
+ }
210
+ };
211
+
188
212
  export const spec = {
189
213
  code: BIDDER_CODE,
190
214
  supportedMediaTypes: [BANNER, VIDEO],
@@ -192,84 +216,11 @@ export const spec = {
192
216
  buildRequests,
193
217
  interpretResponse,
194
218
  gvlid: GVLID,
219
+ getUserSyncs,
195
220
  };
196
221
 
197
222
  registerBidder(spec);
198
223
 
199
- let cookieSynced = false;
200
- function cookieSync(bidderRequest) {
201
- if (cookieSynced) return;
202
- const xhr = new XMLHttpRequest();
203
- xhr.open('GET', COOKIE_SYNC_JSON)
204
- xhr.addEventListener('load', function () {
205
- const macro = Macro({
206
- gpdr: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : '0',
207
- gpdr_consent: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : '',
208
- });
209
- JSON.parse(this.responseText).filter(Boolean).forEach(url => {
210
- firePixel(macro.replace(url))
211
- })
212
- })
213
- xhr.send()
214
- cookieSynced = true;
215
- }
216
-
217
- function firePixel(url) {
218
- const img = document.createElement('img');
219
- img.width = 1;
220
- img.height = 1;
221
- img.src = url;
222
- document.body.appendChild(img);
223
- setTimeout(() => {
224
- img.remove();
225
- }, 10000)
226
- }
227
-
228
- function normalizeKey (x) {
229
- return x.replace(/_/g, '').toLowerCase();
230
- }
231
-
232
- function Macro (obj) {
233
- const macros = {};
234
- for (const key in obj) {
235
- macros[normalizeKey(key)] = obj[key];
236
- }
237
-
238
- const set = (key, value) => {
239
- macros[normalizeKey(key)] = typeof value === 'function' ? value : String(value);
240
- };
241
-
242
- return {
243
- set,
244
- setAll (obj) {
245
- for (const key in obj) {
246
- macros[normalizeKey(key)] = set(obj[key]);
247
- }
248
- },
249
- replace (string, extraMacros = {}) {
250
- const allMacros = {
251
- ...macros,
252
- ...extraMacros,
253
- };
254
- const regexes = [
255
- /{{\s*([a-zA-Z0-9_]+)\s*}}/g,
256
- /\$\$\s*([a-zA-Z0-9_]+)\s*\$\$/g,
257
- /\[\s*([a-zA-Z0-9_]+)\s*\]/g,
258
- /\{\s*([a-zA-Z0-9_]+)\s*\}/g,
259
- ];
260
- regexes.forEach(regex => {
261
- string = string.replace(regex, (str, x) => {
262
- x = normalizeKey(x);
263
- let value = allMacros[x];
264
- value = typeof value === 'function' ? value(allMacros) : value;
265
- return !value && value !== 0 ? '' : value;
266
- });
267
- });
268
- return string;
269
- },
270
- };
271
- }
272
-
273
224
  function getDomainWithoutSubdomain (hostname) {
274
225
  const parts = hostname.split('.');
275
226
  const newParts = [];
@@ -203,7 +203,7 @@ export const spec = {
203
203
  },
204
204
  onTimeout: function(timeoutData) {
205
205
  // Call '/track/bid_timeout' with timeout data
206
- triggerPixel(buildUrl(TRACK_TIMEOUT_PATH) + '?data=' + JSON.stringify(timeoutData));
206
+ triggerPixel(buildUrl(TRACK_TIMEOUT_PATH) + '//' + JSON.stringify(timeoutData));
207
207
  }
208
208
  };
209
209
 
@@ -144,9 +144,9 @@ function getAdapterMode() {
144
144
 
145
145
  function getResponseFormat(bid) {
146
146
  const adm = bid.adm;
147
- if (adm.includes('o2playerSettings') || adm.includes('YAHOO.VideoPlatform.VideoPlayer') || adm.includes('AdPlacement')) {
147
+ if (adm.indexOf('o2playerSettings') !== -1 || adm.indexOf('YAHOO.VideoPlatform.VideoPlayer') !== -1 || adm.indexOf('AdPlacement') !== -1) {
148
148
  return BANNER;
149
- } else if (adm.includes('VAST')) {
149
+ } else if (adm.indexOf('VAST') !== -1) {
150
150
  return VIDEO;
151
151
  }
152
152
  };
@@ -188,23 +188,23 @@ function validateAppendObject(validationType, allowedKeys, inputObject, appendTo
188
188
  for (const objectKey in inputObject) {
189
189
  switch (validationType) {
190
190
  case 'string':
191
- if (allowedKeys.includes(objectKey) && isStr(inputObject[objectKey])) {
191
+ if (allowedKeys.indexOf(objectKey) !== -1 && isStr(inputObject[objectKey])) {
192
192
  outputObject[objectKey] = inputObject[objectKey];
193
193
  };
194
194
  break;
195
195
  case 'number':
196
- if (allowedKeys.includes(objectKey) && isNumber(inputObject[objectKey])) {
196
+ if (allowedKeys.indexOf(objectKey) !== -1 && isNumber(inputObject[objectKey])) {
197
197
  outputObject[objectKey] = inputObject[objectKey];
198
198
  };
199
199
  break;
200
200
 
201
201
  case 'array':
202
- if (allowedKeys.includes(objectKey) && isArray(inputObject[objectKey])) {
202
+ if (allowedKeys.indexOf(objectKey) !== -1 && isArray(inputObject[objectKey])) {
203
203
  outputObject[objectKey] = inputObject[objectKey];
204
204
  };
205
205
  break;
206
206
  case 'object':
207
- if (allowedKeys.includes(objectKey) && isPlainObject(inputObject[objectKey])) {
207
+ if (allowedKeys.indexOf(objectKey) !== -1 && isPlainObject(inputObject[objectKey])) {
208
208
  outputObject[objectKey] = inputObject[objectKey];
209
209
  };
210
210
  break;
@@ -1,7 +1,7 @@
1
1
  import { _each, isPlainObject, isArray, deepAccess } from '../src/utils.js';
2
2
  import { registerBidder } from '../src/adapters/bidderFactory.js'
3
3
  import find from 'core-js-pure/features/array/find.js'
4
- import { VIDEO, BANNER } from '../src/mediaTypes.js'
4
+ import { VIDEO, BANNER, NATIVE } from '../src/mediaTypes.js'
5
5
  import { Renderer } from '../src/Renderer.js'
6
6
  import { config } from '../src/config.js';
7
7
 
@@ -15,7 +15,7 @@ const GVLID = 70
15
15
  export const spec = {
16
16
  code: BIDDER_CODE,
17
17
  gvlid: GVLID,
18
- supportedMediaTypes: [VIDEO, BANNER],
18
+ supportedMediaTypes: [VIDEO, BANNER, NATIVE],
19
19
 
20
20
  isBidRequestValid: function (bid) {
21
21
  if (bid && bid.params && bid.params.adslotId && bid.params.supplyId) {
@@ -149,6 +149,27 @@ export const spec = {
149
149
  }
150
150
  }
151
151
 
152
+ if (isNative(bidRequest, adType)) {
153
+ const url = `${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.supplyId}/?ts=${timestamp}${extId}${gdprApplies}${gdprConsent}${pvId}`
154
+ bidResponse.adUrl = url
155
+ bidResponse.mediaType = NATIVE
156
+ const nativeImageAssetObj = find(matchedBid.native.assets, e => e.id === 2)
157
+ const nativeImageAsset = nativeImageAssetObj ? nativeImageAssetObj.img : {url: '', w: 0, h: 0};
158
+ const nativeTitleAsset = find(matchedBid.native.assets, e => e.id === 1)
159
+ const nativeBodyAsset = find(matchedBid.native.assets, e => e.id === 3)
160
+ bidResponse.native = {
161
+ title: nativeTitleAsset ? nativeTitleAsset.title.text : '',
162
+ body: nativeBodyAsset ? nativeBodyAsset.data.value : '',
163
+ image: {
164
+ url: nativeImageAsset.url,
165
+ width: nativeImageAsset.w,
166
+ height: nativeImageAsset.h,
167
+ },
168
+ clickUrl: matchedBid.native.link.url,
169
+ impressionTrackers: matchedBid.native.imptrackers,
170
+ };
171
+ }
172
+
152
173
  bidResponses.push(bidResponse)
153
174
  }
154
175
  })
@@ -162,16 +183,26 @@ export const spec = {
162
183
  * @param {String} adtype
163
184
  * @returns {Boolean}
164
185
  */
165
- function isVideo (format, adtype) {
186
+ function isVideo(format, adtype) {
166
187
  return deepAccess(format, 'mediaTypes.video') && adtype.toLowerCase() === 'video'
167
188
  }
168
189
 
190
+ /**
191
+ * Is this a native format?
192
+ * @param {Object} format
193
+ * @param {String} adtype
194
+ * @returns {Boolean}
195
+ */
196
+ function isNative(format, adtype) {
197
+ return deepAccess(format, 'mediaTypes.native') && adtype.toLowerCase() === 'native'
198
+ }
199
+
169
200
  /**
170
201
  * Is this an outstream context?
171
202
  * @param {Object} format
172
203
  * @returns {Boolean}
173
204
  */
174
- function isOutstream (format) {
205
+ function isOutstream(format) {
175
206
  let context = deepAccess(format, 'mediaTypes.video.context')
176
207
  return (context === 'outstream')
177
208
  }
@@ -181,7 +212,7 @@ function isOutstream (format) {
181
212
  * @param {Object} format
182
213
  * @returns {Array}
183
214
  */
184
- function getPlayerSize (format) {
215
+ function getPlayerSize(format) {
185
216
  let playerSize = deepAccess(format, 'mediaTypes.video.playerSize')
186
217
  return (playerSize && isArray(playerSize[0])) ? playerSize[0] : playerSize
187
218
  }
@@ -191,7 +222,7 @@ function getPlayerSize (format) {
191
222
  * @param {String} size
192
223
  * @returns {Array}
193
224
  */
194
- function parseSize (size) {
225
+ function parseSize(size) {
195
226
  return size.split('x').map(Number)
196
227
  }
197
228
 
@@ -200,7 +231,7 @@ function parseSize (size) {
200
231
  * @param {Array} eids
201
232
  * @returns {String}
202
233
  */
203
- function createUserIdString (eids) {
234
+ function createUserIdString(eids) {
204
235
  let str = []
205
236
  for (let i = 0; i < eids.length; i++) {
206
237
  str.push(eids[i].source + ':' + eids[i].uids[0].id)
@@ -213,7 +244,7 @@ function createUserIdString (eids) {
213
244
  * @param {Object} obj
214
245
  * @returns {String}
215
246
  */
216
- function createQueryString (obj) {
247
+ function createQueryString(obj) {
217
248
  let str = []
218
249
  for (var p in obj) {
219
250
  if (obj.hasOwnProperty(p)) {
@@ -233,7 +264,7 @@ function createQueryString (obj) {
233
264
  * @param {Object} obj
234
265
  * @returns {String}
235
266
  */
236
- function createTargetingString (obj) {
267
+ function createTargetingString(obj) {
237
268
  let str = []
238
269
  for (var p in obj) {
239
270
  if (obj.hasOwnProperty(p)) {
@@ -250,7 +281,7 @@ function createTargetingString (obj) {
250
281
  * @param {Object} schain
251
282
  * @returns {String}
252
283
  */
253
- function createSchainString (schain) {
284
+ function createSchainString(schain) {
254
285
  const ver = schain.ver || ''
255
286
  const complete = (schain.complete === 1 || schain.complete === 0) ? schain.complete : ''
256
287
  const keys = ['asi', 'sid', 'hp', 'rid', 'name', 'domain', 'ext']
@@ -11,53 +11,96 @@ Maintainer: solutions@yieldlab.de
11
11
  Module that connects to Yieldlab's demand sources
12
12
 
13
13
  # Test Parameters
14
+
15
+ ```javascript
16
+ const adUnits = [
17
+ {
18
+ code: 'banner',
19
+ sizes: [ [ 728, 90 ] ],
20
+ bids: [{
21
+ bidder: 'yieldlab',
22
+ params: {
23
+ adslotId: '5220336',
24
+ supplyId: '1381604',
25
+ targeting: {
26
+ key1: 'value1',
27
+ key2: 'value2'
28
+ },
29
+ extId: 'abc',
30
+ iabContent: {
31
+ id: 'some_id',
32
+ episode: '1',
33
+ title: 'some title',
34
+ series: 'some series',
35
+ season: 's1',
36
+ artist: 'John Doe',
37
+ genre: 'some genre',
38
+ isrc: 'CC-XXX-YY-NNNNN',
39
+ url: 'http://foo_url.de',
40
+ cat: [ 'IAB1-1', 'IAB1-2', 'IAB2-10' ],
41
+ context: '7',
42
+ keywords: ['k1', 'k2'],
43
+ live: '0'
44
+ }
45
+ }
46
+ }]
47
+ },
48
+ {
49
+ code: 'video',
50
+ sizes: [ [ 640, 480 ] ],
51
+ mediaTypes: {
52
+ video: {
53
+ context: 'instream' // or 'outstream'
54
+ }
55
+ },
56
+ bids: [{
57
+ bidder: 'yieldlab',
58
+ params: {
59
+ adslotId: '5220339',
60
+ supplyId: '1381604'
61
+ }
62
+ }]
63
+ },
64
+ {
65
+ code: 'native',
66
+ mediaTypes: {
67
+ native: {
68
+ // native config
69
+ }
70
+ },
71
+ bids: [{
72
+ bidder: 'yieldlab',
73
+ params: {
74
+ adslotId: '5220339',
75
+ supplyId: '1381604'
76
+ }
77
+ }]
78
+ }
79
+ ];
14
80
  ```
15
- var adUnits = [
16
- {
17
- code: "banner",
18
- sizes: [[728, 90]],
19
- bids: [{
20
- bidder: "yieldlab",
21
- params: {
22
- adslotId: "5220336",
23
- supplyId: "1381604",
24
- targeting: {
25
- key1: "value1",
26
- key2: "value2"
27
- },
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
- }
44
- }
45
- }]
46
- }, {
47
- code: "video",
48
- sizes: [[640, 480]],
49
- mediaTypes: {
50
- video: {
51
- context: "instream" // or "outstream"
52
- }
53
- },
54
- bids: [{
55
- bidder: "yieldlab",
56
- params: {
57
- adslotId: "5220339",
58
- supplyId: "1381604"
59
- }
60
- }]
61
- }
62
- ];
81
+
82
+ # Multi-Format Setup
83
+
84
+ A general overview of how to set up multi-format ads can be found in the offical Prebid.js docs. See: [show multi-format ads](https://docs.prebid.org/dev-docs/show-multi-format-ads.html)
85
+
86
+ When setting up multi-format ads with Yieldlab make sure to always add at least one eligible Adslot per given media type in the ad unit configuration.
87
+
88
+ ```javascript
89
+ const adUnit = {
90
+ code: 'multi-format-adslot',
91
+ mediaTypes: {
92
+ banner: {
93
+ sizes: [ [ 728, 90 ] ]
94
+ },
95
+ native: {
96
+ // native config
97
+ }
98
+ },
99
+ bids: [
100
+ // banner Adslot
101
+ { bidder: 'yieldlab', params: { adslotId: '1234', supplyId: '42' } },
102
+ // native Adslot
103
+ { bidder: 'yieldlab', params: { adslotId: '2345', supplyId: '42' } }
104
+ ]
105
+ };
63
106
  ```
@@ -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.18.0",
3
+ "version": "6.1.0",
4
4
  "description": "Header Bidding Management Library",
5
5
  "main": "src/prebid.js",
6
6
  "scripts": {
@@ -11,6 +11,11 @@
11
11
  "type": "git",
12
12
  "url": "https://github.com/prebid/Prebid.js.git"
13
13
  },
14
+ "browserslist": [
15
+ "> 0.25%",
16
+ "not IE 11",
17
+ "not op_mini all"
18
+ ],
14
19
  "keywords": [
15
20
  "advertising",
16
21
  "auction",