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.
- package/.devcontainer/devcontainer.json +3 -1
- package/dist/33acrossBidAdapter.js +1 -1
- package/dist/33acrossIdSystem.js +1 -1
- package/dist/adagioBidAdapter.js +1 -1
- package/dist/adbookpspBidAdapter.js +1 -1
- package/dist/adgenerationBidAdapter.js +1 -1
- package/dist/admanBidAdapter.js +1 -1
- package/dist/adqueryBidAdapter.js +1 -1
- package/dist/adrelevantisBidAdapter.js +1 -1
- package/dist/adtrgtmeBidAdapter.js +1 -1
- package/dist/adxcgBidAdapter.js +1 -1
- package/dist/adyoulikeBidAdapter.js +1 -1
- package/dist/ajaBidAdapter.js +1 -1
- package/dist/amxBidAdapter.js +1 -1
- package/dist/amxIdSystem.js +1 -1
- package/dist/appierAnalyticsAdapter.js +1 -1
- package/dist/appnexusBidAdapter.js +1 -1
- package/dist/asoBidAdapter.js +1 -1
- package/dist/axonixBidAdapter.js +1 -1
- package/dist/bidglassBidAdapter.js +1 -1
- package/dist/big-richmediaBidAdapter.js +1 -1
- package/dist/bridBidAdapter.js +1 -0
- package/dist/bridgewellBidAdapter.js +1 -1
- package/dist/brightMountainMediaBidAdapter.js +1 -1
- package/dist/carodaBidAdapter.js +1 -1
- package/dist/categoryTranslation.js +1 -1
- package/dist/chtnwBidAdapter.js +1 -1
- package/dist/cmp.js +1 -0
- package/dist/concertBidAdapter.js +1 -1
- package/dist/connectadBidAdapter.js +1 -1
- package/dist/consentManagement.js +1 -1
- package/dist/consentManagementGpp.js +1 -1
- package/dist/consentManagementUsp.js +1 -1
- package/dist/consumableBidAdapter.js +1 -1
- package/dist/conversantAnalyticsAdapter.js +1 -1
- package/dist/conversantBidAdapter.js +1 -1
- package/dist/craftBidAdapter.js +1 -1
- package/dist/criteoBidAdapter.js +1 -1
- package/dist/cwireBidAdapter.js +1 -1
- package/dist/dependencies.json +12 -0
- package/dist/dspxBidAdapter.js +1 -1
- package/dist/eplanningBidAdapter.js +1 -1
- package/dist/euidIdSystem.js +1 -1
- package/dist/feedadBidAdapter.js +1 -1
- package/dist/finativeBidAdapter.js +1 -1
- package/dist/freewheel-sspBidAdapter.js +1 -1
- package/dist/gmosspBidAdapter.js +1 -1
- package/dist/goldbachBidAdapter.js +1 -1
- package/dist/gppControl_usnat.js +1 -0
- package/dist/greenbidsAnalyticsAdapter.js +1 -1
- package/dist/greenbidsRtdProvider.js +1 -1
- package/dist/gridBidAdapter.js +1 -1
- package/dist/gumgumBidAdapter.js +1 -1
- package/dist/h12mediaBidAdapter.js +1 -1
- package/dist/hypelabBidAdapter.js +1 -1
- package/dist/id5IdSystem.js +1 -1
- package/dist/imdsBidAdapter.js +1 -1
- package/dist/improvedigitalBidAdapter.js +1 -1
- package/dist/insticatorBidAdapter.js +1 -1
- package/dist/intentIqIdSystem.js +1 -1
- package/dist/ixBidAdapter.js +1 -1
- package/dist/justpremiumBidAdapter.js +1 -1
- package/dist/kargoBidAdapter.js +1 -1
- package/dist/konduitAnalyticsAdapter.js +1 -1
- package/dist/kueezBidAdapter.js +1 -1
- package/dist/kueezRtbBidAdapter.js +1 -1
- package/dist/kulturemediaBidAdapter.js +1 -1
- package/dist/lassoBidAdapter.js +1 -1
- package/dist/lifestreetBidAdapter.js +1 -1
- package/dist/liveIntentIdSystem.js +1 -1
- package/dist/logicadBidAdapter.js +1 -1
- package/dist/loglyliftBidAdapter.js +1 -1
- package/dist/magniteAnalyticsAdapter.js +1 -1
- package/dist/malltvAnalyticsAdapter.js +1 -1
- package/dist/marsmediaBidAdapter.js +1 -1
- package/dist/mediafuseBidAdapter.js +1 -1
- package/dist/mediasquareBidAdapter.js +1 -1
- package/dist/mgidBidAdapter.js +1 -1
- package/dist/minutemediaBidAdapter.js +1 -1
- package/dist/minutemediaplusBidAdapter.js +1 -1
- package/dist/mspa.js +1 -0
- package/dist/nexx360BidAdapter.js +1 -1
- package/dist/not-for-prod/prebid.js +136 -132
- package/dist/oguryBidAdapter.js +1 -1
- package/dist/onetagBidAdapter.js +1 -1
- package/dist/ooloAnalyticsAdapter.js +1 -1
- package/dist/optidigitalBidAdapter.js +1 -1
- package/dist/outbrainBidAdapter.js +1 -1
- package/dist/oxxionRtdProvider.js +1 -1
- package/dist/parrableIdSystem.js +1 -1
- package/dist/pixfutureBidAdapter.js +1 -1
- package/dist/prebid-core.js +1 -1
- package/dist/publinkIdSystem.js +1 -1
- package/dist/pubmaticBidAdapter.js +1 -1
- package/dist/pubwiseAnalyticsAdapter.js +1 -1
- package/dist/pxyzBidAdapter.js +1 -1
- package/dist/quantcastBidAdapter.js +1 -1
- package/dist/readpeakBidAdapter.js +1 -1
- package/dist/relaidoBidAdapter.js +1 -1
- package/dist/retailspotBidAdapter.js +1 -1
- package/dist/rhythmoneBidAdapter.js +1 -1
- package/dist/riseBidAdapter.js +1 -1
- package/dist/rubiconBidAdapter.js +1 -1
- package/dist/seedingAllianceBidAdapter.js +1 -1
- package/dist/seedtagBidAdapter.js +1 -1
- package/dist/sharethroughAnalyticsAdapter.js +1 -1
- package/dist/sharethroughBidAdapter.js +1 -1
- package/dist/shinezBidAdapter.js +1 -1
- package/dist/smaatoBidAdapter.js +1 -1
- package/dist/smartadserverBidAdapter.js +1 -1
- package/dist/smartxBidAdapter.js +1 -1
- package/dist/smilewantedBidAdapter.js +1 -1
- package/dist/sonobiBidAdapter.js +1 -1
- package/dist/sovrnAnalyticsAdapter.js +1 -1
- package/dist/sovrnBidAdapter.js +1 -1
- package/dist/sspBCBidAdapter.js +1 -1
- package/dist/stvBidAdapter.js +1 -1
- package/dist/sublimeBidAdapter.js +1 -1
- package/dist/targetVideoBidAdapter.js +1 -1
- package/dist/teadsBidAdapter.js +1 -1
- package/dist/trionBidAdapter.js +1 -1
- package/dist/tripleliftBidAdapter.js +1 -1
- package/dist/ttdBidAdapter.js +1 -1
- package/dist/ucfunnelAnalyticsAdapter.js +1 -1
- package/dist/uid2IdSystem.js +1 -1
- package/dist/underdogmediaBidAdapter.js +1 -1
- package/dist/undertoneBidAdapter.js +1 -1
- package/dist/userId.js +1 -1
- package/dist/vidazooBidAdapter.js +1 -1
- package/dist/videobyteBidAdapter.js +1 -1
- package/dist/visxBidAdapter.js +1 -1
- package/dist/vuukleBidAdapter.js +1 -1
- package/dist/widespaceBidAdapter.js +1 -1
- package/dist/winrBidAdapter.js +1 -1
- package/dist/yahoosspBidAdapter.js +1 -1
- package/dist/yieldmoBidAdapter.js +1 -1
- package/dist/yieldoneAnalyticsAdapter.js +1 -1
- package/libraries/cmp/cmpClient.js +139 -0
- package/libraries/mspa/activityControls.js +91 -0
- package/modules/admanBidAdapter.js +5 -0
- package/modules/bridBidAdapter.js +223 -0
- package/modules/categoryTranslation.js +3 -2
- package/modules/consentManagement.js +12 -86
- package/modules/consentManagementGpp.js +47 -126
- package/modules/consentManagementUsp.js +19 -97
- package/modules/gppControl_usnat.js +11 -0
- package/modules/intentIqIdSystem.js +6 -5
- package/modules/liveIntentIdSystem.js +8 -3
- package/modules/mediasquareBidAdapter.js +19 -23
- package/modules/oxxionRtdProvider.js +124 -11
- package/modules/oxxionRtdProvider.md +19 -4
- package/modules/tripleliftBidAdapter.js +21 -1
- package/modules/userId/eids.js +29 -0
- package/modules/userId/eids.md +19 -2
- package/modules/userId/index.js +78 -29
- package/modules/userId/userId.md +3 -0
- package/package.json +1 -1
- package/src/activities/params.js +4 -1
- package/test/spec/libraries/cmp/cmpClient_spec.js +233 -0
- package/test/spec/libraries/mspa/activityControls_spec.js +315 -0
- package/test/spec/modules/admanBidAdapter_spec.js +8 -2
- package/test/spec/modules/adqueryBidAdapter_spec.js +5 -1
- package/test/spec/modules/bridBidAdapter_spec.js +129 -0
- package/test/spec/modules/byDataAnalyticsAdapter_spec.js +9 -7
- package/test/spec/modules/chtnwBidAdapter_spec.js +4 -1
- package/test/spec/modules/consentManagementGpp_spec.js +84 -7
- package/test/spec/modules/consentManagement_spec.js +8 -18
- package/test/spec/modules/datablocksBidAdapter_spec.js +7 -3
- package/test/spec/modules/eids_spec.js +87 -0
- package/test/spec/modules/insticatorBidAdapter_spec.js +6 -2
- package/test/spec/modules/intentIqIdSystem_spec.js +36 -2
- package/test/spec/modules/ixBidAdapter_spec.js +40 -12
- package/test/spec/modules/lassoBidAdapter_spec.js +6 -4
- package/test/spec/modules/liveIntentIdMinimalSystem_spec.js +17 -2
- package/test/spec/modules/liveIntentIdSystem_spec.js +11 -6
- package/test/spec/modules/mediasquareBidAdapter_spec.js +3 -0
- package/test/spec/modules/onetagBidAdapter_spec.js +81 -75
- package/test/spec/modules/orbidderBidAdapter_spec.js +6 -3
- package/test/spec/modules/oxxionRtdProvider_spec.js +113 -1
- package/test/spec/modules/relaidoBidAdapter_spec.js +4 -3
- package/test/spec/modules/tripleliftBidAdapter_spec.js +20 -1
- package/test/spec/modules/ucfunnelBidAdapter_spec.js +37 -16
- 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
|
-
|
|
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
|
|
38
|
+
* @returns {Array}
|
|
51
39
|
*/
|
|
52
|
-
function
|
|
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
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
|
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
|
-
|
|
74
|
+
cmp({
|
|
164
75
|
command: 'addEventListener',
|
|
165
76
|
callback: function (evt) {
|
|
166
77
|
if (evt) {
|
|
167
|
-
logInfo(`Received a ${(
|
|
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
|
-
|
|
170
|
-
logInfo(`Received a ${
|
|
171
|
-
|
|
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 (!
|
|
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(
|
|
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(
|
|
203
|
+
function processCmpData(consentData, {onSuccess, onError}) {
|
|
285
204
|
function checkData() {
|
|
286
|
-
const gppString =
|
|
287
|
-
const gppSection =
|
|
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.`,
|
|
215
|
+
onError(`CMP returned unexpected value during lookup process.`, consentData);
|
|
298
216
|
} else {
|
|
299
|
-
onSuccess(storeConsentData(
|
|
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 {
|
|
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(
|
|
226
|
+
export function storeConsentData({gppData, sectionData} = {}) {
|
|
308
227
|
consentData = {
|
|
309
|
-
gppString: (
|
|
310
|
-
|
|
311
|
-
fullGppData: (cmpConsentObject) || undefined,
|
|
228
|
+
gppString: (gppData) ? gppData.gppString : undefined,
|
|
229
|
+
gppData: (gppData) || undefined,
|
|
312
230
|
};
|
|
313
|
-
consentData.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,
|
|
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
|
-
|
|
68
|
+
const cmp = cmpClient({
|
|
69
|
+
apiName: '__uspapi',
|
|
70
|
+
apiVersion: USPAPI_VERSION,
|
|
71
|
+
apiArgs: ['command', 'version', 'callback'],
|
|
72
|
+
});
|
|
98
73
|
|
|
99
|
-
if (!
|
|
74
|
+
if (!cmp) {
|
|
100
75
|
return onError('USP CMP not found.');
|
|
101
76
|
}
|
|
102
77
|
|
|
103
|
-
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
|
|
186
|
-
if (bid['mediasquare'].hasOwnProperty(
|
|
187
|
-
params[
|
|
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
|
-
|
|
193
|
-
if (bid.hasOwnProperty(
|
|
194
|
-
params[
|
|
195
|
-
if (typeof params[
|
|
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
|
}
|