prebid.js 8.1.0 → 8.2.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 (183) hide show
  1. package/.devcontainer/devcontainer.json +3 -1
  2. package/dist/33acrossBidAdapter.js +1 -1
  3. package/dist/33acrossIdSystem.js +1 -1
  4. package/dist/adagioBidAdapter.js +1 -1
  5. package/dist/adbookpspBidAdapter.js +1 -1
  6. package/dist/adgenerationBidAdapter.js +1 -1
  7. package/dist/admanBidAdapter.js +1 -1
  8. package/dist/adqueryBidAdapter.js +1 -1
  9. package/dist/adrelevantisBidAdapter.js +1 -1
  10. package/dist/adtrgtmeBidAdapter.js +1 -1
  11. package/dist/adxcgBidAdapter.js +1 -1
  12. package/dist/adyoulikeBidAdapter.js +1 -1
  13. package/dist/ajaBidAdapter.js +1 -1
  14. package/dist/amxBidAdapter.js +1 -1
  15. package/dist/amxIdSystem.js +1 -1
  16. package/dist/appierAnalyticsAdapter.js +1 -1
  17. package/dist/appnexusBidAdapter.js +1 -1
  18. package/dist/asoBidAdapter.js +1 -1
  19. package/dist/axonixBidAdapter.js +1 -1
  20. package/dist/bidglassBidAdapter.js +1 -1
  21. package/dist/big-richmediaBidAdapter.js +1 -1
  22. package/dist/bridBidAdapter.js +1 -0
  23. package/dist/bridgewellBidAdapter.js +1 -1
  24. package/dist/brightMountainMediaBidAdapter.js +1 -1
  25. package/dist/carodaBidAdapter.js +1 -1
  26. package/dist/categoryTranslation.js +1 -1
  27. package/dist/chtnwBidAdapter.js +1 -1
  28. package/dist/cmp.js +1 -0
  29. package/dist/concertBidAdapter.js +1 -1
  30. package/dist/connectadBidAdapter.js +1 -1
  31. package/dist/consentManagement.js +1 -1
  32. package/dist/consentManagementGpp.js +1 -1
  33. package/dist/consentManagementUsp.js +1 -1
  34. package/dist/consumableBidAdapter.js +1 -1
  35. package/dist/conversantAnalyticsAdapter.js +1 -1
  36. package/dist/conversantBidAdapter.js +1 -1
  37. package/dist/craftBidAdapter.js +1 -1
  38. package/dist/criteoBidAdapter.js +1 -1
  39. package/dist/cwireBidAdapter.js +1 -1
  40. package/dist/dependencies.json +12 -0
  41. package/dist/dspxBidAdapter.js +1 -1
  42. package/dist/eplanningBidAdapter.js +1 -1
  43. package/dist/euidIdSystem.js +1 -1
  44. package/dist/feedadBidAdapter.js +1 -1
  45. package/dist/finativeBidAdapter.js +1 -1
  46. package/dist/freewheel-sspBidAdapter.js +1 -1
  47. package/dist/gmosspBidAdapter.js +1 -1
  48. package/dist/goldbachBidAdapter.js +1 -1
  49. package/dist/gppControl_usnat.js +1 -0
  50. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  51. package/dist/greenbidsRtdProvider.js +1 -1
  52. package/dist/gridBidAdapter.js +1 -1
  53. package/dist/gumgumBidAdapter.js +1 -1
  54. package/dist/h12mediaBidAdapter.js +1 -1
  55. package/dist/hypelabBidAdapter.js +1 -1
  56. package/dist/id5IdSystem.js +1 -1
  57. package/dist/imdsBidAdapter.js +1 -1
  58. package/dist/improvedigitalBidAdapter.js +1 -1
  59. package/dist/insticatorBidAdapter.js +1 -1
  60. package/dist/intentIqIdSystem.js +1 -1
  61. package/dist/ixBidAdapter.js +1 -1
  62. package/dist/justpremiumBidAdapter.js +1 -1
  63. package/dist/kargoBidAdapter.js +1 -1
  64. package/dist/konduitAnalyticsAdapter.js +1 -1
  65. package/dist/kueezBidAdapter.js +1 -1
  66. package/dist/kueezRtbBidAdapter.js +1 -1
  67. package/dist/kulturemediaBidAdapter.js +1 -1
  68. package/dist/lassoBidAdapter.js +1 -1
  69. package/dist/lifestreetBidAdapter.js +1 -1
  70. package/dist/liveIntentIdSystem.js +1 -1
  71. package/dist/logicadBidAdapter.js +1 -1
  72. package/dist/loglyliftBidAdapter.js +1 -1
  73. package/dist/magniteAnalyticsAdapter.js +1 -1
  74. package/dist/malltvAnalyticsAdapter.js +1 -1
  75. package/dist/marsmediaBidAdapter.js +1 -1
  76. package/dist/mediafuseBidAdapter.js +1 -1
  77. package/dist/mediasquareBidAdapter.js +1 -1
  78. package/dist/mgidBidAdapter.js +1 -1
  79. package/dist/minutemediaBidAdapter.js +1 -1
  80. package/dist/minutemediaplusBidAdapter.js +1 -1
  81. package/dist/mspa.js +1 -0
  82. package/dist/nexx360BidAdapter.js +1 -1
  83. package/dist/not-for-prod/prebid.js +136 -132
  84. package/dist/oguryBidAdapter.js +1 -1
  85. package/dist/onetagBidAdapter.js +1 -1
  86. package/dist/ooloAnalyticsAdapter.js +1 -1
  87. package/dist/optidigitalBidAdapter.js +1 -1
  88. package/dist/outbrainBidAdapter.js +1 -1
  89. package/dist/oxxionRtdProvider.js +1 -1
  90. package/dist/parrableIdSystem.js +1 -1
  91. package/dist/pixfutureBidAdapter.js +1 -1
  92. package/dist/prebid-core.js +1 -1
  93. package/dist/publinkIdSystem.js +1 -1
  94. package/dist/pubmaticBidAdapter.js +1 -1
  95. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  96. package/dist/pxyzBidAdapter.js +1 -1
  97. package/dist/quantcastBidAdapter.js +1 -1
  98. package/dist/readpeakBidAdapter.js +1 -1
  99. package/dist/relaidoBidAdapter.js +1 -1
  100. package/dist/retailspotBidAdapter.js +1 -1
  101. package/dist/rhythmoneBidAdapter.js +1 -1
  102. package/dist/riseBidAdapter.js +1 -1
  103. package/dist/rubiconBidAdapter.js +1 -1
  104. package/dist/seedingAllianceBidAdapter.js +1 -1
  105. package/dist/seedtagBidAdapter.js +1 -1
  106. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  107. package/dist/sharethroughBidAdapter.js +1 -1
  108. package/dist/shinezBidAdapter.js +1 -1
  109. package/dist/smaatoBidAdapter.js +1 -1
  110. package/dist/smartadserverBidAdapter.js +1 -1
  111. package/dist/smartxBidAdapter.js +1 -1
  112. package/dist/smilewantedBidAdapter.js +1 -1
  113. package/dist/sonobiBidAdapter.js +1 -1
  114. package/dist/sovrnAnalyticsAdapter.js +1 -1
  115. package/dist/sovrnBidAdapter.js +1 -1
  116. package/dist/sspBCBidAdapter.js +1 -1
  117. package/dist/stvBidAdapter.js +1 -1
  118. package/dist/sublimeBidAdapter.js +1 -1
  119. package/dist/targetVideoBidAdapter.js +1 -1
  120. package/dist/teadsBidAdapter.js +1 -1
  121. package/dist/trionBidAdapter.js +1 -1
  122. package/dist/tripleliftBidAdapter.js +1 -1
  123. package/dist/ttdBidAdapter.js +1 -1
  124. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  125. package/dist/uid2IdSystem.js +1 -1
  126. package/dist/underdogmediaBidAdapter.js +1 -1
  127. package/dist/undertoneBidAdapter.js +1 -1
  128. package/dist/userId.js +1 -1
  129. package/dist/vidazooBidAdapter.js +1 -1
  130. package/dist/videobyteBidAdapter.js +1 -1
  131. package/dist/visxBidAdapter.js +1 -1
  132. package/dist/vuukleBidAdapter.js +1 -1
  133. package/dist/widespaceBidAdapter.js +1 -1
  134. package/dist/winrBidAdapter.js +1 -1
  135. package/dist/yahoosspBidAdapter.js +1 -1
  136. package/dist/yieldmoBidAdapter.js +1 -1
  137. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  138. package/libraries/cmp/cmpClient.js +139 -0
  139. package/libraries/mspa/activityControls.js +91 -0
  140. package/modules/admanBidAdapter.js +5 -0
  141. package/modules/bridBidAdapter.js +223 -0
  142. package/modules/categoryTranslation.js +3 -2
  143. package/modules/consentManagement.js +12 -86
  144. package/modules/consentManagementGpp.js +47 -126
  145. package/modules/consentManagementUsp.js +19 -97
  146. package/modules/gppControl_usnat.js +11 -0
  147. package/modules/intentIqIdSystem.js +6 -5
  148. package/modules/liveIntentIdSystem.js +8 -3
  149. package/modules/mediasquareBidAdapter.js +19 -23
  150. package/modules/oxxionRtdProvider.js +124 -11
  151. package/modules/oxxionRtdProvider.md +19 -4
  152. package/modules/tripleliftBidAdapter.js +21 -1
  153. package/modules/userId/eids.js +29 -0
  154. package/modules/userId/eids.md +19 -2
  155. package/modules/userId/index.js +78 -29
  156. package/modules/userId/userId.md +3 -0
  157. package/package.json +1 -1
  158. package/src/activities/params.js +4 -1
  159. package/test/spec/libraries/cmp/cmpClient_spec.js +233 -0
  160. package/test/spec/libraries/mspa/activityControls_spec.js +315 -0
  161. package/test/spec/modules/admanBidAdapter_spec.js +8 -2
  162. package/test/spec/modules/adqueryBidAdapter_spec.js +5 -1
  163. package/test/spec/modules/bridBidAdapter_spec.js +129 -0
  164. package/test/spec/modules/byDataAnalyticsAdapter_spec.js +9 -7
  165. package/test/spec/modules/chtnwBidAdapter_spec.js +4 -1
  166. package/test/spec/modules/consentManagementGpp_spec.js +84 -7
  167. package/test/spec/modules/consentManagement_spec.js +8 -18
  168. package/test/spec/modules/datablocksBidAdapter_spec.js +7 -3
  169. package/test/spec/modules/eids_spec.js +87 -0
  170. package/test/spec/modules/insticatorBidAdapter_spec.js +6 -2
  171. package/test/spec/modules/intentIqIdSystem_spec.js +36 -2
  172. package/test/spec/modules/ixBidAdapter_spec.js +40 -12
  173. package/test/spec/modules/lassoBidAdapter_spec.js +6 -4
  174. package/test/spec/modules/liveIntentIdMinimalSystem_spec.js +17 -2
  175. package/test/spec/modules/liveIntentIdSystem_spec.js +11 -6
  176. package/test/spec/modules/mediasquareBidAdapter_spec.js +3 -0
  177. package/test/spec/modules/onetagBidAdapter_spec.js +81 -75
  178. package/test/spec/modules/orbidderBidAdapter_spec.js +6 -3
  179. package/test/spec/modules/oxxionRtdProvider_spec.js +113 -1
  180. package/test/spec/modules/relaidoBidAdapter_spec.js +4 -3
  181. package/test/spec/modules/tripleliftBidAdapter_spec.js +20 -1
  182. package/test/spec/modules/ucfunnelBidAdapter_spec.js +37 -16
  183. package/test/spec/modules/userId_spec.js +393 -6
@@ -7,10 +7,12 @@
7
7
  import {deepSetValue, isNumber, isPlainObject, isStr, logError, logInfo, logWarn} from '../src/utils.js';
8
8
  import {config} from '../src/config.js';
9
9
  import {gppDataHandler} from '../src/adapterManager.js';
10
- import {includes} from '../src/polyfill.js';
11
10
  import {timedAuctionHook} from '../src/utils/perfMetrics.js';
12
11
  import { enrichFPD } from '../src/fpd/enrichment.js';
13
12
  import {getGlobal} from '../src/prebidGlobal.js';
13
+ import {cmpClient} from '../libraries/cmp/cmpClient.js';
14
+ import {GreedyPromise} from '../src/utils/promise.js';
15
+ import {buildActivityParams} from '../src/activities/params.js';
14
16
 
15
17
  const DEFAULT_CMP = 'iab';
16
18
  const DEFAULT_CONSENT_TIMEOUT = 10000;
@@ -18,7 +20,7 @@ const CMP_VERSION = 1;
18
20
 
19
21
  export let userCMP;
20
22
  export let consentTimeout;
21
- export let staticConsentData;
23
+ let staticConsentData;
22
24
 
23
25
  let consentData;
24
26
  let addedConsentHook = false;
@@ -29,28 +31,16 @@ const cmpCallMap = {
29
31
  'static': lookupStaticConsentData
30
32
  };
31
33
 
32
- /**
33
- * This function checks the state of the IAB gppData's applicableSection field (to ensure it's populated and has a valid value).
34
- * section === 0 represents a CMP's default value when CMP is loading, it shoud not be used a real user's section.
35
- *
36
- * TODO --- The initial version of the GPP CMP API spec used this naming convention, but it was later changed as an update to the spec.
37
- * CMPs should adjust their logic to use the new format (applicableSecctions), but that may not be the case with the initial release.
38
- * Added support just in case for this transition period, can likely be removed at a later date...
39
- * @param gppData represents the IAB gppData object
40
- * @returns true|false
41
- */
42
- function checkApplicableSectionIsReady(gppData) {
43
- return gppData && Array.isArray(gppData.applicableSection) && gppData.applicableSection.length > 0 && gppData.applicableSection[0] !== 0;
44
- }
45
-
46
34
  /**
47
35
  * This function checks the state of the IAB gppData's applicableSections field (to ensure it's populated and has a valid value).
48
36
  * section === 0 represents a CMP's default value when CMP is loading, it shoud not be used a real user's section.
49
37
  * @param gppData represents the IAB gppData object
50
- * @returns true|false
38
+ * @returns {Array}
51
39
  */
52
- function checkApplicableSectionsIsReady(gppData) {
53
- return gppData && Array.isArray(gppData.applicableSections) && gppData.applicableSections.length > 0 && gppData.applicableSections[0] !== 0;
40
+ function applicableSections(gppData) {
41
+ return gppData && Array.isArray(gppData.applicableSections) && gppData.applicableSections.length > 0 && gppData.applicableSections[0] !== 0
42
+ ? gppData.applicableSections
43
+ : [];
54
44
  }
55
45
 
56
46
  /**
@@ -68,107 +58,36 @@ function lookupStaticConsentData({onSuccess, onError}) {
68
58
  * @param {function({})} onSuccess acts as a success callback when CMP returns a value; pass along consentObjectfrom CMP
69
59
  * @param {function(string, ...{}?)} cmpError acts as an error callback while interacting with CMP; pass along an error message (string) and any extra error arguments (purely for logging)
70
60
  */
71
- function lookupIabConsent({onSuccess, onError}) {
72
- const cmpApiName = '__gpp';
73
- const cmpCallbacks = {};
74
- let registeredPostMessageResponseListener = false;
75
-
76
- function findCMP() {
77
- let f = window;
78
- let cmpFrame;
79
- let cmpDirectAccess = false;
80
- while (true) {
81
- try {
82
- if (typeof f[cmpApiName] === 'function') {
83
- cmpFrame = f;
84
- cmpDirectAccess = true;
85
- break;
86
- }
87
- } catch (e) {}
88
-
89
- // need separate try/catch blocks due to the exception errors thrown when trying to check for a frame that doesn't exist in 3rd party env
90
- try {
91
- if (f.frames['__gppLocator']) {
92
- cmpFrame = f;
93
- break;
94
- }
95
- } catch (e) {}
96
-
97
- if (f === window.top) break;
98
- f = f.parent;
99
- }
100
-
101
- return {
102
- cmpFrame,
103
- cmpDirectAccess
104
- };
105
- }
106
-
107
- const {cmpFrame, cmpDirectAccess} = findCMP();
108
-
109
- if (!cmpFrame) {
61
+ export function lookupIabConsent({onSuccess, onError}, mkClient = cmpClient) {
62
+ const cmp = mkClient({
63
+ apiName: '__gpp',
64
+ apiVersion: CMP_VERSION,
65
+ });
66
+ if (!cmp) {
110
67
  return onError('GPP CMP not found.');
111
68
  }
112
69
 
113
- const invokeCMP = (cmpDirectAccess) ? invokeCMPDirect : invokeCMPFrame;
114
-
115
- function invokeCMPDirect({command, callback, parameter, version = CMP_VERSION}, resultCb) {
116
- if (typeof resultCb === 'function') {
117
- resultCb(cmpFrame[cmpApiName](command, callback, parameter, version));
118
- } else {
119
- cmpFrame[cmpApiName](command, callback, parameter, version);
120
- }
121
- }
122
-
123
- function invokeCMPFrame({command, callback, parameter, version = CMP_VERSION}, resultCb) {
124
- const callName = `${cmpApiName}Call`;
125
- if (!registeredPostMessageResponseListener) {
126
- // when we get the return message, call the stashed callback;
127
- window.addEventListener('message', readPostMessageResponse, false);
128
- registeredPostMessageResponseListener = true;
129
- }
130
-
131
- // call CMP via postMessage
132
- const callId = Math.random().toString();
133
- const msg = {
134
- [callName]: {
135
- command: command,
136
- parameter,
137
- version,
138
- callId: callId
139
- }
140
- };
141
-
142
- // TODO? - add logic to check if random was already used in the same session, and roll another if so?
143
- cmpCallbacks[callId] = (typeof callback === 'function') ? callback : resultCb;
144
- cmpFrame.postMessage(msg, '*');
145
-
146
- function readPostMessageResponse(event) {
147
- const cmpDataPkgName = `${cmpApiName}Return`;
148
- const json = (typeof event.data === 'string' && event.data.includes(cmpDataPkgName)) ? JSON.parse(event.data) : event.data;
149
- if (json[cmpDataPkgName] && json[cmpDataPkgName].callId) {
150
- const payload = json[cmpDataPkgName];
151
-
152
- if (cmpCallbacks.hasOwnProperty(payload.callId)) {
153
- cmpCallbacks[payload.callId](payload.returnValue);
154
- }
155
- }
156
- }
157
- }
158
-
159
- const startupMsg = (cmpDirectAccess) ? 'Detected GPP CMP API is directly accessible, calling it now...'
70
+ const startupMsg = (cmp.isDirect) ? 'Detected GPP CMP API is directly accessible, calling it now...'
160
71
  : 'Detected GPP CMP is outside the current iframe where Prebid.js is located, calling it now...';
161
72
  logInfo(startupMsg);
162
73
 
163
- invokeCMP({
74
+ cmp({
164
75
  command: 'addEventListener',
165
76
  callback: function (evt) {
166
77
  if (evt) {
167
- logInfo(`Received a ${(cmpDirectAccess ? 'direct' : 'postmsg')} response from GPP CMP for event`, evt);
78
+ logInfo(`Received a ${(cmp.isDirect ? 'direct' : 'postmsg')} response from GPP CMP for event`, evt);
168
79
  if (evt.eventName === 'sectionChange' || evt.pingData.cmpStatus === 'loaded') {
169
- invokeCMP({command: 'getGPPData'}, function (gppData) {
170
- logInfo(`Received a ${cmpDirectAccess ? 'direct' : 'postmsg'} response from GPP CMP for getGPPData`, gppData);
171
- processCmpData(gppData, {onSuccess, onError});
80
+ cmp({command: 'getGPPData'}).then((gppData) => {
81
+ logInfo(`Received a ${cmp.isDirect ? 'direct' : 'postmsg'} response from GPP CMP for getGPPData`, gppData);
82
+ return GreedyPromise.all(
83
+ (gppData?.pingData?.supportedAPIs || [])
84
+ .map((name) => cmp({command: 'getSection', parameter: name})
85
+ .catch(() => { logError(`Could not retrieve section data for GPP section '${name}'`) })
86
+ .then((res) => [name, res]))
87
+ ).then((sections) => {
88
+ const sectionData = Object.fromEntries(sections.filter(([_, val]) => val != null));
89
+ processCmpData({gppData, sectionData}, {onSuccess, onError});
90
+ })
172
91
  });
173
92
  } else if (evt.pingData.cmpStatus === 'error') {
174
93
  onError('CMP returned with a cmpStatus:error response. Please check CMP setup.');
@@ -199,7 +118,7 @@ function loadConsentData(cb) {
199
118
  }
200
119
  }
201
120
 
202
- if (!includes(Object.keys(cmpCallMap), userCMP)) {
121
+ if (!cmpCallMap.hasOwnProperty(userCMP)) {
203
122
  done(null, false, `GPP CMP framework (${userCMP}) is not a supported framework. Aborting consentManagement module and resuming auction.`);
204
123
  return;
205
124
  }
@@ -219,7 +138,7 @@ function loadConsentData(cb) {
219
138
  }
220
139
  processCmpData(consentData, {
221
140
  onSuccess: continueToAuction,
222
- onError: () => continueToAuction(storeConsentData(undefined))
141
+ onError: () => continueToAuction(storeConsentData())
223
142
  })
224
143
  }
225
144
  if (consentTimeout === 0) {
@@ -281,11 +200,10 @@ export const requestBidsHook = timedAuctionHook('gpp', function requestBidsHook(
281
200
  * If it's bad, we call `onError`
282
201
  * If it's good, then we store the value and call `onSuccess`
283
202
  */
284
- function processCmpData(consentObject, {onSuccess, onError}) {
203
+ function processCmpData(consentData, {onSuccess, onError}) {
285
204
  function checkData() {
286
- const gppString = consentObject && consentObject.gppString;
287
- const gppSection = (checkApplicableSectionsIsReady(consentObject)) ? consentObject.applicableSections
288
- : (checkApplicableSectionIsReady(consentObject)) ? consentObject.applicableSection : [];
205
+ const gppString = consentData?.gppData?.gppString;
206
+ const gppSection = consentData?.gppData?.applicableSections;
289
207
 
290
208
  return !!(
291
209
  (!Array.isArray(gppSection)) ||
@@ -294,25 +212,25 @@ function processCmpData(consentObject, {onSuccess, onError}) {
294
212
  }
295
213
 
296
214
  if (checkData()) {
297
- onError(`CMP returned unexpected value during lookup process.`, consentObject);
215
+ onError(`CMP returned unexpected value during lookup process.`, consentData);
298
216
  } else {
299
- onSuccess(storeConsentData(consentObject));
217
+ onSuccess(storeConsentData(consentData));
300
218
  }
301
219
  }
302
220
 
303
221
  /**
304
222
  * Stores CMP data locally in module to make information available in adaptermanager.js for later in the auction
305
- * @param {object} cmpConsentObject required; an object representing user's consent choices (can be undefined in certain use-cases for this function only)
223
+ * @param {{}} gppData the result of calling a CMP's `getGPPData` (or equivalent)
224
+ * @param {{}} sectionData map from GPP section name to the result of calling a CMP's `getSection` (or equivalent)
306
225
  */
307
- function storeConsentData(cmpConsentObject) {
226
+ export function storeConsentData({gppData, sectionData} = {}) {
308
227
  consentData = {
309
- gppString: (cmpConsentObject) ? cmpConsentObject.gppString : undefined,
310
-
311
- fullGppData: (cmpConsentObject) || undefined,
228
+ gppString: (gppData) ? gppData.gppString : undefined,
229
+ gppData: (gppData) || undefined,
312
230
  };
313
- consentData.applicableSections = (checkApplicableSectionsIsReady(cmpConsentObject)) ? cmpConsentObject.applicableSections
314
- : (checkApplicableSectionIsReady(cmpConsentObject)) ? cmpConsentObject.applicableSection : [];
231
+ consentData.applicableSections = applicableSections(gppData);
315
232
  consentData.apiVersion = CMP_VERSION;
233
+ consentData.sectionData = sectionData;
316
234
  return consentData;
317
235
  }
318
236
 
@@ -353,7 +271,7 @@ export function setConsentConfig(config) {
353
271
 
354
272
  if (userCMP === 'static') {
355
273
  if (isPlainObject(config.consentData)) {
356
- staticConsentData = config.consentData;
274
+ staticConsentData = {gppData: config.consentData, sectionData: config.sectionData};
357
275
  consentTimeout = 0;
358
276
  } else {
359
277
  logError(`consentManagement.gpp config with cmpApi: 'static' did not specify consentData. No consents will be available to adapters.`);
@@ -364,6 +282,9 @@ export function setConsentConfig(config) {
364
282
 
365
283
  if (!addedConsentHook) {
366
284
  getGlobal().requestBids.before(requestBidsHook, 50);
285
+ buildActivityParams.before((next, params) => {
286
+ return next(Object.assign({gppConsent: gppDataHandler.getConsentData()}, params));
287
+ });
367
288
  }
368
289
  addedConsentHook = true;
369
290
  gppDataHandler.enable();
@@ -4,12 +4,13 @@
4
4
  * information and make it available for any USP (CCPA) supported adapters to
5
5
  * read/pass this information to their system.
6
6
  */
7
- import {deepSetValue, isFn, isNumber, isPlainObject, isStr, logError, logInfo, logWarn} from '../src/utils.js';
7
+ import {deepSetValue, isNumber, isPlainObject, isStr, logError, logInfo, logWarn} from '../src/utils.js';
8
8
  import {config} from '../src/config.js';
9
9
  import adapterManager, {uspDataHandler} from '../src/adapterManager.js';
10
10
  import {timedAuctionHook} from '../src/utils/perfMetrics.js';
11
11
  import {getHook} from '../src/hook.js';
12
12
  import {enrichFPD} from '../src/fpd/enrichment.js';
13
+ import {cmpClient} from '../libraries/cmp/cmpClient.js';
13
14
 
14
15
  const DEFAULT_CONSENT_API = 'iab';
15
16
  const DEFAULT_CONSENT_TIMEOUT = 50;
@@ -41,35 +42,6 @@ function lookupStaticConsentData({onSuccess, onError}) {
41
42
  * based on the appropriate result.
42
43
  */
43
44
  function lookupUspConsent({onSuccess, onError}) {
44
- function findUsp() {
45
- let f = window;
46
- let uspapiFrame;
47
- let uspapiFunction;
48
-
49
- while (true) {
50
- try {
51
- if (typeof f.__uspapi === 'function') {
52
- uspapiFunction = f.__uspapi;
53
- uspapiFrame = f;
54
- break;
55
- }
56
- } catch (e) {}
57
-
58
- try {
59
- if (f.frames['__uspapiLocator']) {
60
- uspapiFrame = f;
61
- break;
62
- }
63
- } catch (e) {}
64
- if (f === window.top) break;
65
- f = f.parent;
66
- }
67
- return {
68
- uspapiFrame,
69
- uspapiFunction,
70
- };
71
- }
72
-
73
45
  function handleUspApiResponseCallbacks() {
74
46
  const uspResponse = {};
75
47
 
@@ -92,86 +64,36 @@ function lookupUspConsent({onSuccess, onError}) {
92
64
  }
93
65
 
94
66
  let callbackHandler = handleUspApiResponseCallbacks();
95
- let uspapiCallbacks = {};
96
67
 
97
- let { uspapiFrame, uspapiFunction } = findUsp();
68
+ const cmp = cmpClient({
69
+ apiName: '__uspapi',
70
+ apiVersion: USPAPI_VERSION,
71
+ apiArgs: ['command', 'version', 'callback'],
72
+ });
98
73
 
99
- if (!uspapiFrame) {
74
+ if (!cmp) {
100
75
  return onError('USP CMP not found.');
101
76
  }
102
77
 
103
- function registerDataDelHandler(invoker, arg2) {
104
- try {
105
- invoker('registerDeletion', arg2, adapterManager.callDataDeletionRequest);
106
- } catch (e) {
107
- logError('Error invoking CMP `registerDeletion`:', e);
108
- }
109
- }
110
-
111
- // to collect the consent information from the user, we perform a call to USPAPI
112
- // to collect the user's consent choices represented as a string (via getUSPData)
113
-
114
- // the following code also determines where the USPAPI is located and uses the proper workflow to communicate with it:
115
- // - use the USPAPI locator code to see if USP's located in the current window or an ancestor window.
116
- // - else assume prebid is in an iframe, and use the locator to see if the CMP is located in a higher parent window. This works in cross domain iframes.
117
- // - if USPAPI is not found, the iframe function will call the uspError exit callback to abort the rest of the USPAPI workflow
118
-
119
- if (isFn(uspapiFunction)) {
78
+ if (cmp.isDirect) {
120
79
  logInfo('Detected USP CMP is directly accessible, calling it now...');
121
- uspapiFunction(
122
- 'getUSPData',
123
- USPAPI_VERSION,
124
- callbackHandler.consentDataCallback
125
- );
126
- registerDataDelHandler(uspapiFunction, USPAPI_VERSION);
127
80
  } else {
128
81
  logInfo(
129
82
  'Detected USP CMP is outside the current iframe where Prebid.js is located, calling it now...'
130
83
  );
131
- callUspApiWhileInIframe(
132
- 'getUSPData',
133
- uspapiFrame,
134
- callbackHandler.consentDataCallback
135
- );
136
- registerDataDelHandler(callUspApiWhileInIframe, uspapiFrame);
137
84
  }
138
85
 
139
- let listening = false;
140
-
141
- function callUspApiWhileInIframe(commandName, uspapiFrame, moduleCallback) {
142
- function callUsp(cmd, ver, callback) {
143
- let callId = Math.random() + '';
144
- let msg = {
145
- __uspapiCall: {
146
- command: cmd,
147
- version: ver,
148
- callId: callId,
149
- },
150
- };
151
-
152
- uspapiCallbacks[callId] = callback;
153
- uspapiFrame.postMessage(msg, '*');
154
- };
155
-
156
- /** when we get the return message, call the stashed callback */
157
- if (!listening) {
158
- window.addEventListener('message', readPostMessageResponse, false);
159
- listening = true;
160
- }
161
-
162
- // call uspapi
163
- callUsp(commandName, USPAPI_VERSION, moduleCallback);
86
+ cmp({
87
+ command: 'getUSPData',
88
+ callback: callbackHandler.consentDataCallback
89
+ });
164
90
 
165
- function readPostMessageResponse(event) {
166
- const res = event && event.data && event.data.__uspapiReturn;
167
- if (res && res.callId) {
168
- if (uspapiCallbacks.hasOwnProperty(res.callId)) {
169
- uspapiCallbacks[res.callId](res.returnValue, res.success);
170
- delete uspapiCallbacks[res.callId];
171
- }
172
- }
173
- }
174
- }
91
+ cmp({
92
+ command: 'registerDeletion',
93
+ callback: adapterManager.callDataDeletionRequest
94
+ }).catch(e => {
95
+ logError('Error invoking CMP `registerDeletion`:', e);
96
+ });
175
97
  }
176
98
 
177
99
  /**
@@ -0,0 +1,11 @@
1
+ import {config} from '../src/config.js';
2
+ import {setupRules} from '../libraries/mspa/activityControls.js';
3
+
4
+ let setupDone = false;
5
+
6
+ config.getConfig('consentManagement', (cfg) => {
7
+ if (cfg?.consentManagement?.gpp != null && !setupDone) {
8
+ setupRules('usnat', [7]);
9
+ setupDone = true;
10
+ }
11
+ })
@@ -59,7 +59,7 @@ export function readData(key) {
59
59
  * @param key
60
60
  * @param {string} value IntentIQ ID value to sintentIqIdSystem_spec.jstore
61
61
  */
62
- function storeData(key, value) {
62
+ function storeData(key, value, cookieStorageEnabled = false) {
63
63
  try {
64
64
  logInfo(MODULE_NAME + ': storing data: key=' + key + ' value=' + value);
65
65
 
@@ -68,7 +68,7 @@ function storeData(key, value) {
68
68
  storage.setDataInLocalStorage(key, value);
69
69
  }
70
70
  const expiresStr = (new Date(Date.now() + (PCID_EXPIRY * (60 * 60 * 24 * 1000)))).toUTCString();
71
- if (storage.cookiesAreEnabled()) {
71
+ if (storage.cookiesAreEnabled() && cookieStorageEnabled) {
72
72
  storage.setCookie(key, value, expiresStr, 'LAX');
73
73
  }
74
74
  }
@@ -119,6 +119,7 @@ export const intentIqIdSubmodule = {
119
119
  logError('User ID - intentIqId submodule requires a valid partner to be defined');
120
120
  return;
121
121
  }
122
+ const cookieStorageEnabled = typeof configParams.enableCookieStorage === 'boolean' ? configParams.enableCookieStorage : false
122
123
  if (!FIRST_PARTY_DATA_KEY.includes(configParams.partner)) { FIRST_PARTY_DATA_KEY += '_' + configParams.partner; }
123
124
  let rrttStrtTime = 0;
124
125
 
@@ -127,7 +128,7 @@ export const intentIqIdSubmodule = {
127
128
  if (!firstPartyData || !firstPartyData.pcid || firstPartyData.pcidDate) {
128
129
  const firstPartyId = generateGUID();
129
130
  firstPartyData = { 'pcid': firstPartyId, 'pcidDate': Date.now() };
130
- storeData(FIRST_PARTY_KEY, JSON.stringify(firstPartyData));
131
+ storeData(FIRST_PARTY_KEY, JSON.stringify(firstPartyData), cookieStorageEnabled);
131
132
  }
132
133
 
133
134
  let partnerData = tryParse(readData(FIRST_PARTY_DATA_KEY));
@@ -172,8 +173,8 @@ export const intentIqIdSubmodule = {
172
173
  }
173
174
  if (shouldUpdateLs === true) {
174
175
  partnerData.date = Date.now();
175
- storeData(FIRST_PARTY_KEY, JSON.stringify(firstPartyData));
176
- storeData(FIRST_PARTY_DATA_KEY, JSON.stringify(partnerData));
176
+ storeData(FIRST_PARTY_KEY, JSON.stringify(firstPartyData), cookieStorageEnabled);
177
+ storeData(FIRST_PARTY_DATA_KEY, JSON.stringify(partnerData), cookieStorageEnabled);
177
178
  }
178
179
  callback(respJson.data);
179
180
  } else {
@@ -14,6 +14,7 @@ import {MODULE_TYPE_UID} from '../src/activities/modules.js';
14
14
 
15
15
  const EVENTS_TOPIC = 'pre_lips'
16
16
  const MODULE_NAME = 'liveIntentId';
17
+ const LI_PROVIDER_DOMAIN = 'liveintent.com';
17
18
  export const storage = getStorageManager({moduleType: MODULE_TYPE_UID, moduleName: MODULE_NAME});
18
19
  const defaultRequestedAttributes = {'nonId': true}
19
20
  const calls = {
@@ -189,15 +190,19 @@ export const liveIntentIdSubmodule = {
189
190
  // As adapters are applied in lexicographical order, we will always
190
191
  // be overwritten by the 'proper' uid2 module if it is present.
191
192
  if (value.uid2) {
192
- result.uid2 = { 'id': value.uid2 }
193
+ result.uid2 = { 'id': value.uid2, ext: { provider: LI_PROVIDER_DOMAIN } }
193
194
  }
194
195
 
195
196
  if (value.bidswitch) {
196
- result.bidswitch = { 'id': value.bidswitch }
197
+ result.bidswitch = { 'id': value.bidswitch, ext: { provider: LI_PROVIDER_DOMAIN } }
197
198
  }
198
199
 
199
200
  if (value.medianet) {
200
- result.medianet = { 'id': value.medianet }
201
+ result.medianet = { 'id': value.medianet, ext: { provider: LI_PROVIDER_DOMAIN } }
202
+ }
203
+
204
+ if (value.magnite) {
205
+ result.magnite = { 'id': value.magnite, ext: { provider: LI_PROVIDER_DOMAIN } }
201
206
  }
202
207
 
203
208
  return result
@@ -120,23 +120,17 @@ export const spec = {
120
120
  netRevenue: value['net_revenue'],
121
121
  ttl: value['ttl'],
122
122
  ad: value['ad'],
123
- mediasquare: {
124
- 'bidder': value['bidder'],
125
- 'code': value['code']
126
- },
123
+ mediasquare: {},
127
124
  meta: {
128
125
  'advertiserDomains': value['adomain']
129
126
  }
130
127
  };
131
- if ('context' in value) {
132
- bidResponse['mediasquare']['context'] = value['context'];
133
- }
134
- if ('match' in value) {
135
- bidResponse['mediasquare']['match'] = value['match'];
136
- }
137
- if ('hasConsent' in value) {
138
- bidResponse['mediasquare']['hasConsent'] = value['hasConsent'];
139
- }
128
+ let paramsToSearchFor = ['bidder', 'code', 'match', 'hasConsent', 'context', 'increment'];
129
+ paramsToSearchFor.forEach(param => {
130
+ if (param in value) {
131
+ bidResponse['mediasquare'][param] = value[param];
132
+ }
133
+ });
140
134
  if ('native' in value) {
141
135
  bidResponse['native'] = value['native'];
142
136
  bidResponse['mediaType'] = 'native';
@@ -180,21 +174,23 @@ export const spec = {
180
174
  }
181
175
  let params = { pbjs: '$prebid.version$', referer: encodeURIComponent(getRefererInfo().page || getRefererInfo().topmostLocation) };
182
176
  let endpoint = document.location.search.match(/msq_test=true/) ? BIDDER_URL_TEST : BIDDER_URL_PROD;
183
- let paramsToSearchFor = ['bidder', 'code', 'match', 'hasConsent', 'context'];
177
+ let paramsToSearchFor = ['bidder', 'code', 'match', 'hasConsent', 'context', 'increment'];
184
178
  if (bid.hasOwnProperty('mediasquare')) {
185
- for (let i = 0; i < paramsToSearchFor.length; i++) {
186
- if (bid['mediasquare'].hasOwnProperty(paramsToSearchFor[i])) {
187
- params[paramsToSearchFor[i]] = bid['mediasquare'][paramsToSearchFor[i]];
179
+ paramsToSearchFor.forEach(param => {
180
+ if (bid['mediasquare'].hasOwnProperty(param)) {
181
+ params[param] = bid['mediasquare'][param];
188
182
  }
189
- }
183
+ });
190
184
  };
191
185
  paramsToSearchFor = ['cpm', 'size', 'mediaType', 'currency', 'creativeId', 'adUnitCode', 'timeToRespond', 'requestId', 'auctionId', 'originalCpm', 'originalCurrency'];
192
- for (let i = 0; i < paramsToSearchFor.length; i++) {
193
- if (bid.hasOwnProperty(paramsToSearchFor[i])) {
194
- params[paramsToSearchFor[i]] = bid[paramsToSearchFor[i]];
195
- if (typeof params[paramsToSearchFor[i]] == 'number') { params[paramsToSearchFor[i]] = params[paramsToSearchFor[i]].toString() }
186
+ paramsToSearchFor.forEach(param => {
187
+ if (bid.hasOwnProperty(param)) {
188
+ params[param] = bid[param];
189
+ if (typeof params[param] == 'number') {
190
+ params[param] = params[param].toString();
191
+ }
196
192
  }
197
- }
193
+ });
198
194
  ajax(endpoint + BIDDER_ENDPOINT_WINNING, null, JSON.stringify(params), {method: 'POST', withCredentials: true});
199
195
  return true;
200
196
  }