prebid.js 6.2.0 → 6.6.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 (169) hide show
  1. package/.circleci/config.yml +1 -1
  2. package/gulpfile.js +87 -82
  3. package/integrationExamples/gpt/weboramaRtdProvider_example.html +23 -14
  4. package/karma.conf.maker.js +1 -1
  5. package/modules/.submodules.json +2 -1
  6. package/modules/33acrossBidAdapter.js +189 -102
  7. package/modules/adagioBidAdapter.js +1 -1
  8. package/modules/addefendBidAdapter.js +1 -0
  9. package/modules/adkernelBidAdapter.js +148 -62
  10. package/modules/adlooxAdServerVideo.js +2 -2
  11. package/modules/adlooxAnalyticsAdapter.js +4 -4
  12. package/modules/admanBidAdapter.js +11 -4
  13. package/modules/admixerBidAdapter.js +1 -1
  14. package/modules/adnuntiusBidAdapter.js +3 -1
  15. package/modules/adomikAnalyticsAdapter.js +27 -9
  16. package/modules/adqueryIdSystem.js +103 -0
  17. package/modules/adqueryIdSystem.md +35 -0
  18. package/modules/adxcgBidAdapter.js +311 -359
  19. package/modules/adxcgBidAdapter.md +22 -21
  20. package/modules/adyoulikeBidAdapter.js +13 -9
  21. package/modules/aniviewBidAdapter.js +1 -1
  22. package/modules/appnexusBidAdapter.js +0 -1
  23. package/modules/beopBidAdapter.js +6 -4
  24. package/modules/bidViewability.js +3 -3
  25. package/modules/bidViewabilityIO.js +3 -3
  26. package/modules/bliinkBidAdapter.js +3 -2
  27. package/modules/colossussspBidAdapter.js +7 -0
  28. package/modules/compassBidAdapter.js +208 -0
  29. package/modules/compassBidAdapter.md +79 -0
  30. package/modules/consentManagement.js +7 -1
  31. package/modules/criteoBidAdapter.js +1 -1
  32. package/modules/criteoIdSystem.js +29 -7
  33. package/modules/currency.js +2 -2
  34. package/modules/cwireBidAdapter.js +3 -0
  35. package/modules/dailyhuntBidAdapter.js +435 -0
  36. package/modules/dailyhuntBidAdapter.md +4 -0
  37. package/modules/docereeBidAdapter.js +10 -1
  38. package/modules/docereeBidAdapter.md +2 -0
  39. package/modules/dspxBidAdapter.js +1 -1
  40. package/modules/engageyaBidAdapter.js +1 -1
  41. package/modules/feedadBidAdapter.js +2 -2
  42. package/modules/feedadBidAdapter.md +4 -2
  43. package/modules/futureads.md +48 -0
  44. package/modules/glimpseBidAdapter.js +82 -47
  45. package/modules/gptPreAuction.js +55 -7
  46. package/modules/gridBidAdapter.js +4 -3
  47. package/modules/gumgumBidAdapter.js +2 -2
  48. package/modules/idImportLibrary.js +45 -8
  49. package/modules/idImportLibrary.md +4 -0
  50. package/modules/improvedigitalBidAdapter.js +42 -4
  51. package/modules/instreamTracking.js +4 -4
  52. package/modules/invibesBidAdapter.js +49 -5
  53. package/modules/invibesBidAdapter.md +2 -1
  54. package/modules/ixBidAdapter.js +53 -18
  55. package/modules/kinessoIdSystem.js +1 -1
  56. package/modules/limelightDigitalBidAdapter.js +2 -1
  57. package/modules/livewrappedAnalyticsAdapter.js +3 -1
  58. package/modules/livewrappedBidAdapter.js +8 -2
  59. package/modules/loglyliftBidAdapter.js +79 -0
  60. package/modules/loglyliftBidAdapter.md +55 -0
  61. package/modules/lotamePanoramaIdSystem.js +80 -8
  62. package/modules/mediasquareBidAdapter.js +1 -9
  63. package/modules/nextMillenniumBidAdapter.js +39 -7
  64. package/modules/oguryBidAdapter.js +9 -2
  65. package/modules/onetagBidAdapter.js +4 -2
  66. package/modules/optimeraRtdProvider.js +8 -1
  67. package/modules/ozoneBidAdapter.js +21 -64
  68. package/modules/prebidServerBidAdapter/index.js +16 -12
  69. package/modules/proxistoreBidAdapter.js +0 -2
  70. package/modules/pubgeniusBidAdapter.js +1 -1
  71. package/modules/pubmaticAnalyticsAdapter.js +16 -0
  72. package/modules/pubxaiAnalyticsAdapter.js +17 -0
  73. package/modules/richaudienceBidAdapter.js +4 -4
  74. package/modules/riseBidAdapter.js +1 -1
  75. package/modules/rtbhouseBidAdapter.js +14 -4
  76. package/modules/rtdModule/index.js +49 -18
  77. package/modules/rubiconBidAdapter.js +31 -19
  78. package/modules/sharedIdSystem.js +27 -1
  79. package/modules/showheroes-bsBidAdapter.js +13 -2
  80. package/modules/tappxBidAdapter.js +8 -5
  81. package/modules/targetVideoBidAdapter.js +187 -0
  82. package/modules/targetVideoBidAdapter.md +34 -0
  83. package/modules/teadsBidAdapter.js +1 -2
  84. package/modules/telariaBidAdapter.js +2 -2
  85. package/modules/trustxBidAdapter.js +8 -16
  86. package/modules/userId/eids.js +7 -1
  87. package/modules/userId/userId.md +8 -0
  88. package/modules/vidoomyBidAdapter.js +16 -10
  89. package/modules/weboramaRtdProvider.js +288 -73
  90. package/modules/weboramaRtdProvider.md +27 -10
  91. package/modules/welectBidAdapter.js +106 -0
  92. package/modules/yahoosspBidAdapter.js +5 -1
  93. package/modules/yieldmoBidAdapter.js +23 -5
  94. package/modules/zetaSspBidAdapter.md +33 -1
  95. package/modules/zeta_global_sspAnalyticsAdapter.js +97 -0
  96. package/modules/zeta_global_sspAnalyticsAdapter.md +24 -0
  97. package/modules/zeta_global_sspBidAdapter.js +22 -1
  98. package/package.json +1 -1
  99. package/plugins/pbjsGlobals.js +28 -1
  100. package/src/auction.js +2 -2
  101. package/src/config.js +27 -3
  102. package/src/hook.js +5 -1
  103. package/src/prebid.js +21 -6
  104. package/src/targeting.js +22 -1
  105. package/src/utils.js +46 -8
  106. package/test/helpers/prebidGlobal.js +1 -0
  107. package/test/spec/config_spec.js +279 -0
  108. package/test/spec/modules/33acrossBidAdapter_spec.js +300 -78
  109. package/test/spec/modules/adlooxAnalyticsAdapter_spec.js +6 -6
  110. package/test/spec/modules/admanBidAdapter_spec.js +2 -2
  111. package/test/spec/modules/adnuntiusBidAdapter_spec.js +17 -0
  112. package/test/spec/modules/adomikAnalyticsAdapter_spec.js +9 -1
  113. package/test/spec/modules/adqueryIdSystem_spec.js +74 -0
  114. package/test/spec/modules/adxcgBidAdapter_spec.js +820 -571
  115. package/test/spec/modules/adyoulikeBidAdapter_spec.js +49 -0
  116. package/test/spec/modules/beopBidAdapter_spec.js +1 -1
  117. package/test/spec/modules/bidViewabilityIO_spec.js +2 -2
  118. package/test/spec/modules/bidViewability_spec.js +4 -4
  119. package/test/spec/modules/bliinkBidAdapter_spec.js +2 -0
  120. package/test/spec/modules/colossussspBidAdapter_spec.js +9 -0
  121. package/test/spec/modules/compassBidAdapter_spec.js +398 -0
  122. package/test/spec/modules/consentManagement_spec.js +20 -0
  123. package/test/spec/modules/criteoIdSystem_spec.js +6 -3
  124. package/test/spec/modules/cwireBidAdapter_spec.js +10 -8
  125. package/test/spec/modules/dailyhuntBidAdapter_spec.js +404 -0
  126. package/test/spec/modules/docereeBidAdapter_spec.js +9 -1
  127. package/test/spec/modules/eids_spec.js +15 -0
  128. package/test/spec/modules/feedadBidAdapter_spec.js +15 -0
  129. package/test/spec/modules/glimpseBidAdapter_spec.js +0 -18
  130. package/test/spec/modules/gptPreAuction_spec.js +177 -2
  131. package/test/spec/modules/idImportLibrary_spec.js +197 -10
  132. package/test/spec/modules/improvedigitalBidAdapter_spec.js +45 -1
  133. package/test/spec/modules/invibesBidAdapter_spec.js +119 -0
  134. package/test/spec/modules/ixBidAdapter_spec.js +112 -62
  135. package/test/spec/modules/limelightDigitalBidAdapter_spec.js +75 -17
  136. package/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +22 -0
  137. package/test/spec/modules/livewrappedBidAdapter_spec.js +31 -0
  138. package/test/spec/modules/loglyliftBidAdapter_spec.js +172 -0
  139. package/test/spec/modules/lotamePanoramaIdSystem_spec.js +227 -0
  140. package/test/spec/modules/mediasquareBidAdapter_spec.js +4 -4
  141. package/test/spec/modules/nextMillenniumBidAdapter_spec.js +26 -1
  142. package/test/spec/modules/oguryBidAdapter_spec.js +10 -2
  143. package/test/spec/modules/optimeraRtdProvider_spec.js +14 -1
  144. package/test/spec/modules/ozoneBidAdapter_spec.js +43 -31
  145. package/test/spec/modules/prebidServerBidAdapter_spec.js +43 -0
  146. package/test/spec/modules/pubgeniusBidAdapter_spec.js +3 -3
  147. package/test/spec/modules/pubmaticAnalyticsAdapter_spec.js +13 -1
  148. package/test/spec/modules/pubxaiAnalyticsAdapter_spec.js +11 -0
  149. package/test/spec/modules/realTimeDataModule_spec.js +147 -48
  150. package/test/spec/modules/richaudienceBidAdapter_spec.js +42 -2
  151. package/test/spec/modules/riseBidAdapter_spec.js +1 -1
  152. package/test/spec/modules/rtbhouseBidAdapter_spec.js +20 -0
  153. package/test/spec/modules/rubiconBidAdapter_spec.js +65 -9
  154. package/test/spec/modules/sharedIdSystem_spec.js +52 -6
  155. package/test/spec/modules/showheroes-bsBidAdapter_spec.js +2 -0
  156. package/test/spec/modules/tappxBidAdapter_spec.js +0 -19
  157. package/test/spec/modules/targetVideoBidAdapter_spec.js +96 -0
  158. package/test/spec/modules/teadsBidAdapter_spec.js +14 -59
  159. package/test/spec/modules/userId_spec.js +68 -19
  160. package/test/spec/modules/weboramaRtdProvider_spec.js +408 -214
  161. package/test/spec/modules/welectBidAdapter_spec.js +211 -0
  162. package/test/spec/modules/yahoosspBidAdapter_spec.js +28 -1
  163. package/test/spec/modules/zeta_global_sspAnalyticsAdapter_spec.js +427 -0
  164. package/test/spec/modules/zeta_global_sspBidAdapter_spec.js +33 -1
  165. package/test/spec/unit/core/targeting_spec.js +72 -0
  166. package/test/spec/unit/pbjs_api_spec.js +3 -1
  167. package/test/spec/utils_spec.js +38 -0
  168. package/test/test_deps.js +3 -0
  169. package/test/test_index.js +1 -3
@@ -40,28 +40,21 @@ export const spec = {
40
40
  * @returns {ServerRequest}
41
41
  */
42
42
  buildRequests: (validBidRequests, bidderRequest) => {
43
- const demo = config.getConfig('glimpse.demo') || false
44
- const account = config.getConfig('glimpse.account') || -1
45
- const demand = config.getConfig('glimpse.demand') || 'glimpse'
46
- const keywords = config.getConfig('glimpse.keywords') || {}
47
-
48
43
  const auth = getVaultJwt()
49
44
  const referer = getReferer(bidderRequest)
50
45
  const gdprConsent = getGdprConsentChoice(bidderRequest)
51
- const bids = validBidRequests.map((bidRequest) => {
52
- return processBidRequest(bidRequest, keywords)
53
- })
46
+ const bidRequests = validBidRequests.map(processBidRequest)
47
+ const firstPartyData = getFirstPartyData()
54
48
 
55
49
  const data = {
56
50
  auth,
57
51
  data: {
58
- bidderCode: spec.code,
59
- demo,
60
- account,
61
- demand,
62
52
  referer,
63
53
  gdprConsent,
64
- bids,
54
+ bidRequests,
55
+ site: firstPartyData.site,
56
+ user: firstPartyData.user,
57
+ bidderCode: spec.code,
65
58
  }
66
59
  }
67
60
 
@@ -91,35 +84,12 @@ export const spec = {
91
84
  },
92
85
  }
93
86
 
94
- function processBidRequest(bidRequest, globalKeywords) {
95
- const sizes = normalizeSizes(bidRequest.sizes)
96
- const bidKeywords = bidRequest.params.keywords || {}
97
- const keywords = {
98
- ...globalKeywords,
99
- ...bidKeywords,
100
- }
101
-
102
- return {
103
- unitCode: bidRequest.adUnitCode,
104
- bidId: bidRequest.bidId,
105
- placementId: bidRequest.params.placementId,
106
- keywords,
107
- sizes,
108
- }
87
+ function setVaultJwt(auth) {
88
+ storageManager.setDataInLocalStorage(LOCAL_STORAGE_KEY.vault.jwt, auth)
109
89
  }
110
90
 
111
- function normalizeSizes(sizes) {
112
- const isSingleSize =
113
- isArray(sizes) &&
114
- sizes.length === 2 &&
115
- !isArray(sizes[0]) &&
116
- !isArray(sizes[1])
117
-
118
- if (isSingleSize) {
119
- return [sizes]
120
- }
121
-
122
- return sizes
91
+ function getVaultJwt() {
92
+ return storageManager.getDataFromLocalStorage(LOCAL_STORAGE_KEY.vault.jwt) || ''
123
93
  }
124
94
 
125
95
  function getReferer(bidderRequest) {
@@ -138,11 +108,17 @@ function getReferer(bidderRequest) {
138
108
  function getGdprConsentChoice(bidderRequest) {
139
109
  const hasGdprConsent =
140
110
  hasValue(bidderRequest) &&
141
- hasValue(bidderRequest.gdprConsent) &&
142
- hasStringValue(bidderRequest.gdprConsent.consentString)
111
+ hasValue(bidderRequest.gdprConsent)
143
112
 
144
113
  if (hasGdprConsent) {
145
- return bidderRequest.gdprConsent
114
+ const gdprConsent = bidderRequest.gdprConsent
115
+ const hasGdprApplies = hasBooleanValue(gdprConsent.gdprApplies)
116
+
117
+ return {
118
+ consentString: gdprConsent.consentString || '',
119
+ vendorData: gdprConsent.vendorData || {},
120
+ gdprApplies: hasGdprApplies ? gdprConsent.gdprApplies : true,
121
+ }
146
122
  }
147
123
 
148
124
  return {
@@ -152,12 +128,64 @@ function getGdprConsentChoice(bidderRequest) {
152
128
  }
153
129
  }
154
130
 
155
- function setVaultJwt(auth) {
156
- storageManager.setDataInLocalStorage(LOCAL_STORAGE_KEY.vault.jwt, auth)
131
+ function processBidRequest(bidRequest) {
132
+ const demand = bidRequest.params.demand || 'glimpse'
133
+ const sizes = normalizeSizes(bidRequest.sizes)
134
+ const keywords = bidRequest.params.keywords || {}
135
+
136
+ return {
137
+ demand,
138
+ sizes,
139
+ keywords,
140
+ bidId: bidRequest.bidId,
141
+ placementId: bidRequest.params.placementId,
142
+ unitCode: bidRequest.adUnitCode,
143
+ }
157
144
  }
158
145
 
159
- function getVaultJwt() {
160
- return storageManager.getDataFromLocalStorage(LOCAL_STORAGE_KEY.vault.jwt) || ''
146
+ function normalizeSizes(sizes) {
147
+ const isSingleSize =
148
+ isArray(sizes) &&
149
+ sizes.length === 2 &&
150
+ !isArray(sizes[0]) &&
151
+ !isArray(sizes[1])
152
+
153
+ if (isSingleSize) {
154
+ return [sizes]
155
+ }
156
+
157
+ return sizes
158
+ }
159
+
160
+ function getFirstPartyData() {
161
+ const siteKeywords = parseGlobalKeywords('site')
162
+ const userKeywords = parseGlobalKeywords('user')
163
+
164
+ const siteAttributes = getConfig('ortb2.site.ext.data', {})
165
+ const userAttributes = getConfig('ortb2.user.ext.data', {})
166
+
167
+ return {
168
+ site: {
169
+ keywords: siteKeywords,
170
+ attributes: siteAttributes,
171
+ },
172
+ user: {
173
+ keywords: userKeywords,
174
+ attributes: userAttributes,
175
+ },
176
+ }
177
+ }
178
+
179
+ function parseGlobalKeywords(scope) {
180
+ const keywords = getConfig(`ortb2.${scope}.keywords`, '')
181
+
182
+ return keywords
183
+ .split(', ')
184
+ .filter((keyword) => keyword !== '')
185
+ }
186
+
187
+ function getConfig(path, defaultValue) {
188
+ return config.getConfig(path) || defaultValue
161
189
  }
162
190
 
163
191
  function isValidBidResponse(bidResponse) {
@@ -177,6 +205,13 @@ function hasValue(value) {
177
205
  )
178
206
  }
179
207
 
208
+ function hasBooleanValue(value) {
209
+ return (
210
+ hasValue(value) &&
211
+ typeof value === 'boolean'
212
+ )
213
+ }
214
+
180
215
  function hasStringValue(value) {
181
216
  return (
182
217
  hasValue(value) &&
@@ -48,10 +48,35 @@ const sanitizeSlotPath = (path) => {
48
48
  return path;
49
49
  }
50
50
 
51
+ const defaultPreAuction = (adUnit, adServerAdSlot) => {
52
+ const context = adUnit.ortb2Imp.ext.data;
53
+
54
+ // use pbadslot if supplied
55
+ if (context.pbadslot) {
56
+ return context.pbadslot;
57
+ }
58
+
59
+ // confirm that GPT is set up
60
+ if (!isGptPubadsDefined()) {
61
+ return;
62
+ }
63
+
64
+ // find all GPT slots with this name
65
+ var gptSlots = window.googletag.pubads().getSlots().filter(slot => slot.getAdUnitPath() === adServerAdSlot);
66
+
67
+ if (gptSlots.length === 0) {
68
+ return; // should never happen
69
+ }
70
+
71
+ if (gptSlots.length === 1) {
72
+ return adServerAdSlot;
73
+ }
74
+
75
+ // else the adunit code must be div id. append it.
76
+ return `${adServerAdSlot}#${adUnit.code}`;
77
+ }
78
+
51
79
  export const appendPbAdSlot = adUnit => {
52
- adUnit.ortb2Imp = adUnit.ortb2Imp || {};
53
- adUnit.ortb2Imp.ext = adUnit.ortb2Imp.ext || {};
54
- adUnit.ortb2Imp.ext.data = adUnit.ortb2Imp.ext.data || {};
55
80
  const context = adUnit.ortb2Imp.ext.data;
56
81
  const { customPbAdSlot } = _currentConfig;
57
82
 
@@ -84,11 +109,32 @@ export const appendPbAdSlot = adUnit => {
84
109
 
85
110
  export const makeBidRequestsHook = (fn, adUnits, ...args) => {
86
111
  appendGptSlots(adUnits);
112
+ const { useDefaultPreAuction, customPreAuction } = _currentConfig;
87
113
  adUnits.forEach(adUnit => {
88
- const usedAdUnitCode = appendPbAdSlot(adUnit);
89
- // gpid should be set to itself if already set, or to what pbadslot was (as long as it was not adUnit code)
90
- if (!adUnit.ortb2Imp.ext.gpid && !usedAdUnitCode) {
91
- adUnit.ortb2Imp.ext.gpid = adUnit.ortb2Imp.ext.data.pbadslot;
114
+ // init the ortb2Imp if not done yet
115
+ adUnit.ortb2Imp = adUnit.ortb2Imp || {};
116
+ adUnit.ortb2Imp.ext = adUnit.ortb2Imp.ext || {};
117
+ adUnit.ortb2Imp.ext.data = adUnit.ortb2Imp.ext.data || {};
118
+ const context = adUnit.ortb2Imp.ext;
119
+
120
+ // if neither new confs set do old stuff
121
+ if (!customPreAuction && !useDefaultPreAuction) {
122
+ const usedAdUnitCode = appendPbAdSlot(adUnit);
123
+ // gpid should be set to itself if already set, or to what pbadslot was (as long as it was not adUnit code)
124
+ if (!context.gpid && !usedAdUnitCode) {
125
+ context.gpid = context.data.pbadslot;
126
+ }
127
+ } else {
128
+ let adserverSlot = deepAccess(context, 'data.adserver.adslot');
129
+ let result;
130
+ if (customPreAuction) {
131
+ result = customPreAuction(adUnit, adserverSlot);
132
+ } else if (useDefaultPreAuction) {
133
+ result = defaultPreAuction(adUnit, adserverSlot);
134
+ }
135
+ if (result) {
136
+ context.gpid = context.data.pbadslot = result;
137
+ }
92
138
  }
93
139
  });
94
140
  return fn.call(this, adUnits, ...args);
@@ -100,6 +146,8 @@ const handleSetGptConfig = moduleConfig => {
100
146
  'customGptSlotMatching', customGptSlotMatching =>
101
147
  typeof customGptSlotMatching === 'function' && customGptSlotMatching,
102
148
  'customPbAdSlot', customPbAdSlot => typeof customPbAdSlot === 'function' && customPbAdSlot,
149
+ 'customPreAuction', customPreAuction => typeof customPreAuction === 'function' && customPreAuction,
150
+ 'useDefaultPreAuction', useDefaultPreAuction => useDefaultPreAuction === true,
103
151
  ]);
104
152
 
105
153
  if (_currentConfig.enabled) {
@@ -291,10 +291,11 @@ export const spec = {
291
291
  if (!hasSynced && syncOptions.pixelEnabled) {
292
292
  let params = '';
293
293
 
294
- if (gdprConsent && typeof gdprConsent.consentString === 'string') {
294
+ if (gdprConsent) {
295
295
  if (typeof gdprConsent.gdprApplies === 'boolean') {
296
- params += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`;
297
- } else {
296
+ params += `&gdpr=${Number(gdprConsent.gdprApplies)}`;
297
+ }
298
+ if (typeof gdprConsent.consentString === 'string') {
298
299
  params += `&gdpr_consent=${gdprConsent.consentString}`;
299
300
  }
300
301
  }
@@ -296,8 +296,8 @@ function buildRequests(validBidRequests, bidderRequest) {
296
296
  let gpid = '';
297
297
 
298
298
  const date = new Date();
299
- const lt = date && date.getTime();
300
- const to = date && date.getTimezoneOffset();
299
+ const lt = date.getTime();
300
+ const to = date.getTimezoneOffset();
301
301
  if (to) {
302
302
  lt && (data.lt = lt);
303
303
  data.to = to;
@@ -9,6 +9,7 @@ let conf;
9
9
  const LOG_PRE_FIX = 'ID-Library: ';
10
10
  const CONF_DEFAULT_OBSERVER_DEBOUNCE_MS = 250;
11
11
  const CONF_DEFAULT_FULL_BODY_SCAN = false;
12
+ const CONF_DEFAULT_INPUT_SCAN = false;
12
13
  const OBSERVER_CONFIG = {
13
14
  subtree: true,
14
15
  attributes: true,
@@ -78,7 +79,13 @@ function targetAction(mutations, observer) {
78
79
  }
79
80
  }
80
81
 
81
- function addInputElementsElementListner(conf) {
82
+ function addInputElementsElementListner() {
83
+ if (doesInputElementsHaveEmail()) {
84
+ _logInfo('Email found in input elements ' + email);
85
+ _logInfo('Post data on email found in target without');
86
+ postData();
87
+ return;
88
+ }
82
89
  _logInfo('Adding input element listeners');
83
90
  const inputs = document.querySelectorAll('input[type=text], input[type=email]');
84
91
 
@@ -89,6 +96,19 @@ function addInputElementsElementListner(conf) {
89
96
  }
90
97
  }
91
98
 
99
+ function addFormInputElementsElementListner(id) {
100
+ _logInfo('Adding input element listeners');
101
+ if (doesFormInputElementsHaveEmail(id)) {
102
+ _logInfo('Email found in input elements ' + email);
103
+ postData();
104
+ return;
105
+ }
106
+ _logInfo('Adding input element listeners');
107
+ const input = document.getElementById(id);
108
+ input.addEventListener('change', event => processInputChange(event));
109
+ input.addEventListener('blur', event => processInputChange(event));
110
+ }
111
+
92
112
  function removeInputElementsElementListner() {
93
113
  _logInfo('Removing input element listeners');
94
114
  const inputs = document.querySelectorAll('input[type=text], input[type=email]');
@@ -149,12 +169,6 @@ function handleTargetElement() {
149
169
  }
150
170
 
151
171
  function handleBodyElements() {
152
- if (doesInputElementsHaveEmail()) {
153
- _logInfo('Email found in input elements ' + email);
154
- _logInfo('Post data on email found in target without');
155
- postData();
156
- return;
157
- }
158
172
  email = getEmail(document.body.innerHTML);
159
173
  if (email !== null) {
160
174
  _logInfo('Email found in body ' + email);
@@ -162,7 +176,7 @@ function handleBodyElements() {
162
176
  postData();
163
177
  return;
164
178
  }
165
- addInputElementsElementListner();
179
+
166
180
  if (conf.fullscan === true) {
167
181
  const bodyObserver = new MutationObserver(debounce(bodyAction, conf.debounce, false));
168
182
  bodyObserver.observe(document.body, OBSERVER_CONFIG);
@@ -182,6 +196,17 @@ function doesInputElementsHaveEmail() {
182
196
  return false;
183
197
  }
184
198
 
199
+ function doesFormInputElementsHaveEmail(formElementId) {
200
+ const input = document.getElementById(formElementId);
201
+ if (input) {
202
+ email = getEmail(input.value);
203
+ if (email !== null) {
204
+ return true;
205
+ }
206
+ }
207
+ return false;
208
+ }
209
+
185
210
  function syncCallback() {
186
211
  return {
187
212
  success: function () {
@@ -213,6 +238,10 @@ function associateIds() {
213
238
  if (window.MutationObserver || window.WebKitMutationObserver) {
214
239
  if (conf.target) {
215
240
  handleTargetElement();
241
+ } else if (conf.formElementId) {
242
+ addFormInputElementsElementListner(conf.formElementId);
243
+ } else if (conf.inputscan) {
244
+ addInputElementsElementListner();
216
245
  } else {
217
246
  handleBodyElements();
218
247
  }
@@ -236,6 +265,14 @@ export function setConfig(config) {
236
265
  config.fullscan = CONF_DEFAULT_FULL_BODY_SCAN;
237
266
  _logInfo('Set default fullscan ' + CONF_DEFAULT_FULL_BODY_SCAN);
238
267
  }
268
+ if (typeof config.inputscan !== 'boolean') {
269
+ config.inputscan = CONF_DEFAULT_INPUT_SCAN;
270
+ _logInfo('Set default input scan ' + CONF_DEFAULT_INPUT_SCAN);
271
+ }
272
+
273
+ if (typeof config.formElementId == 'string') {
274
+ _logInfo('Looking for formElementId ' + config.formElementId);
275
+ }
239
276
  conf = config;
240
277
  associateIds();
241
278
  }
@@ -8,6 +8,8 @@
8
8
  | `url` | Yes | String | N/A | URL endpoint used to post the hashed email and user IDs. |
9
9
  | `debounce` | No | Number | 250 | Time in milliseconds before the email and IDs are fetched. |
10
10
  | `fullscan` | No | Boolean | false | Enable/disable a full page body scan to get email. |
11
+ | `formElementId` | No | String | N/A | ID attribute of the input (type=text/email) from which the email can be read. |
12
+ | `inputscan` | No | Boolean | N/A | Enable/disable a input element (type=text/email) scan to get email. |
11
13
 
12
14
  ## Example
13
15
 
@@ -18,5 +20,7 @@ pbjs.setConfig({
18
20
  url: 'https://example.com',
19
21
  debounce: 250,
20
22
  fullscan: false,
23
+ inputscan: false,
24
+ formElementId: "userid"
21
25
  },
22
26
  });
@@ -1,4 +1,4 @@
1
- import { deepSetValue, logError, _each, getBidRequest, isNumber, isArray, deepAccess, isFn, isPlainObject, logWarn, getBidIdParameter, getUniqueIdentifierStr, isEmpty, isInteger } from '../src/utils.js';
1
+ import { deepSetValue, logError, _each, getBidRequest, isNumber, isArray, deepAccess, isFn, isPlainObject, logWarn, getBidIdParameter, getUniqueIdentifierStr, isEmpty, isInteger, isStr } from '../src/utils.js';
2
2
  import { registerBidder } from '../src/adapters/bidderFactory.js';
3
3
  import { config } from '../src/config.js';
4
4
  import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js';
@@ -11,7 +11,7 @@ const RENDERER_URL = 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js
11
11
  const VIDEO_TARGETING = ['skip', 'skipmin', 'skipafter'];
12
12
 
13
13
  export const spec = {
14
- version: '7.4.0',
14
+ version: '7.6.0',
15
15
  code: BIDDER_CODE,
16
16
  gvlid: 253,
17
17
  aliases: ['id'],
@@ -45,8 +45,24 @@ export const spec = {
45
45
  libVersion: this.version
46
46
  };
47
47
 
48
- if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.consentString) {
49
- requestParameters.gdpr = bidderRequest.gdprConsent.consentString;
48
+ const gdprConsent = deepAccess(bidderRequest, 'gdprConsent')
49
+ if (gdprConsent) {
50
+ // GDPR Consent String
51
+ if (gdprConsent.consentString) {
52
+ requestParameters.gdpr = gdprConsent.consentString;
53
+ }
54
+
55
+ // Additional Consent String
56
+ const additionalConsent = deepAccess(gdprConsent, 'addtlConsent');
57
+ if (additionalConsent && additionalConsent.indexOf('~') !== -1) {
58
+ // Google Ad Tech Provider IDs
59
+ const atpIds = additionalConsent.substring(additionalConsent.indexOf('~') + 1);
60
+ deepSetValue(
61
+ requestParameters,
62
+ 'user.ext.consented_providers_settings.consented_providers',
63
+ atpIds.split('.').map(id => parseInt(id, 10))
64
+ );
65
+ }
50
66
  }
51
67
 
52
68
  if (bidderRequest && bidderRequest.uspConsent) {
@@ -57,6 +73,22 @@ export const spec = {
57
73
  requestParameters.referrer = bidderRequest.refererInfo.referer;
58
74
  }
59
75
 
76
+ // Adding first party data
77
+ const site = config.getConfig('ortb2.site');
78
+ if (site) {
79
+ const pageCategory = site.pagecat || site.cat;
80
+ if (pageCategory && isArray(pageCategory)) {
81
+ requestParameters.pagecat = pageCategory.filter((category) => {
82
+ return category && isStr(category)
83
+ });
84
+ }
85
+ const genre = deepAccess(site, 'content.genre');
86
+ if (genre && isStr(genre)) {
87
+ requestParameters.genre = genre;
88
+ }
89
+ }
90
+ // End of adding first party data
91
+
60
92
  requestParameters.schain = bidRequests[0].schain;
61
93
 
62
94
  if (bidRequests[0].userId) {
@@ -605,6 +637,12 @@ export function ImproveDigitalAdServerJSClient(endPoint) {
605
637
  if (requestParameters.schain) {
606
638
  impressionBidRequestObject.schain = requestParameters.schain;
607
639
  }
640
+ if (requestParameters.pagecat) {
641
+ impressionBidRequestObject.pagecat = requestParameters.pagecat;
642
+ }
643
+ if (requestParameters.genre) {
644
+ impressionBidRequestObject.genre = requestParameters.genre;
645
+ }
608
646
  if (requestParameters.user) {
609
647
  impressionBidRequestObject.user = requestParameters.user;
610
648
  }
@@ -3,11 +3,11 @@ import { config } from '../src/config.js';
3
3
  import { auctionManager } from '../src/auctionManager.js';
4
4
  import { INSTREAM } from '../src/video.js';
5
5
  import * as events from '../src/events.js';
6
- import { BID_STATUS, EVENTS, TARGETING_KEYS } from '../src/constants.json';
6
+ import CONSTANTS from '../src/constants.json'
7
7
 
8
- const {CACHE_ID, UUID} = TARGETING_KEYS;
9
- const {BID_WON, AUCTION_END} = EVENTS;
10
- const {RENDERED} = BID_STATUS;
8
+ const {CACHE_ID, UUID} = CONSTANTS.TARGETING_KEYS;
9
+ const {BID_WON, AUCTION_END} = CONSTANTS.EVENTS;
10
+ const {RENDERED} = CONSTANTS.BID_STATUS;
11
11
 
12
12
  const INSTREAM_TRACKING_DEFAULT_CONFIG = {
13
13
  enabled: false,
@@ -4,7 +4,8 @@ import {getStorageManager} from '../src/storageManager.js';
4
4
 
5
5
  const CONSTANTS = {
6
6
  BIDDER_CODE: 'invibes',
7
- BID_ENDPOINT: 'https://bid.videostep.com/Bid/VideoAdContent',
7
+ BID_ENDPOINT: '.videostep.com/Bid/VideoAdContent',
8
+ BID_SUBDOMAIN: 'https://bid',
8
9
  SYNC_ENDPOINT: 'https://k.r66net.com/GetUserSync',
9
10
  TIME_TO_LIVE: 300,
10
11
  DEFAULT_CURRENCY: 'EUR',
@@ -78,14 +79,14 @@ function buildRequest(bidRequests, bidderRequest) {
78
79
  bidderRequest = bidderRequest || {};
79
80
  const _placementIds = [];
80
81
  const _adUnitCodes = [];
81
- let _loginId, _customEndpoint, _userId;
82
+ let _customEndpoint, _userId, _domainId;
82
83
  let _ivAuctionStart = bidderRequest.auctionStart || Date.now();
83
84
 
84
85
  bidRequests.forEach(function (bidRequest) {
85
86
  bidRequest.startTime = new Date().getTime();
86
87
  _placementIds.push(bidRequest.params.placementId);
87
88
  _adUnitCodes.push(bidRequest.adUnitCode);
88
- _loginId = _loginId || bidRequest.params.loginId;
89
+ _domainId = _domainId || bidRequest.params.domainId;
89
90
  _customEndpoint = _customEndpoint || bidRequest.params.customEndpoint;
90
91
  _customUserSync = _customUserSync || bidRequest.params.customUserSync;
91
92
  _userId = _userId || bidRequest.userId;
@@ -102,7 +103,6 @@ function buildRequest(bidRequests, bidderRequest) {
102
103
  let bidParamsJson = {
103
104
  placementIds: _placementIds,
104
105
  adUnitCodes: _adUnitCodes,
105
- loginId: _loginId,
106
106
  auctionStartTime: _ivAuctionStart,
107
107
  bidVersion: CONSTANTS.PREBID_VERSION
108
108
  };
@@ -146,9 +146,11 @@ function buildRequest(bidRequests, bidderRequest) {
146
146
  }
147
147
  }
148
148
 
149
+ let endpoint = createEndpoint(_customEndpoint, _domainId, _placementIds);
150
+
149
151
  return {
150
152
  method: CONSTANTS.METHOD,
151
- url: _customEndpoint || CONSTANTS.BID_ENDPOINT,
153
+ url: endpoint,
152
154
  data: data,
153
155
  options: {withCredentials: true},
154
156
  // for POST: { contentType: 'application/json', withCredentials: true }
@@ -280,6 +282,48 @@ function createBid(bidRequest, requestPlacement, multipositionEnabled, usedPlace
280
282
  };
281
283
  }
282
284
 
285
+ function createEndpoint(customEndpoint, domainId, placementIds) {
286
+ if (customEndpoint != null) {
287
+ return customEndpoint;
288
+ }
289
+
290
+ if (domainId != null) {
291
+ return extractEndpointFromId(domainId - 1000);
292
+ }
293
+
294
+ if (placementIds.length > 0) {
295
+ for (var i = 0; i < placementIds.length; i++) {
296
+ const id = extractFromPlacement(placementIds[i]);
297
+ if (id != null) {
298
+ return extractEndpointFromId(id);
299
+ }
300
+ }
301
+ }
302
+
303
+ return extractEndpointFromId(1);
304
+ }
305
+
306
+ function extractEndpointFromId(domainId) {
307
+ if (domainId < 2) {
308
+ return CONSTANTS.BID_SUBDOMAIN + CONSTANTS.BID_ENDPOINT;
309
+ }
310
+
311
+ return CONSTANTS.BID_SUBDOMAIN + domainId + CONSTANTS.BID_ENDPOINT;
312
+ }
313
+
314
+ function extractFromPlacement(placementId) {
315
+ if (placementId == null) { return null; }
316
+
317
+ var pattern = /_ivbs([0-9]+)/g;
318
+
319
+ var match = pattern.exec(placementId);
320
+ if (match != null && match[1] != null) {
321
+ return parseInt(match[1]);
322
+ }
323
+
324
+ return null;
325
+ }
326
+
283
327
  function addMeta(bidModelMeta) {
284
328
  var meta = {};
285
329
  if (bidModelMeta != null) {
@@ -20,7 +20,8 @@ Connect to Invibes for bids.
20
20
  {
21
21
  bidder: 'invibes',
22
22
  params: {
23
- placementId: '12345'
23
+ placementId: '12345',
24
+ domainId: 1001
24
25
  }
25
26
  }
26
27
  ]