prebid.js 8.7.0 → 8.8.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/dist/33acrossBidAdapter.js +1 -1
- package/dist/33acrossIdSystem.js +1 -1
- package/dist/a1MediaRtdProvider.js +1 -1
- package/dist/adagioBidAdapter.js +1 -1
- package/dist/adbookpspBidAdapter.js +1 -1
- package/dist/adgenerationBidAdapter.js +1 -1
- package/dist/admaticBidAdapter.js +1 -1
- package/dist/adqueryBidAdapter.js +1 -1
- package/dist/adqueryIdSystem.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/bidViewability.js +1 -1
- package/dist/bidglassBidAdapter.js +1 -1
- package/dist/big-richmediaBidAdapter.js +1 -1
- package/dist/brandmetricsRtdProvider.js +1 -1
- package/dist/bridBidAdapter.js +1 -1
- package/dist/bridgewellBidAdapter.js +1 -1
- package/dist/brightMountainMediaBidAdapter.js +1 -1
- package/dist/carodaBidAdapter.js +1 -1
- package/dist/chtnwBidAdapter.js +1 -1
- package/dist/concertBidAdapter.js +1 -1
- package/dist/connectadBidAdapter.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 +4 -1
- 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/geoedgeRtdProvider.js +1 -1
- package/dist/gmosspBidAdapter.js +1 -1
- package/dist/goldbachBidAdapter.js +1 -1
- 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/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/nativoBidAdapter.js +1 -1
- package/dist/nexx360BidAdapter.js +1 -1
- package/dist/not-for-prod/prebid.js +138 -137
- package/dist/oguryBidAdapter.js +1 -1
- package/dist/onetagBidAdapter.js +1 -1
- package/dist/ooloAnalyticsAdapter.js +1 -1
- package/dist/operaadsBidAdapter.js +1 -1
- package/dist/operaadsIdSystem.js +1 -0
- package/dist/optidigitalBidAdapter.js +1 -1
- package/dist/outbrainBidAdapter.js +1 -1
- package/dist/oxxionAnalyticsAdapter.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/smartyadsBidAdapter.js +1 -1
- package/dist/smilewantedBidAdapter.js +1 -1
- package/dist/snigelBidAdapter.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/topicsFpdModule.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/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/integrationExamples/topics/topics-server.js +72 -0
- package/modules/.submodules.json +2 -1
- package/modules/a1MediaRtdProvider.js +1 -1
- package/modules/admaticBidAdapter.js +5 -0
- package/modules/adqueryBidAdapter.js +23 -21
- package/modules/adqueryIdSystem.js +45 -30
- package/modules/adrelevantisBidAdapter.js +2 -0
- package/modules/bidViewability.js +7 -0
- package/modules/bidViewability.md +9 -8
- package/modules/brandmetricsRtdProvider.js +30 -27
- package/modules/criteoBidAdapter.js +66 -43
- package/modules/geoedgeRtdProvider.js +43 -13
- package/modules/geoedgeRtdProvider.md +2 -1
- package/modules/liveIntentIdSystem.js +16 -1
- package/modules/nativoBidAdapter.js +21 -3
- package/modules/onetagBidAdapter.js +3 -0
- package/modules/operaadsBidAdapter.js +5 -0
- package/modules/operaadsBidAdapter.md +5 -5
- package/modules/operaadsIdSystem.js +106 -0
- package/modules/operaadsIdSystem.md +52 -0
- package/modules/oxxionAnalyticsAdapter.js +22 -5
- package/modules/rubiconBidAdapter.js +2 -2
- package/modules/smartyadsBidAdapter.js +18 -1
- package/modules/snigelBidAdapter.js +69 -16
- package/modules/snigelBidAdapter.md +9 -3
- package/modules/topicsFpdModule.js +35 -9
- package/modules/visxBidAdapter.js +51 -1
- package/package.json +2 -2
- package/src/adloader.js +1 -0
- package/src/native.js +2 -2
- package/test/spec/modules/admaticBidAdapter_spec.js +5 -0
- package/test/spec/modules/adqueryIdSystem_spec.js +13 -24
- package/test/spec/modules/bidViewability_spec.js +32 -1
- package/test/spec/modules/brandmetricsRtdProvider_spec.js +6 -0
- package/test/spec/modules/criteoBidAdapter_spec.js +228 -0
- package/test/spec/modules/eids_spec.js +48 -0
- package/test/spec/modules/geoedgeRtdProvider_spec.js +44 -24
- package/test/spec/modules/liveIntentIdMinimalSystem_spec.js +5 -0
- package/test/spec/modules/liveIntentIdSystem_spec.js +5 -0
- package/test/spec/modules/nativoBidAdapter_spec.js +6 -1
- package/test/spec/modules/onetagBidAdapter_spec.js +69 -0
- package/test/spec/modules/operaadsIdSystem_spec.js +53 -0
- package/test/spec/modules/oxxionAnalyticsAdapter_spec.js +6 -1
- package/test/spec/modules/rubiconBidAdapter_spec.js +24 -0
- package/test/spec/modules/smartyadsBidAdapter_spec.js +49 -0
- package/test/spec/modules/snigelBidAdapter_spec.js +57 -6
- package/test/spec/modules/topicsFpdModule_spec.js +102 -1
- package/test/spec/modules/visxBidAdapter_spec.js +151 -1
- package/test/spec/native_spec.js +5 -3
|
@@ -20,6 +20,8 @@ import { ajax } from '../src/ajax.js';
|
|
|
20
20
|
import { generateUUID, insertElement, isEmpty, logError } from '../src/utils.js';
|
|
21
21
|
import * as events from '../src/events.js';
|
|
22
22
|
import CONSTANTS from '../src/constants.json';
|
|
23
|
+
import { loadExternalScript } from '../src/adloader.js';
|
|
24
|
+
import { auctionManager } from '../src/auctionManager.js';
|
|
23
25
|
|
|
24
26
|
/** @type {string} */
|
|
25
27
|
const SUBMODULE_NAME = 'geoedge';
|
|
@@ -33,9 +35,13 @@ const PV_ID = generateUUID();
|
|
|
33
35
|
/** @type {string} */
|
|
34
36
|
const HOST_NAME = 'https://rumcdn.geoedge.be';
|
|
35
37
|
/** @type {string} */
|
|
36
|
-
const
|
|
38
|
+
const FILE_NAME_CLIENT = 'grumi.js';
|
|
39
|
+
/** @type {string} */
|
|
40
|
+
const FILE_NAME_INPAGE = 'grumi-ip.js';
|
|
41
|
+
/** @type {function} */
|
|
42
|
+
export let getClientUrl = (key) => `${HOST_NAME}/${key}/${FILE_NAME_CLIENT}`;
|
|
37
43
|
/** @type {function} */
|
|
38
|
-
export let
|
|
44
|
+
export let getInPageUrl = (key) => `${HOST_NAME}/${key}/${FILE_NAME_INPAGE}`;
|
|
39
45
|
/** @type {string} */
|
|
40
46
|
export let wrapper
|
|
41
47
|
/** @type {boolean} */;
|
|
@@ -177,7 +183,8 @@ function isSupportedBidder(bidder, paramsBidders) {
|
|
|
177
183
|
function shouldWrap(bid, params) {
|
|
178
184
|
let supportedBidder = isSupportedBidder(bid.bidderCode, params.bidders);
|
|
179
185
|
let donePreload = params.wap ? preloaded : true;
|
|
180
|
-
|
|
186
|
+
let isGPT = params.gpt;
|
|
187
|
+
return wrapperReady && supportedBidder && donePreload && !isGPT;
|
|
181
188
|
}
|
|
182
189
|
|
|
183
190
|
function conditionallyWrap(bidResponse, config, userConsent) {
|
|
@@ -187,31 +194,55 @@ function conditionallyWrap(bidResponse, config, userConsent) {
|
|
|
187
194
|
}
|
|
188
195
|
}
|
|
189
196
|
|
|
197
|
+
function isBillingMessage(data, params) {
|
|
198
|
+
return data.key === params.key && data.impression;
|
|
199
|
+
}
|
|
200
|
+
|
|
190
201
|
/**
|
|
191
|
-
* Fire billable events
|
|
202
|
+
* Fire billable events when our client sends a message
|
|
203
|
+
* Messages will be sent only when:
|
|
204
|
+
* a. applicable bids are wrapped
|
|
205
|
+
* b. our code laoded and executed sucesfully
|
|
192
206
|
*/
|
|
193
207
|
function fireBillableEventsForApplicableBids(params) {
|
|
194
|
-
|
|
195
|
-
|
|
208
|
+
window.addEventListener('message', function (message) {
|
|
209
|
+
let data = message.data;
|
|
210
|
+
if (isBillingMessage(data, params)) {
|
|
211
|
+
let winningBid = auctionManager.findBidByAdId(data.adId);
|
|
196
212
|
events.emit(CONSTANTS.EVENTS.BILLABLE_EVENT, {
|
|
197
213
|
vendor: SUBMODULE_NAME,
|
|
198
|
-
billingId:
|
|
199
|
-
type: 'impression',
|
|
200
|
-
transactionId: winningBid.transactionId,
|
|
201
|
-
auctionId: winningBid.auctionId,
|
|
202
|
-
bidId: winningBid.requestId
|
|
214
|
+
billingId: data.impressionId,
|
|
215
|
+
type: winningBid ? 'impression' : data.type,
|
|
216
|
+
transactionId: winningBid?.transactionId || data.transactionId,
|
|
217
|
+
auctionId: winningBid?.auctionId || data.auctionId,
|
|
218
|
+
bidId: winningBid?.requestId || data.requestId
|
|
203
219
|
});
|
|
204
220
|
}
|
|
205
221
|
});
|
|
206
222
|
}
|
|
207
223
|
|
|
224
|
+
/**
|
|
225
|
+
* Loads Geoedge in page script that monitors all ad slots created by GPT
|
|
226
|
+
* @param {Object} params
|
|
227
|
+
*/
|
|
228
|
+
function setupInPage(params) {
|
|
229
|
+
window.grumi = params;
|
|
230
|
+
window.grumi.fromPrebid = true;
|
|
231
|
+
loadExternalScript(getInPageUrl(params.key), SUBMODULE_NAME);
|
|
232
|
+
}
|
|
233
|
+
|
|
208
234
|
function init(config, userConsent) {
|
|
209
235
|
let params = config.params;
|
|
210
236
|
if (!params || !params.key) {
|
|
211
237
|
logError('missing key for geoedge RTD module provider');
|
|
212
238
|
return false;
|
|
213
239
|
}
|
|
214
|
-
|
|
240
|
+
if (params.gpt) {
|
|
241
|
+
setupInPage(params);
|
|
242
|
+
} else {
|
|
243
|
+
fetchWrapper(setWrapper);
|
|
244
|
+
preloadClient(params.key);
|
|
245
|
+
}
|
|
215
246
|
fireBillableEventsForApplicableBids(params);
|
|
216
247
|
return true;
|
|
217
248
|
}
|
|
@@ -228,7 +259,6 @@ export const geoedgeSubmodule = {
|
|
|
228
259
|
};
|
|
229
260
|
|
|
230
261
|
export function beforeInit() {
|
|
231
|
-
fetchWrapper(setWrapper);
|
|
232
262
|
submodule('realTimeData', geoedgeSubmodule);
|
|
233
263
|
}
|
|
234
264
|
|
|
@@ -5,7 +5,7 @@ Module Type: Rtd Provider
|
|
|
5
5
|
Maintainer: guy.books@geoedge.com
|
|
6
6
|
|
|
7
7
|
The Geoedge Realtime module lets publishers block bad ads such as automatic redirects, malware, offensive creatives and landing pages.
|
|
8
|
-
To use this module, you'll need to work with [Geoedge](https://www.geoedge.com/publishers-real-time-protection/) to get an account and
|
|
8
|
+
To use this module, you'll need to work with [Geoedge](https://www.geoedge.com/publishers-real-time-protection/) to get an account and customer key.
|
|
9
9
|
|
|
10
10
|
## Integration
|
|
11
11
|
|
|
@@ -49,6 +49,7 @@ Parameters details:
|
|
|
49
49
|
|params.key | String | Customer key |Required, contact Geoedge to get your key |
|
|
50
50
|
|params.bidders | Object | Bidders to monitor |Optional, list of bidder to include / exclude from monitoring. Omitting this will monitor bids from all bidders. |
|
|
51
51
|
|params.wap |Boolean |Wrap after preload |Optional, defaults to `false`. Set to `true` if you want to monitor only after the module has preloaded the monitoring client. |
|
|
52
|
+
|params.gpt |Boolean |Wrap all GPT ad slots |Optional, defaults to `false`. Set to `true` if you want to monitor all Google Publisher Tag ad slots, regaedless if the winning bid comes from Prebid or Google Ad Manager (Direct, Adx, Adesnse, Open Bidding, etc). |
|
|
52
53
|
|
|
53
54
|
## Example
|
|
54
55
|
|
|
@@ -205,6 +205,10 @@ export const liveIntentIdSubmodule = {
|
|
|
205
205
|
result.magnite = { 'id': value.magnite, ext: { provider: LI_PROVIDER_DOMAIN } }
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
+
if (value.index) {
|
|
209
|
+
result.index = { 'id': value.index, ext: { provider: LI_PROVIDER_DOMAIN } }
|
|
210
|
+
}
|
|
211
|
+
|
|
208
212
|
return result
|
|
209
213
|
}
|
|
210
214
|
|
|
@@ -294,7 +298,18 @@ export const liveIntentIdSubmodule = {
|
|
|
294
298
|
}
|
|
295
299
|
}
|
|
296
300
|
},
|
|
297
|
-
|
|
301
|
+
'index': {
|
|
302
|
+
source: 'liveintent.indexexchange.com',
|
|
303
|
+
atype: 3,
|
|
304
|
+
getValue: function(data) {
|
|
305
|
+
return data.id;
|
|
306
|
+
},
|
|
307
|
+
getUidExt: function(data) {
|
|
308
|
+
if (data.ext) {
|
|
309
|
+
return data.ext;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
298
313
|
}
|
|
299
314
|
};
|
|
300
315
|
|
|
@@ -2,7 +2,20 @@ import { deepAccess, isEmpty } from '../src/utils.js'
|
|
|
2
2
|
import { registerBidder } from '../src/adapters/bidderFactory.js'
|
|
3
3
|
import { BANNER } from '../src/mediaTypes.js'
|
|
4
4
|
import { getGlobal } from '../src/prebidGlobal.js'
|
|
5
|
-
|
|
5
|
+
import { ortbConverter } from '../libraries/ortbConverter/converter.js'
|
|
6
|
+
|
|
7
|
+
const converter = ortbConverter({
|
|
8
|
+
context: {
|
|
9
|
+
// `netRevenue` and `ttl` are required properties of bid responses - provide a default for them
|
|
10
|
+
netRevenue: true, // or false if your adapter should set bidResponse.netRevenue = false
|
|
11
|
+
ttl: 30 // default bidResponse.ttl (when not specified in ORTB response.seatbid[].bid[].exp)
|
|
12
|
+
},
|
|
13
|
+
imp(buildImp, bidRequest, context) {
|
|
14
|
+
const imp = buildImp(bidRequest, context);
|
|
15
|
+
imp.tagid = bidRequest.adUnitCode
|
|
16
|
+
return imp;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
6
19
|
|
|
7
20
|
const BIDDER_CODE = 'nativo'
|
|
8
21
|
const BIDDER_ENDPOINT = 'https://exchange.postrelease.com/prebid'
|
|
@@ -136,6 +149,10 @@ export const spec = {
|
|
|
136
149
|
* @return ServerRequest Info describing the request to the server.
|
|
137
150
|
*/
|
|
138
151
|
buildRequests: function (validBidRequests, bidderRequest) {
|
|
152
|
+
// Get OpenRTB Data
|
|
153
|
+
const openRTBData = converter.toORTB({bidRequests: validBidRequests, bidderRequest})
|
|
154
|
+
const openRTBDataString = JSON.stringify(openRTBData)
|
|
155
|
+
|
|
139
156
|
const requestData = new RequestData()
|
|
140
157
|
requestData.addBidRequestDataSource(new UserEIDs())
|
|
141
158
|
|
|
@@ -271,8 +288,9 @@ export const spec = {
|
|
|
271
288
|
const requestUrl = buildRequestUrl(BIDDER_ENDPOINT, qsParamStrings)
|
|
272
289
|
|
|
273
290
|
let serverRequest = {
|
|
274
|
-
method: '
|
|
275
|
-
url: requestUrl
|
|
291
|
+
method: 'POST',
|
|
292
|
+
url: requestUrl,
|
|
293
|
+
data: openRTBDataString,
|
|
276
294
|
}
|
|
277
295
|
|
|
278
296
|
return serverRequest
|
|
@@ -70,6 +70,9 @@ function buildRequests(validBidRequests, bidderRequest) {
|
|
|
70
70
|
if (bidderRequest && bidderRequest.uspConsent) {
|
|
71
71
|
payload.usPrivacy = bidderRequest.uspConsent;
|
|
72
72
|
}
|
|
73
|
+
if (bidderRequest && bidderRequest.ortb2) {
|
|
74
|
+
payload.ortb2 = bidderRequest.ortb2;
|
|
75
|
+
}
|
|
73
76
|
if (validBidRequests && validBidRequests.length !== 0 && validBidRequests[0].userIdAsEids) {
|
|
74
77
|
payload.userId = validBidRequests[0].userIdAsEids;
|
|
75
78
|
}
|
|
@@ -680,6 +680,11 @@ function mapNativeImage(image, type) {
|
|
|
680
680
|
* @returns {String} userId
|
|
681
681
|
*/
|
|
682
682
|
function getUserId(bidRequest) {
|
|
683
|
+
let operaId = deepAccess(bidRequest, 'userId.operaId');
|
|
684
|
+
if (operaId) {
|
|
685
|
+
return operaId;
|
|
686
|
+
}
|
|
687
|
+
|
|
683
688
|
let sharedId = deepAccess(bidRequest, 'userId.sharedid.id');
|
|
684
689
|
if (sharedId) {
|
|
685
690
|
return sharedId;
|
|
@@ -135,18 +135,18 @@ var adUnits = [{
|
|
|
135
135
|
|
|
136
136
|
### User Ids
|
|
137
137
|
|
|
138
|
-
Opera Ads Bid Adapter uses `
|
|
138
|
+
Opera Ads Bid Adapter uses `operaId`, please refer to [`Opera ID System`](./operaadsIdSystem.md).
|
|
139
139
|
|
|
140
140
|
```javascript
|
|
141
141
|
pbjs.setConfig({
|
|
142
142
|
...,
|
|
143
143
|
userSync: {
|
|
144
144
|
userIds: [{
|
|
145
|
-
name: '
|
|
145
|
+
name: 'operaId',
|
|
146
146
|
storage: {
|
|
147
|
-
name: '
|
|
148
|
-
type: '
|
|
149
|
-
expires:
|
|
147
|
+
name: 'operaId',
|
|
148
|
+
type: 'html5',
|
|
149
|
+
expires: 14
|
|
150
150
|
}
|
|
151
151
|
}]
|
|
152
152
|
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This module adds operaId to the User ID module
|
|
3
|
+
* The {@link module:modules/userId} module is required
|
|
4
|
+
* @module modules/operaadsIdSystem
|
|
5
|
+
* @requires module:modules/userId
|
|
6
|
+
*/
|
|
7
|
+
import * as ajax from '../src/ajax.js';
|
|
8
|
+
import { submodule } from '../src/hook.js';
|
|
9
|
+
import { logMessage, logError } from '../src/utils.js';
|
|
10
|
+
|
|
11
|
+
const MODULE_NAME = 'operaId';
|
|
12
|
+
const ID_KEY = MODULE_NAME;
|
|
13
|
+
const version = '1.0';
|
|
14
|
+
const SYNC_URL = 'https://t.adx.opera.com/identity/';
|
|
15
|
+
const AJAX_TIMEOUT = 300;
|
|
16
|
+
const AJAX_OPTIONS = {method: 'GET', withCredentials: true, contentType: 'application/json'};
|
|
17
|
+
|
|
18
|
+
function constructUrl(pairs) {
|
|
19
|
+
const queries = [];
|
|
20
|
+
for (let key in pairs) {
|
|
21
|
+
queries.push(`${key}=${encodeURIComponent(pairs[key])}`);
|
|
22
|
+
}
|
|
23
|
+
return `${SYNC_URL}?${queries.join('&')}`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function asyncRequest(url, cb) {
|
|
27
|
+
ajax.ajaxBuilder(AJAX_TIMEOUT)(
|
|
28
|
+
url,
|
|
29
|
+
{
|
|
30
|
+
success: response => {
|
|
31
|
+
try {
|
|
32
|
+
const jsonResponse = JSON.parse(response);
|
|
33
|
+
const { uid: operaId } = jsonResponse;
|
|
34
|
+
cb(operaId);
|
|
35
|
+
return;
|
|
36
|
+
} catch (e) {
|
|
37
|
+
logError(`${MODULE_NAME}: invalid response`, response);
|
|
38
|
+
}
|
|
39
|
+
cb();
|
|
40
|
+
},
|
|
41
|
+
error: (err) => {
|
|
42
|
+
logError(`${MODULE_NAME}: ID error response`, err);
|
|
43
|
+
cb();
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
null,
|
|
47
|
+
AJAX_OPTIONS
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const operaIdSubmodule = {
|
|
52
|
+
/**
|
|
53
|
+
* used to link submodule with config
|
|
54
|
+
* @type {string}
|
|
55
|
+
*/
|
|
56
|
+
name: MODULE_NAME,
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @type {string}
|
|
60
|
+
*/
|
|
61
|
+
version,
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* decode the stored id value for passing to bid requests
|
|
65
|
+
* @function
|
|
66
|
+
* @param {string} id
|
|
67
|
+
* @returns {{'operaId': string}}
|
|
68
|
+
*/
|
|
69
|
+
decode: (id) =>
|
|
70
|
+
id != null && id.length > 0
|
|
71
|
+
? { [ID_KEY]: id }
|
|
72
|
+
: undefined,
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* performs action to obtain id and return a value in the callback's response argument
|
|
76
|
+
* @function
|
|
77
|
+
* @param {SubmoduleConfig} [config]
|
|
78
|
+
* @returns {IdResponse|undefined}
|
|
79
|
+
*/
|
|
80
|
+
getId(config, consentData) {
|
|
81
|
+
logMessage(`${MODULE_NAME}: start synchronizing opera uid`);
|
|
82
|
+
const params = (config && config.params) || {};
|
|
83
|
+
if (typeof params.pid !== 'string' || params.pid.length == 0) {
|
|
84
|
+
logError(`${MODULE_NAME}: submodule requires a publisher ID to be defined`);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const { pid, syncUrl = SYNC_URL } = params;
|
|
89
|
+
const url = constructUrl(syncUrl, { publisherId: pid });
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
callback: (cb) => {
|
|
93
|
+
asyncRequest(url, cb);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
eids: {
|
|
99
|
+
'operaId': {
|
|
100
|
+
source: 't.adx.opera.com',
|
|
101
|
+
atype: 1
|
|
102
|
+
},
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
submodule('userId', operaIdSubmodule);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Opera ID System
|
|
2
|
+
|
|
3
|
+
For help adding this module, please contact [adtech-prebid-group@opera.com](adtech-prebid-group@opera.com).
|
|
4
|
+
|
|
5
|
+
### Prebid Configuration
|
|
6
|
+
|
|
7
|
+
You should configure this module under your `userSync.userIds[]` configuration:
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
pbjs.setConfig({
|
|
11
|
+
userSync: {
|
|
12
|
+
userIds: [
|
|
13
|
+
{
|
|
14
|
+
name: "operaId",
|
|
15
|
+
storage: {
|
|
16
|
+
name: "operaId",
|
|
17
|
+
type: "html5",
|
|
18
|
+
expires: 14
|
|
19
|
+
},
|
|
20
|
+
params: {
|
|
21
|
+
pid: "your-pulisher-ID-here"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
```
|
|
28
|
+
<br>
|
|
29
|
+
|
|
30
|
+
| Param under `userSync.userIds[]` | Scope | Type | Description | Example |
|
|
31
|
+
| -------------------------------- | -------- | ------ | ----------------------------- | ----------------------------------------- |
|
|
32
|
+
| name | Required | string | ID for the operaId module | `"operaId"` |
|
|
33
|
+
| storage | Optional | Object | Settings for operaId storage | See [storage settings](#storage-settings) |
|
|
34
|
+
| params | Required | Object | Parameters for opreaId module | See [params](#params) |
|
|
35
|
+
<br>
|
|
36
|
+
|
|
37
|
+
### Params
|
|
38
|
+
|
|
39
|
+
| Param under `params` | Scope | Type | Description | Example |
|
|
40
|
+
| -------------------- | -------- | ------ | ------------------------------ | --------------- |
|
|
41
|
+
| pid | Required | string | Publisher ID assigned by Opera | `"pub12345678"` |
|
|
42
|
+
<br>
|
|
43
|
+
|
|
44
|
+
### Storage Settings
|
|
45
|
+
|
|
46
|
+
The following settings are suggested for the `storage` property in the `userSync.userIds[]` object:
|
|
47
|
+
|
|
48
|
+
| Param under `storage` | Type | Description | Example |
|
|
49
|
+
| --------------------- | ------------- | -------------------------------------------------------------------------------- | ----------- |
|
|
50
|
+
| name | String | Where the ID will be stored | `"operaId"` |
|
|
51
|
+
| type | String | For best performance, this should be `"html5"` | `"html5"` |
|
|
52
|
+
| expires | Number <= 30 | number of days until the stored ID expires. **Must be less than or equal to 30** | `14` |
|
|
@@ -21,6 +21,7 @@ let saveEvents = {}
|
|
|
21
21
|
let allEvents = {}
|
|
22
22
|
let auctionEnd = {}
|
|
23
23
|
let initOptions = {}
|
|
24
|
+
let mode = {};
|
|
24
25
|
let endpoint = 'https://default'
|
|
25
26
|
let requestsAttributes = ['adUnitCode', 'auctionId', 'bidder', 'bidderCode', 'bidId', 'cpm', 'creativeId', 'currency', 'width', 'height', 'mediaType', 'netRevenue', 'originalCpm', 'originalCurrency', 'requestId', 'size', 'source', 'status', 'timeToRespond', 'transactionId', 'ttl', 'sizes', 'mediaTypes', 'src', 'params', 'userId', 'labelAny', 'bids', 'adId'];
|
|
26
27
|
|
|
@@ -41,16 +42,27 @@ function filterAttributes(arg, removead) {
|
|
|
41
42
|
}
|
|
42
43
|
if (typeof arg['gdprConsent'] != 'undefined') {
|
|
43
44
|
response['gdprConsent'] = {};
|
|
44
|
-
if (typeof arg['gdprConsent']['consentString'] != 'undefined') {
|
|
45
|
+
if (typeof arg['gdprConsent']['consentString'] != 'undefined') {
|
|
46
|
+
response['gdprConsent']['consentString'] = arg['gdprConsent']['consentString'];
|
|
47
|
+
}
|
|
45
48
|
}
|
|
46
|
-
if (typeof arg['meta'] == 'object'
|
|
47
|
-
response['meta'] = {
|
|
49
|
+
if (typeof arg['meta'] == 'object') {
|
|
50
|
+
response['meta'] = {};
|
|
51
|
+
if (typeof arg['meta']['advertiserDomains'] != 'undefined') {
|
|
52
|
+
response['meta']['advertiserDomains'] = arg['meta']['advertiserDomains'];
|
|
53
|
+
}
|
|
54
|
+
if (typeof arg['meta']['demandSource'] == 'string') {
|
|
55
|
+
response['meta']['demandSource'] = arg['meta']['demandSource'];
|
|
56
|
+
}
|
|
48
57
|
}
|
|
49
58
|
requestsAttributes.forEach((attr) => {
|
|
50
59
|
if (typeof arg[attr] != 'undefined') { response[attr] = arg[attr]; }
|
|
51
60
|
});
|
|
52
|
-
if (typeof response['creativeId'] == 'number') {
|
|
61
|
+
if (typeof response['creativeId'] == 'number') {
|
|
62
|
+
response['creativeId'] = response['creativeId'].toString();
|
|
63
|
+
}
|
|
53
64
|
}
|
|
65
|
+
response['oxxionMode'] = mode;
|
|
54
66
|
return response;
|
|
55
67
|
}
|
|
56
68
|
|
|
@@ -229,7 +241,12 @@ oxxionAnalytics.originEnableAnalytics = oxxionAnalytics.enableAnalytics;
|
|
|
229
241
|
oxxionAnalytics.enableAnalytics = function (config) {
|
|
230
242
|
oxxionAnalytics.originEnableAnalytics(config); // call the base class function
|
|
231
243
|
initOptions = config.options;
|
|
232
|
-
if (initOptions.domain) {
|
|
244
|
+
if (initOptions.domain) {
|
|
245
|
+
endpoint = 'https://' + initOptions.domain;
|
|
246
|
+
}
|
|
247
|
+
if (window.OXXION_MODE) {
|
|
248
|
+
mode = window.OXXION_MODE;
|
|
249
|
+
}
|
|
233
250
|
};
|
|
234
251
|
|
|
235
252
|
adapterManager.registerAnalyticsAdapter({
|
|
@@ -27,7 +27,7 @@ const DEFAULT_PBS_INTEGRATION = 'pbjs';
|
|
|
27
27
|
const DEFAULT_RENDERER_URL = 'https://video-outstream.rubiconproject.com/apex-2.2.1.js';
|
|
28
28
|
// renderer code at https://github.com/rubicon-project/apex2
|
|
29
29
|
|
|
30
|
-
let rubiConf = {};
|
|
30
|
+
let rubiConf = config.getConfig('rubicon') || {};
|
|
31
31
|
// we are saving these as global to this module so that if a pub accidentally overwrites the entire
|
|
32
32
|
// rubicon object, then we do not lose other data
|
|
33
33
|
config.getConfig('rubicon', config => {
|
|
@@ -322,7 +322,7 @@ export const spec = {
|
|
|
322
322
|
)
|
|
323
323
|
);
|
|
324
324
|
});
|
|
325
|
-
if (
|
|
325
|
+
if (rubiConf.singleRequest !== true) {
|
|
326
326
|
// bids are not grouped if single request mode is not enabled
|
|
327
327
|
requests = filteredHttpRequest.concat(bannerBidRequests.map(bidRequest => {
|
|
328
328
|
const bidParams = spec.createSlotParams(bidRequest, bidderRequest);
|
|
@@ -3,6 +3,7 @@ import {registerBidder} from '../src/adapters/bidderFactory.js';
|
|
|
3
3
|
import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js';
|
|
4
4
|
import { config } from '../src/config.js';
|
|
5
5
|
import { convertOrtbRequestToProprietaryNative } from '../src/native.js';
|
|
6
|
+
import { ajax } from '../src/ajax.js';
|
|
6
7
|
|
|
7
8
|
const BIDDER_CODE = 'smartyads';
|
|
8
9
|
const AD_URL = 'https://n1.smartyads.com/?c=o&m=prebid&secret_key=prebid_js';
|
|
@@ -122,7 +123,23 @@ export const spec = {
|
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
return syncs
|
|
125
|
-
}
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
onBidWon: function(bid) {
|
|
129
|
+
if (bid.winUrl) {
|
|
130
|
+
ajax(bid.winUrl, () => {}, JSON.stringify(bid));
|
|
131
|
+
} else {
|
|
132
|
+
ajax('https://et-nd43.itdsmr.com/?c=o&m=prebid&secret_key=prebid_js&winTest=1', () => {}, JSON.stringify(bid));
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
onTimeout: function(bid) {
|
|
137
|
+
ajax('https://et-nd43.itdsmr.com/?c=o&m=prebid&secret_key=prebid_js&bidTimeout=1', () => {}, JSON.stringify(bid));
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
onBidderError: function(bid) {
|
|
141
|
+
ajax('https://et-nd43.itdsmr.com/?c=o&m=prebid&secret_key=prebid_js&bidderError=1', () => {}, JSON.stringify(bid));
|
|
142
|
+
},
|
|
126
143
|
|
|
127
144
|
};
|
|
128
145
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {config} from '../src/config.js';
|
|
2
2
|
import {registerBidder} from '../src/adapters/bidderFactory.js';
|
|
3
3
|
import {BANNER} from '../src/mediaTypes.js';
|
|
4
|
-
import {deepAccess, isArray, isFn, isPlainObject} from '../src/utils.js';
|
|
4
|
+
import {deepAccess, isArray, isFn, isPlainObject, inIframe, getDNT} from '../src/utils.js';
|
|
5
5
|
import {hasPurpose1Consent} from '../src/utils/gpdr.js';
|
|
6
6
|
import {getGlobal} from '../src/prebidGlobal.js';
|
|
7
7
|
|
|
@@ -13,6 +13,7 @@ const DEFAULT_CURRENCIES = ['USD'];
|
|
|
13
13
|
const FLOOR_MATCH_ALL_SIZES = '*';
|
|
14
14
|
|
|
15
15
|
const getConfig = config.getConfig;
|
|
16
|
+
const refreshes = {};
|
|
16
17
|
|
|
17
18
|
export const spec = {
|
|
18
19
|
code: BIDDER_CODE,
|
|
@@ -29,12 +30,15 @@ export const spec = {
|
|
|
29
30
|
method: 'POST',
|
|
30
31
|
url: getEndpoint(),
|
|
31
32
|
data: JSON.stringify({
|
|
32
|
-
id: bidderRequest.
|
|
33
|
+
id: bidderRequest.auctionId,
|
|
34
|
+
accountId: deepAccess(bidRequests, '0.params.accountId'),
|
|
35
|
+
site: deepAccess(bidRequests, '0.params.site'),
|
|
33
36
|
cur: getCurrencies(),
|
|
34
37
|
test: getTestFlag(),
|
|
35
|
-
devw: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
|
|
36
|
-
devh: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight,
|
|
37
38
|
version: getGlobal().version,
|
|
39
|
+
gpp: deepAccess(bidderRequest, 'gppConsent.gppString') || deepAccess(bidderRequest, 'ortb2.regs.gpp'),
|
|
40
|
+
gpp_sid:
|
|
41
|
+
deepAccess(bidderRequest, 'gppConsent.applicableSections') || deepAccess(bidderRequest, 'ortb2.regs.gpp_sid'),
|
|
38
42
|
gdprApplies: gdprApplies,
|
|
39
43
|
gdprConsentString: gdprApplies === true ? deepAccess(bidderRequest, 'gdprConsent.consentString') : undefined,
|
|
40
44
|
gdprConsentProv: gdprApplies === true ? deepAccess(bidderRequest, 'gdprConsent.addtlConsent') : undefined,
|
|
@@ -43,12 +47,24 @@ export const spec = {
|
|
|
43
47
|
eids: deepAccess(bidRequests, '0.userIdAsEids'),
|
|
44
48
|
schain: deepAccess(bidRequests, '0.schain'),
|
|
45
49
|
page: getPage(bidderRequest),
|
|
50
|
+
topframe: inIframe() === true ? 0 : 1,
|
|
51
|
+
device: {
|
|
52
|
+
w: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
|
|
53
|
+
h: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight,
|
|
54
|
+
dnt: getDNT() ? 1 : 0,
|
|
55
|
+
language: getLanguage(),
|
|
56
|
+
},
|
|
46
57
|
placements: bidRequests.map((r) => {
|
|
47
58
|
return {
|
|
48
|
-
|
|
59
|
+
id: r.adUnitCode,
|
|
60
|
+
tid: r.transactionId,
|
|
61
|
+
gpid: deepAccess(r, 'ortb2Imp.ext.gpid'),
|
|
62
|
+
pbadslot: deepAccess(r, 'ortb2Imp.ext.data.pbadslot') || deepAccess(r, 'ortb2Imp.ext.gpid'),
|
|
49
63
|
name: r.params.placement,
|
|
50
64
|
sizes: r.sizes,
|
|
51
65
|
floor: getPriceFloor(r, BANNER, FLOOR_MATCH_ALL_SIZES),
|
|
66
|
+
refresh: getRefreshInformation(r.adUnitCode),
|
|
67
|
+
params: r.params.additionalParams,
|
|
52
68
|
};
|
|
53
69
|
}),
|
|
54
70
|
}),
|
|
@@ -56,14 +72,14 @@ export const spec = {
|
|
|
56
72
|
};
|
|
57
73
|
},
|
|
58
74
|
|
|
59
|
-
interpretResponse: function (serverResponse) {
|
|
75
|
+
interpretResponse: function (serverResponse, bidRequest) {
|
|
60
76
|
if (!serverResponse.body || !serverResponse.body.bids) {
|
|
61
77
|
return [];
|
|
62
78
|
}
|
|
63
79
|
|
|
64
80
|
return serverResponse.body.bids.map((bid) => {
|
|
65
81
|
return {
|
|
66
|
-
requestId: bid.
|
|
82
|
+
requestId: mapIdToRequestId(bid.id, bidRequest),
|
|
67
83
|
cpm: bid.price,
|
|
68
84
|
creativeId: bid.crid,
|
|
69
85
|
currency: serverResponse.body.cur,
|
|
@@ -77,9 +93,9 @@ export const spec = {
|
|
|
77
93
|
});
|
|
78
94
|
},
|
|
79
95
|
|
|
80
|
-
getUserSyncs: function (syncOptions, responses, gdprConsent, uspConsent) {
|
|
96
|
+
getUserSyncs: function (syncOptions, responses, gdprConsent, uspConsent, gppConsent) {
|
|
81
97
|
const syncUrl = getSyncUrl(responses || []);
|
|
82
|
-
if (syncUrl && syncOptions.iframeEnabled && hasSyncConsent(gdprConsent, uspConsent)) {
|
|
98
|
+
if (syncUrl && syncOptions.iframeEnabled && hasSyncConsent(gdprConsent, uspConsent, gppConsent)) {
|
|
83
99
|
return [{type: 'iframe', url: getSyncEndpoint(syncUrl, gdprConsent)}];
|
|
84
100
|
}
|
|
85
101
|
},
|
|
@@ -101,6 +117,14 @@ function getTestFlag() {
|
|
|
101
117
|
return getConfig(`${BIDDER_CODE}.test`) === true;
|
|
102
118
|
}
|
|
103
119
|
|
|
120
|
+
function getLanguage() {
|
|
121
|
+
return navigator && navigator.language
|
|
122
|
+
? navigator.language.indexOf('-') != -1
|
|
123
|
+
? navigator.language.split('-')[0]
|
|
124
|
+
: navigator.language
|
|
125
|
+
: undefined;
|
|
126
|
+
}
|
|
127
|
+
|
|
104
128
|
function getCurrencies() {
|
|
105
129
|
const currencyOverrides = getConfig(`${BIDDER_CODE}.cur`);
|
|
106
130
|
if (currencyOverrides !== undefined && (!isArray(currencyOverrides) || currencyOverrides.length === 0)) {
|
|
@@ -130,14 +154,43 @@ function getPriceFloor(bidRequest, mediaType, size) {
|
|
|
130
154
|
}
|
|
131
155
|
}
|
|
132
156
|
|
|
133
|
-
function
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
157
|
+
function getRefreshInformation(adUnitCode) {
|
|
158
|
+
const refresh = refreshes[adUnitCode];
|
|
159
|
+
if (!refresh) {
|
|
160
|
+
refreshes[adUnitCode] = {
|
|
161
|
+
count: 0,
|
|
162
|
+
previousTime: new Date(),
|
|
163
|
+
};
|
|
164
|
+
return undefined;
|
|
140
165
|
}
|
|
166
|
+
|
|
167
|
+
const currentTime = new Date();
|
|
168
|
+
const timeDifferenceSeconds = Math.floor((currentTime - refresh.previousTime) / 1000);
|
|
169
|
+
refresh.count += 1;
|
|
170
|
+
refresh.previousTime = currentTime;
|
|
171
|
+
return {
|
|
172
|
+
count: refresh.count,
|
|
173
|
+
time: timeDifferenceSeconds,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function mapIdToRequestId(id, bidRequest) {
|
|
178
|
+
return bidRequest.bidderRequest.bids.filter((bid) => bid.adUnitCode === id)[0].bidId;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function hasUspConsent(uspConsent) {
|
|
182
|
+
return typeof uspConsent !== 'string' || !(uspConsent[0] === '1' && uspConsent[2] === 'Y');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function hasGppConsent(gppConsent) {
|
|
186
|
+
return (
|
|
187
|
+
!(gppConsent && Array.isArray(gppConsent.applicableSections)) ||
|
|
188
|
+
gppConsent.applicableSections.every((section) => typeof section === 'number' && section <= 5)
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function hasSyncConsent(gdprConsent, uspConsent, gppConsent) {
|
|
193
|
+
return hasPurpose1Consent(gdprConsent) && hasUspConsent(uspConsent) && hasGppConsent(gppConsent);
|
|
141
194
|
}
|
|
142
195
|
|
|
143
196
|
function getSyncUrl(responses) {
|