prebid.js 6.3.0 → 6.7.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 (157) hide show
  1. package/.circleci/config.yml +1 -1
  2. package/gulpfile.js +87 -74
  3. package/integrationExamples/gpt/amp/creative.html +11 -33
  4. package/karma.conf.maker.js +1 -1
  5. package/modules/.submodules.json +2 -1
  6. package/modules/adbookpspBidAdapter.js +27 -10
  7. package/modules/adhashBidAdapter.js +3 -3
  8. package/modules/adkernelBidAdapter.js +148 -62
  9. package/modules/adlooxAdServerVideo.js +2 -2
  10. package/modules/adlooxAnalyticsAdapter.js +4 -4
  11. package/modules/admanBidAdapter.js +10 -4
  12. package/modules/adomikAnalyticsAdapter.js +27 -9
  13. package/modules/adqueryIdSystem.js +103 -0
  14. package/modules/adqueryIdSystem.md +35 -0
  15. package/modules/adyoulikeBidAdapter.js +13 -9
  16. package/modules/aniviewBidAdapter.js +1 -1
  17. package/modules/beopBidAdapter.js +1 -1
  18. package/modules/bidViewability.js +3 -3
  19. package/modules/bidViewabilityIO.js +3 -3
  20. package/modules/bliinkBidAdapter.js +3 -2
  21. package/modules/colossussspBidAdapter.js +12 -8
  22. package/modules/colossussspBidAdapter.md +15 -1
  23. package/modules/compassBidAdapter.js +208 -0
  24. package/modules/compassBidAdapter.md +79 -0
  25. package/modules/consentManagement.js +7 -1
  26. package/modules/consumableBidAdapter.md +1 -1
  27. package/modules/criteoBidAdapter.js +1 -1
  28. package/modules/criteoIdSystem.js +29 -7
  29. package/modules/currency.js +2 -2
  30. package/modules/dailyhuntBidAdapter.js +435 -0
  31. package/modules/dailyhuntBidAdapter.md +4 -0
  32. package/modules/docereeBidAdapter.js +10 -1
  33. package/modules/docereeBidAdapter.md +2 -0
  34. package/modules/engageyaBidAdapter.js +1 -1
  35. package/modules/feedadBidAdapter.js +2 -2
  36. package/modules/feedadBidAdapter.md +4 -2
  37. package/modules/glimpseBidAdapter.js +66 -44
  38. package/modules/gnetBidAdapter.js +3 -3
  39. package/modules/gnetBidAdapter.md +4 -4
  40. package/modules/gptPreAuction.js +55 -7
  41. package/modules/gridBidAdapter.js +4 -3
  42. package/modules/gumgumBidAdapter.js +4 -4
  43. package/modules/idImportLibrary.js +45 -8
  44. package/modules/idImportLibrary.md +4 -0
  45. package/modules/improvedigitalBidAdapter.js +42 -4
  46. package/modules/instreamTracking.js +4 -4
  47. package/modules/invibesBidAdapter.js +49 -5
  48. package/modules/invibesBidAdapter.md +2 -1
  49. package/modules/ixBidAdapter.js +53 -18
  50. package/modules/jwplayerRtdProvider.js +71 -6
  51. package/modules/jwplayerRtdProvider.md +27 -11
  52. package/modules/kargoBidAdapter.js +2 -2
  53. package/modules/limelightDigitalBidAdapter.js +2 -1
  54. package/modules/livewrappedAnalyticsAdapter.js +3 -1
  55. package/modules/livewrappedBidAdapter.js +8 -2
  56. package/modules/loglyliftBidAdapter.js +79 -0
  57. package/modules/loglyliftBidAdapter.md +55 -0
  58. package/modules/nextMillenniumBidAdapter.js +11 -7
  59. package/modules/oguryBidAdapter.js +9 -2
  60. package/modules/onetagBidAdapter.js +4 -2
  61. package/modules/optimeraRtdProvider.js +8 -1
  62. package/modules/ozoneBidAdapter.js +21 -64
  63. package/modules/pilotxBidAdapter.js +147 -0
  64. package/modules/pilotxBidAdapter.md +50 -0
  65. package/modules/proxistoreBidAdapter.js +0 -2
  66. package/modules/pubgeniusBidAdapter.js +1 -1
  67. package/modules/pubmaticAnalyticsAdapter.js +16 -0
  68. package/modules/pubxaiAnalyticsAdapter.js +17 -0
  69. package/modules/richaudienceBidAdapter.js +3 -2
  70. package/modules/riseBidAdapter.js +1 -1
  71. package/modules/rtbhouseBidAdapter.js +14 -4
  72. package/modules/rtdModule/index.js +14 -15
  73. package/modules/rubiconAnalyticsAdapter.js +3 -2
  74. package/modules/rubiconBidAdapter.js +21 -11
  75. package/modules/seedingAllianceBidAdapter.js +3 -3
  76. package/modules/sharethroughBidAdapter.js +12 -17
  77. package/modules/showheroes-bsBidAdapter.js +13 -2
  78. package/modules/synacormediaBidAdapter.js +31 -10
  79. package/modules/tappxBidAdapter.js +8 -5
  80. package/modules/teadsBidAdapter.js +1 -2
  81. package/modules/telariaBidAdapter.js +2 -2
  82. package/modules/trustxBidAdapter.js +8 -16
  83. package/modules/userId/eids.js +7 -1
  84. package/modules/userId/userId.md +8 -0
  85. package/modules/viewability.js +177 -0
  86. package/modules/viewability.md +87 -0
  87. package/modules/welectBidAdapter.js +106 -0
  88. package/modules/yieldmoBidAdapter.js +23 -5
  89. package/modules/zeta_global_sspAnalyticsAdapter.js +97 -0
  90. package/modules/zeta_global_sspAnalyticsAdapter.md +24 -0
  91. package/package.json +1 -1
  92. package/src/auction.js +2 -2
  93. package/src/config.js +27 -3
  94. package/src/hook.js +5 -1
  95. package/src/prebid.js +20 -4
  96. package/src/secureCreatives.js +3 -2
  97. package/src/utils.js +12 -1
  98. package/test/helpers/prebidGlobal.js +1 -0
  99. package/test/spec/config_spec.js +279 -0
  100. package/test/spec/modules/adbookpspBidAdapter_spec.js +17 -3
  101. package/test/spec/modules/adhashBidAdapter_spec.js +2 -2
  102. package/test/spec/modules/adlooxAnalyticsAdapter_spec.js +6 -6
  103. package/test/spec/modules/admanBidAdapter_spec.js +2 -2
  104. package/test/spec/modules/adomikAnalyticsAdapter_spec.js +9 -1
  105. package/test/spec/modules/adqueryIdSystem_spec.js +74 -0
  106. package/test/spec/modules/adyoulikeBidAdapter_spec.js +49 -0
  107. package/test/spec/modules/beopBidAdapter_spec.js +1 -1
  108. package/test/spec/modules/bidViewabilityIO_spec.js +2 -2
  109. package/test/spec/modules/bidViewability_spec.js +4 -4
  110. package/test/spec/modules/bliinkBidAdapter_spec.js +2 -0
  111. package/test/spec/modules/colossussspBidAdapter_spec.js +5 -2
  112. package/test/spec/modules/compassBidAdapter_spec.js +398 -0
  113. package/test/spec/modules/consentManagement_spec.js +20 -0
  114. package/test/spec/modules/criteoIdSystem_spec.js +6 -3
  115. package/test/spec/modules/dailyhuntBidAdapter_spec.js +404 -0
  116. package/test/spec/modules/docereeBidAdapter_spec.js +9 -1
  117. package/test/spec/modules/eids_spec.js +15 -0
  118. package/test/spec/modules/feedadBidAdapter_spec.js +15 -0
  119. package/test/spec/modules/glimpseBidAdapter_spec.js +0 -18
  120. package/test/spec/modules/gnetBidAdapter_spec.js +6 -6
  121. package/test/spec/modules/gptPreAuction_spec.js +177 -2
  122. package/test/spec/modules/idImportLibrary_spec.js +197 -10
  123. package/test/spec/modules/improvedigitalBidAdapter_spec.js +45 -1
  124. package/test/spec/modules/invibesBidAdapter_spec.js +119 -0
  125. package/test/spec/modules/ixBidAdapter_spec.js +112 -62
  126. package/test/spec/modules/jwplayerRtdProvider_spec.js +195 -2
  127. package/test/spec/modules/kargoBidAdapter_spec.js +1 -1
  128. package/test/spec/modules/limelightDigitalBidAdapter_spec.js +75 -17
  129. package/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +22 -0
  130. package/test/spec/modules/livewrappedBidAdapter_spec.js +31 -0
  131. package/test/spec/modules/loglyliftBidAdapter_spec.js +172 -0
  132. package/test/spec/modules/nextMillenniumBidAdapter_spec.js +9 -2
  133. package/test/spec/modules/oguryBidAdapter_spec.js +10 -2
  134. package/test/spec/modules/optimeraRtdProvider_spec.js +14 -1
  135. package/test/spec/modules/ozoneBidAdapter_spec.js +43 -31
  136. package/test/spec/modules/pilotxBidAdapter_spec.js +244 -0
  137. package/test/spec/modules/pubgeniusBidAdapter_spec.js +3 -3
  138. package/test/spec/modules/pubmaticAnalyticsAdapter_spec.js +13 -1
  139. package/test/spec/modules/pubxaiAnalyticsAdapter_spec.js +11 -0
  140. package/test/spec/modules/realTimeDataModule_spec.js +67 -5
  141. package/test/spec/modules/richaudienceBidAdapter_spec.js +40 -0
  142. package/test/spec/modules/riseBidAdapter_spec.js +1 -1
  143. package/test/spec/modules/rtbhouseBidAdapter_spec.js +20 -0
  144. package/test/spec/modules/rubiconAnalyticsAdapter_spec.js +30 -0
  145. package/test/spec/modules/rubiconBidAdapter_spec.js +48 -9
  146. package/test/spec/modules/sharethroughBidAdapter_spec.js +91 -6
  147. package/test/spec/modules/showheroes-bsBidAdapter_spec.js +2 -0
  148. package/test/spec/modules/synacormediaBidAdapter_spec.js +70 -0
  149. package/test/spec/modules/tappxBidAdapter_spec.js +0 -19
  150. package/test/spec/modules/teadsBidAdapter_spec.js +14 -59
  151. package/test/spec/modules/userId_spec.js +68 -19
  152. package/test/spec/modules/viewability_spec.js +280 -0
  153. package/test/spec/modules/welectBidAdapter_spec.js +211 -0
  154. package/test/spec/modules/zeta_global_sspAnalyticsAdapter_spec.js +427 -0
  155. package/test/spec/unit/pbjs_api_spec.js +3 -1
  156. package/test/test_deps.js +3 -0
  157. package/test/test_index.js +1 -3
@@ -1,14 +1,14 @@
1
1
  # Overview
2
2
 
3
3
  ```
4
- Module Name: Gnet Bidder Adapter
4
+ Module Name: Gnet RTB Bidder Adapter
5
5
  Module Type: Bidder Adapter
6
- Maintainer: roberto.wu@grumft.com
6
+ Maintainer: bruno.bonanho@grumft.com
7
7
  ```
8
8
 
9
9
  # Description
10
10
 
11
- Connect to Gnet Project exchange for bids.
11
+ Connect to Gnet RTB exchange for bids.
12
12
 
13
13
  # Test Parameters
14
14
  ```
@@ -24,7 +24,7 @@ Connect to Gnet Project exchange for bids.
24
24
  {
25
25
  bidder: 'gnet',
26
26
  params: {
27
- websiteId: '4'
27
+ websiteId: '1', adunitId: '1'
28
28
  }
29
29
  }
30
30
  ]
@@ -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
  }
@@ -298,10 +298,10 @@ function buildRequests(validBidRequests, bidderRequest) {
298
298
  const date = new Date();
299
299
  const lt = date.getTime();
300
300
  const to = date.getTimezoneOffset();
301
- if (to) {
302
- lt && (data.lt = lt);
303
- data.to = to;
304
- }
301
+
302
+ // ADTS-174 Removed unnecessary checks to fix failing test
303
+ data.lt = lt;
304
+ data.to = to;
305
305
 
306
306
  // ADTS-169 add adUnitCode to requests
307
307
  if (adUnitCode) data.aun = adUnitCode
@@ -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
  ]
@@ -1,8 +1,8 @@
1
- import { deepAccess, parseGPTSingleSizeArray, inIframe, deepClone, logError, logWarn, isFn, contains, isInteger, isArray, deepSetValue, parseQueryStringParameters, isEmpty, mergeDeep, convertTypes } from '../src/utils.js';
1
+ import { deepAccess, parseGPTSingleSizeArray, inIframe, deepClone, logError, logWarn, isFn, contains, isInteger, isArray, deepSetValue, parseQueryStringParameters, isEmpty, mergeDeep, convertTypes, hasDeviceAccess } from '../src/utils.js';
2
2
  import { BANNER, VIDEO } from '../src/mediaTypes.js';
3
3
  import { config } from '../src/config.js';
4
- import { EVENTS } from '../src/constants.json';
5
- import { getStorageManager } from '../src/storageManager.js';
4
+ import CONSTANTS from '../src/constants.json';
5
+ import { getStorageManager, validateStorageEnforcement } from '../src/storageManager.js';
6
6
  import events from '../src/events.js';
7
7
  import find from 'core-js-pure/features/array/find.js';
8
8
  import { registerBidder } from '../src/adapters/bidderFactory.js';
@@ -53,7 +53,12 @@ const SOURCE_RTI_MAPPING = {
53
53
  'neustar.biz': 'fabrickId',
54
54
  'zeotap.com': 'zeotapIdPlus',
55
55
  'uidapi.com': 'UID2',
56
- 'adserver.org': 'TDID'
56
+ 'adserver.org': 'TDID',
57
+ 'id5-sync.com': '', // ID5 Universal ID, configured as id5Id
58
+ 'crwdcntrl.net': '', // Lotame Panorama ID, lotamePanoramaId
59
+ 'epsilon.com': '', // Publisher Link, publinkId
60
+ 'audigent.com': '', // Halo ID from Audigent, haloId
61
+ 'pubcid.org': '' // SharedID, pubcid
57
62
  };
58
63
  const PROVIDERS = [
59
64
  'britepoolid',
@@ -69,7 +74,8 @@ const PROVIDERS = [
69
74
  'quantcastId',
70
75
  'pubcid',
71
76
  'TDID',
72
- 'flocId'
77
+ 'flocId',
78
+ 'pubProvidedId'
73
79
  ];
74
80
  const REQUIRED_VIDEO_PARAMS = ['mimes', 'minduration', 'maxduration']; // note: protocol/protocols is also reqd
75
81
  const VIDEO_PARAMS_ALLOW_LIST = [
@@ -194,7 +200,7 @@ function bidToImp(bid) {
194
200
  imp.id = bid.bidId;
195
201
 
196
202
  imp.ext = {};
197
- imp.ext.siteID = bid.params.siteId;
203
+ imp.ext.siteID = bid.params.siteId.toString();
198
204
 
199
205
  if (bid.params.hasOwnProperty('id') &&
200
206
  (typeof bid.params.id === 'string' || typeof bid.params.id === 'number')) {
@@ -444,16 +450,19 @@ function getEidInfo(allEids, flocData) {
444
450
  let seenSources = {};
445
451
  if (isArray(allEids)) {
446
452
  for (const eid of allEids) {
447
- if (SOURCE_RTI_MAPPING[eid.source] && deepAccess(eid, 'uids.0')) {
453
+ if (SOURCE_RTI_MAPPING.hasOwnProperty(eid.source) && deepAccess(eid, 'uids.0')) {
448
454
  seenSources[eid.source] = true;
449
- eid.uids[0].ext = {
450
- rtiPartner: SOURCE_RTI_MAPPING[eid.source]
451
- };
455
+ if (SOURCE_RTI_MAPPING[eid.source] != '') {
456
+ eid.uids[0].ext = {
457
+ rtiPartner: SOURCE_RTI_MAPPING[eid.source]
458
+ };
459
+ }
452
460
  delete eid.uids[0].atype;
453
461
  toSend.push(eid);
454
462
  }
455
463
  }
456
464
  }
465
+
457
466
  const isValidFlocId = flocData && flocData.id && flocData.version;
458
467
  if (isValidFlocId) {
459
468
  const flocEid = {
@@ -466,6 +475,7 @@ function getEidInfo(allEids, flocData) {
466
475
 
467
476
  return { toSend, seenSources };
468
477
  }
478
+
469
479
  /**
470
480
  * Builds a request object to be sent to the ad server based on bid requests.
471
481
  *
@@ -680,6 +690,7 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
680
690
 
681
691
  if (impressionObjects.length && BANNER in impressionObjects[0]) {
682
692
  const { id, banner: { topframe }, ext } = impressionObjects[0];
693
+ const gpid = impressions[transactionIds[adUnitIndex]].gpid;
683
694
  const _bannerImpression = {
684
695
  id,
685
696
  banner: {
@@ -688,10 +699,10 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
688
699
  },
689
700
  }
690
701
 
691
- if (ext.dfp_ad_unit_code) {
692
- _bannerImpression.ext = {
693
- dfp_ad_unit_code: ext.dfp_ad_unit_code
694
- }
702
+ if (ext.dfp_ad_unit_code || gpid) {
703
+ _bannerImpression.ext = {};
704
+ _bannerImpression.ext.dfp_ad_unit_code = ext.dfp_ad_unit_code;
705
+ _bannerImpression.ext.gpid = gpid;
695
706
  }
696
707
 
697
708
  if ('bidfloor' in impressionObjects[0]) {
@@ -911,6 +922,7 @@ function createBannerImps(validBidRequest, missingBannerSizes, bannerImps) {
911
922
  bannerImps[validBidRequest.transactionId].ixImps = []
912
923
  }
913
924
  bannerImps[validBidRequest.transactionId].ixImps.push(imp);
925
+ bannerImps[validBidRequest.transactionId].gpid = deepAccess(validBidRequest, 'ortb2Imp.ext.gpid');
914
926
  }
915
927
 
916
928
  if (ixConfig.hasOwnProperty('detectMissingSizes') && ixConfig.detectMissingSizes) {
@@ -991,7 +1003,7 @@ function createMissingBannerImp(bid, imp, newSize) {
991
1003
  *
992
1004
  * @param {ErrorData} data
993
1005
  */
994
- function errorEventHandler(data) {
1006
+ function storeErrorEventData(data) {
995
1007
  if (!storage.localStorageIsEnabled()) {
996
1008
  return;
997
1009
  }
@@ -1033,6 +1045,24 @@ function errorEventHandler(data) {
1033
1045
  storage.setDataInLocalStorage(LOCAL_STORAGE_KEY, JSON.stringify(currentStorage));
1034
1046
  }
1035
1047
 
1048
+ /**
1049
+ * Event handler for storing data into local storage. It will only store data if
1050
+ * local storage premissions are avaliable
1051
+ */
1052
+ function localStorageHandler(data) {
1053
+ if (data.type === 'ERROR' && data.arguments && data.arguments[1] && data.arguments[1].bidder === BIDDER_CODE) {
1054
+ const DEFAULT_ENFORCEMENT_SETTINGS = {
1055
+ hasEnforcementHook: false,
1056
+ valid: hasDeviceAccess()
1057
+ };
1058
+ validateStorageEnforcement(GLOBAL_VENDOR_ID, BIDDER_CODE, DEFAULT_ENFORCEMENT_SETTINGS, (permissions) => {
1059
+ if (permissions.valid) {
1060
+ storeErrorEventData(data);
1061
+ }
1062
+ });
1063
+ }
1064
+ }
1065
+
1036
1066
  /**
1037
1067
  * Get ixdiag stored in LocalStorage and format to be added to request payload
1038
1068
  *
@@ -1129,8 +1159,8 @@ export const spec = {
1129
1159
  */
1130
1160
  isBidRequestValid: function (bid) {
1131
1161
  if (!hasRegisteredHandler) {
1132
- events.on(EVENTS.AUCTION_DEBUG, errorEventHandler);
1133
- events.on(EVENTS.AD_RENDER_FAILED, errorEventHandler);
1162
+ events.on(CONSTANTS.EVENTS.AUCTION_DEBUG, localStorageHandler);
1163
+ events.on(CONSTANTS.EVENTS.AD_RENDER_FAILED, localStorageHandler);
1134
1164
  hasRegisteredHandler = true;
1135
1165
  }
1136
1166
 
@@ -1168,7 +1198,12 @@ export const spec = {
1168
1198
  }
1169
1199
 
1170
1200
  if (typeof bid.params.siteId !== 'string' && typeof bid.params.siteId !== 'number') {
1171
- logError('IX Bid Adapter: siteId must be string or number value.', { bidder: BIDDER_CODE, code: ERROR_CODES.SITE_ID_INVALID_VALUE });
1201
+ logError('IX Bid Adapter: siteId must be string or number type.', { bidder: BIDDER_CODE, code: ERROR_CODES.SITE_ID_INVALID_VALUE });
1202
+ return false;
1203
+ }
1204
+
1205
+ if (typeof bid.params.siteId !== 'string' && isNaN(Number(bid.params.siteId))) {
1206
+ logError('IX Bid Adapter: siteId must valid value', { bidder: BIDDER_CODE, code: ERROR_CODES.SITE_ID_INVALID_VALUE });
1172
1207
  return false;
1173
1208
  }
1174
1209