prebid.js 6.5.0 → 6.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/modules/.submodules.json +2 -1
- package/modules/adkernelBidAdapter.js +2 -1
- package/modules/admanBidAdapter.js +10 -4
- package/modules/adomikAnalyticsAdapter.js +23 -11
- package/modules/adqueryIdSystem.js +103 -0
- package/modules/adqueryIdSystem.md +35 -0
- package/modules/bliinkBidAdapter.js +2 -1
- package/modules/compassBidAdapter.js +9 -2
- package/modules/criteoBidAdapter.js +1 -1
- package/modules/criteoIdSystem.js +29 -7
- package/modules/glimpseBidAdapter.js +66 -44
- package/modules/idImportLibrary.js +45 -8
- package/modules/idImportLibrary.md +4 -0
- package/modules/improvedigitalBidAdapter.js +24 -2
- package/modules/nextMillenniumBidAdapter.js +3 -1
- package/modules/oguryBidAdapter.js +9 -2
- package/modules/onetagBidAdapter.js +4 -2
- package/modules/proxistoreBidAdapter.js +0 -2
- package/modules/pubmaticAnalyticsAdapter.js +16 -0
- package/modules/richaudienceBidAdapter.js +3 -2
- package/modules/riseBidAdapter.js +1 -1
- package/modules/rtbhouseBidAdapter.js +14 -4
- package/modules/rtdModule/index.js +6 -5
- package/modules/showheroes-bsBidAdapter.js +13 -2
- package/modules/tappxBidAdapter.js +8 -5
- package/modules/teadsBidAdapter.js +1 -2
- package/modules/userId/eids.js +7 -1
- package/modules/userId/userId.md +8 -0
- package/modules/welectBidAdapter.js +106 -0
- package/package.json +1 -1
- package/src/hook.js +5 -1
- package/src/prebid.js +18 -4
- package/test/spec/modules/admanBidAdapter_spec.js +2 -2
- package/test/spec/modules/adomikAnalyticsAdapter_spec.js +3 -1
- package/test/spec/modules/adqueryIdSystem_spec.js +74 -0
- package/test/spec/modules/bliinkBidAdapter_spec.js +2 -0
- package/test/spec/modules/compassBidAdapter_spec.js +1 -0
- package/test/spec/modules/criteoIdSystem_spec.js +6 -3
- package/test/spec/modules/eids_spec.js +15 -0
- package/test/spec/modules/glimpseBidAdapter_spec.js +0 -18
- package/test/spec/modules/idImportLibrary_spec.js +197 -10
- package/test/spec/modules/improvedigitalBidAdapter_spec.js +42 -0
- package/test/spec/modules/loglyliftBidAdapter_spec.js +1 -1
- package/test/spec/modules/nextMillenniumBidAdapter_spec.js +1 -1
- package/test/spec/modules/oguryBidAdapter_spec.js +10 -2
- package/test/spec/modules/pubmaticAnalyticsAdapter_spec.js +13 -1
- package/test/spec/modules/realTimeDataModule_spec.js +16 -3
- package/test/spec/modules/richaudienceBidAdapter_spec.js +40 -0
- package/test/spec/modules/riseBidAdapter_spec.js +1 -1
- package/test/spec/modules/rtbhouseBidAdapter_spec.js +20 -0
- package/test/spec/modules/showheroes-bsBidAdapter_spec.js +2 -0
- package/test/spec/modules/tappxBidAdapter_spec.js +0 -19
- package/test/spec/modules/teadsBidAdapter_spec.js +14 -59
- package/test/spec/modules/userId_spec.js +68 -19
- package/test/spec/modules/welectBidAdapter_spec.js +211 -0
- package/test/spec/unit/pbjs_api_spec.js +3 -1
package/modules/.submodules.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {registerBidder} from '../src/adapters/bidderFactory.js';
|
|
2
2
|
import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js';
|
|
3
3
|
import { isFn, deepAccess, logMessage } from '../src/utils.js';
|
|
4
|
+
import {config} from '../src/config.js';
|
|
4
5
|
|
|
5
6
|
const BIDDER_CODE = 'adman';
|
|
6
7
|
const AD_URL = 'https://pub.admanmedia.com/?c=o&m=multi';
|
|
7
|
-
const URL_SYNC = 'https://pub.admanmedia.com
|
|
8
|
+
const URL_SYNC = 'https://pub.admanmedia.com';
|
|
8
9
|
|
|
9
10
|
function isBidResponseValid(bid) {
|
|
10
11
|
if (!bid.requestId || !bid.cpm || !bid.creativeId ||
|
|
@@ -152,19 +153,24 @@ export const spec = {
|
|
|
152
153
|
},
|
|
153
154
|
|
|
154
155
|
getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => {
|
|
155
|
-
let
|
|
156
|
+
let syncType = syncOptions.iframeEnabled ? 'iframe' : 'image';
|
|
157
|
+
let syncUrl = URL_SYNC + `/${syncType}?pbjs=1`;
|
|
156
158
|
if (gdprConsent && gdprConsent.consentString) {
|
|
157
159
|
if (typeof gdprConsent.gdprApplies === 'boolean') {
|
|
158
160
|
syncUrl += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`;
|
|
159
161
|
} else {
|
|
160
|
-
syncUrl += `&gdpr
|
|
162
|
+
syncUrl += `&gdpr=0&gdpr_consent=${gdprConsent.consentString}`;
|
|
161
163
|
}
|
|
162
164
|
}
|
|
163
165
|
if (uspConsent && uspConsent.consentString) {
|
|
164
166
|
syncUrl += `&ccpa_consent=${uspConsent.consentString}`;
|
|
165
167
|
}
|
|
168
|
+
|
|
169
|
+
const coppa = config.getConfig('coppa') ? 1 : 0;
|
|
170
|
+
syncUrl += `&coppa=${coppa}`;
|
|
171
|
+
|
|
166
172
|
return [{
|
|
167
|
-
type:
|
|
173
|
+
type: syncType,
|
|
168
174
|
url: syncUrl
|
|
169
175
|
}];
|
|
170
176
|
}
|
|
@@ -14,6 +14,8 @@ const bidWon = CONSTANTS.EVENTS.BID_WON;
|
|
|
14
14
|
const bidTimeout = CONSTANTS.EVENTS.BID_TIMEOUT;
|
|
15
15
|
const ua = navigator.userAgent;
|
|
16
16
|
|
|
17
|
+
var _sampled = true;
|
|
18
|
+
|
|
17
19
|
let adomikAdapter = Object.assign(adapter({}),
|
|
18
20
|
{
|
|
19
21
|
// Track every event needed
|
|
@@ -81,6 +83,7 @@ adomikAdapter.sendTypedEvent = function() {
|
|
|
81
83
|
uid: adomikAdapter.currentContext.uid,
|
|
82
84
|
ahbaid: adomikAdapter.currentContext.id,
|
|
83
85
|
hostname: window.location.hostname,
|
|
86
|
+
sampling: adomikAdapter.currentContext.sampling,
|
|
84
87
|
eventsByPlacementCode: groupedTypedEvents.map(function(typedEventsByType) {
|
|
85
88
|
let sizes = [];
|
|
86
89
|
const eventKeys = ['request', 'response', 'winner'];
|
|
@@ -203,19 +206,28 @@ adomikAdapter.adapterEnableAnalytics = adomikAdapter.enableAnalytics;
|
|
|
203
206
|
|
|
204
207
|
adomikAdapter.enableAnalytics = function (config) {
|
|
205
208
|
adomikAdapter.currentContext = {};
|
|
206
|
-
|
|
207
209
|
const initOptions = config.options;
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
210
|
+
|
|
211
|
+
_sampled = typeof config === 'undefined' ||
|
|
212
|
+
typeof config.sampling === 'undefined' ||
|
|
213
|
+
Math.random() < parseFloat(config.sampling);
|
|
214
|
+
|
|
215
|
+
if (_sampled) {
|
|
216
|
+
if (initOptions) {
|
|
217
|
+
adomikAdapter.currentContext = {
|
|
218
|
+
uid: initOptions.id,
|
|
219
|
+
url: initOptions.url,
|
|
220
|
+
testId: initOptions.testId,
|
|
221
|
+
testValue: initOptions.testValue,
|
|
222
|
+
id: '',
|
|
223
|
+
timeouted: false,
|
|
224
|
+
sampling: config.sampling
|
|
225
|
+
}
|
|
226
|
+
logInfo('Adomik Analytics enabled with config', initOptions);
|
|
227
|
+
adomikAdapter.adapterEnableAnalytics(config);
|
|
216
228
|
}
|
|
217
|
-
|
|
218
|
-
|
|
229
|
+
} else {
|
|
230
|
+
logInfo('Adomik Analytics ignored for sampling', config.sampling);
|
|
219
231
|
}
|
|
220
232
|
};
|
|
221
233
|
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This module adds Adquery QID to the User ID module
|
|
3
|
+
* The {@link module:modules/userId} module is required
|
|
4
|
+
* @module modules/adqueryIdSystem
|
|
5
|
+
* @requires module:modules/userId
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {ajax} from '../src/ajax.js';
|
|
9
|
+
import {getStorageManager} from '../src/storageManager.js';
|
|
10
|
+
import {submodule} from '../src/hook.js';
|
|
11
|
+
import * as utils from '../src/utils.js';
|
|
12
|
+
|
|
13
|
+
const MODULE_NAME = 'qid';
|
|
14
|
+
const AU_GVLID = 902;
|
|
15
|
+
|
|
16
|
+
export const storage = getStorageManager(AU_GVLID, 'qid');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Param or default.
|
|
20
|
+
* @param {String} param
|
|
21
|
+
* @param {String} defaultVal
|
|
22
|
+
*/
|
|
23
|
+
function paramOrDefault(param, defaultVal, arg) {
|
|
24
|
+
if (utils.isFn(param)) {
|
|
25
|
+
return param(arg);
|
|
26
|
+
} else if (utils.isStr(param)) {
|
|
27
|
+
return param;
|
|
28
|
+
}
|
|
29
|
+
return defaultVal;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** @type {Submodule} */
|
|
33
|
+
export const adqueryIdSubmodule = {
|
|
34
|
+
/**
|
|
35
|
+
* used to link submodule with config
|
|
36
|
+
* @type {string}
|
|
37
|
+
*/
|
|
38
|
+
name: MODULE_NAME,
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* IAB TCF Vendor ID
|
|
42
|
+
* @type {string}
|
|
43
|
+
*/
|
|
44
|
+
gvlid: AU_GVLID,
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* decode the stored id value for passing to bid requests
|
|
48
|
+
* @function
|
|
49
|
+
* @param {{value:string}} value
|
|
50
|
+
* @returns {{qid:Object}}
|
|
51
|
+
*/
|
|
52
|
+
decode(value) {
|
|
53
|
+
let qid = storage.getDataFromLocalStorage('qid');
|
|
54
|
+
if (utils.isStr(qid)) {
|
|
55
|
+
return {qid: qid};
|
|
56
|
+
}
|
|
57
|
+
return (value && typeof value['qid'] === 'string') ? { 'qid': value['qid'] } : undefined;
|
|
58
|
+
},
|
|
59
|
+
/**
|
|
60
|
+
* performs action to obtain id and return a value in the callback's response argument
|
|
61
|
+
* @function
|
|
62
|
+
* @param {SubmoduleConfig} [config]
|
|
63
|
+
* @returns {IdResponse|undefined}
|
|
64
|
+
*/
|
|
65
|
+
getId(config) {
|
|
66
|
+
if (!utils.isPlainObject(config.params)) {
|
|
67
|
+
config.params = {};
|
|
68
|
+
}
|
|
69
|
+
const url = paramOrDefault(config.params.url,
|
|
70
|
+
`https://bidder.adquery.io/prebid/qid`,
|
|
71
|
+
config.params.urlArg);
|
|
72
|
+
|
|
73
|
+
const resp = function (callback) {
|
|
74
|
+
let qid = storage.getDataFromLocalStorage('qid');
|
|
75
|
+
if (utils.isStr(qid)) {
|
|
76
|
+
const responseObj = {qid: qid};
|
|
77
|
+
callback(responseObj);
|
|
78
|
+
} else {
|
|
79
|
+
const callbacks = {
|
|
80
|
+
success: response => {
|
|
81
|
+
let responseObj;
|
|
82
|
+
if (response) {
|
|
83
|
+
try {
|
|
84
|
+
responseObj = JSON.parse(response);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
utils.logError(error);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
callback(responseObj);
|
|
90
|
+
},
|
|
91
|
+
error: error => {
|
|
92
|
+
utils.logError(`${MODULE_NAME}: ID fetch encountered an error`, error);
|
|
93
|
+
callback();
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
ajax(url, callbacks, undefined, {method: 'GET'});
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
return {callback: resp};
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
submodule('userId', adqueryIdSubmodule);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Adquery QID
|
|
2
|
+
|
|
3
|
+
Adquery QID Module. For assistance setting up your module please contact us at [prebid@adquery.io](prebid@adquery.io).
|
|
4
|
+
|
|
5
|
+
### Prebid Params
|
|
6
|
+
|
|
7
|
+
Individual params may be set for the Adquery ID Submodule. At least one identifier must be set in the params.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
pbjs.setConfig({
|
|
11
|
+
usersync: {
|
|
12
|
+
userIds: [{
|
|
13
|
+
name: 'qid',
|
|
14
|
+
storage: {
|
|
15
|
+
name: 'qid',
|
|
16
|
+
type: 'html5'
|
|
17
|
+
}
|
|
18
|
+
}]
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
```
|
|
22
|
+
## Parameter Descriptions for the `usersync` Configuration Section
|
|
23
|
+
The below parameters apply only to the Adquery User ID Module integration.
|
|
24
|
+
|
|
25
|
+
| Param under usersync.userIds[] | Scope | Type | Description | Example |
|
|
26
|
+
| --- | --- | --- | --- | --- |
|
|
27
|
+
| name | Required | String | ID value for the Adquery ID module - `"qid"` | `"qid"` |
|
|
28
|
+
| storage | Required | Object | The publisher must specify the local storage in which to store the results of the call to get the user ID. | |
|
|
29
|
+
| storage.type | Required | String | This is where the results of the user ID will be stored. The recommended method is `localStorage` by specifying `html5`. | `"html5"` |
|
|
30
|
+
| storage.name | Required | String | The name of the html5 local storage where the user ID will be stored. | `"qid"` |
|
|
31
|
+
| storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. | `365` |
|
|
32
|
+
| value | Optional | Object | Used only if the page has a separate mechanism for storing the Adquery ID. The value is an object containing the values to be sent to the adapters. In this scenario, no URL is called and nothing is added to local storage | `{"qid": "2abf9f001fcd81241b67"}` |
|
|
33
|
+
| params | Optional | Object | Used to store params for the id system |
|
|
34
|
+
| params.url | Optional | String | Set an alternate GET url for qid with this parameter |
|
|
35
|
+
| params.urlArg | Optional | Object | Optional url parameter for params.url |
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// eslint-disable-next-line prebid/validate-imports
|
|
2
2
|
// eslint-disable-next-line prebid/validate-imports
|
|
3
3
|
import {registerBidder} from '../src/adapters/bidderFactory.js'
|
|
4
|
-
|
|
5
4
|
export const BIDDER_CODE = 'bliink'
|
|
6
5
|
export const BLIINK_ENDPOINT_ENGINE = 'https://engine.bliink.io/delivery'
|
|
7
6
|
export const BLIINK_ENDPOINT_ENGINE_VAST = 'https://engine.bliink.io/vast'
|
|
@@ -174,6 +173,8 @@ export const buildRequests = (_, bidderRequest) => {
|
|
|
174
173
|
pageUrl: bidderRequest.refererInfo.referer,
|
|
175
174
|
pageDescription: getMetaValue(META_DESCRIPTION),
|
|
176
175
|
keywords: getKeywords().join(','),
|
|
176
|
+
gdpr: false,
|
|
177
|
+
gdpr_consent: '',
|
|
177
178
|
pageTitle: document.title,
|
|
178
179
|
}
|
|
179
180
|
|
|
@@ -28,16 +28,23 @@ function isBidResponseValid(bid) {
|
|
|
28
28
|
function getPlacementReqData(bid) {
|
|
29
29
|
const { params, bidId, mediaTypes } = bid;
|
|
30
30
|
const schain = bid.schain || {};
|
|
31
|
-
const { placementId } = params;
|
|
31
|
+
const { placementId, endpointId } = params;
|
|
32
32
|
const bidfloor = getBidFloor(bid);
|
|
33
33
|
|
|
34
34
|
const placement = {
|
|
35
|
-
placementId,
|
|
36
35
|
bidId,
|
|
37
36
|
schain,
|
|
38
37
|
bidfloor
|
|
39
38
|
};
|
|
40
39
|
|
|
40
|
+
if (placementId) {
|
|
41
|
+
placement.placementId = placementId;
|
|
42
|
+
placement.type = 'publisher';
|
|
43
|
+
} else if (endpointId) {
|
|
44
|
+
placement.endpointId = endpointId;
|
|
45
|
+
placement.type = 'network';
|
|
46
|
+
}
|
|
47
|
+
|
|
41
48
|
if (mediaTypes && mediaTypes[BANNER]) {
|
|
42
49
|
placement.adFormat = BANNER;
|
|
43
50
|
placement.sizes = mediaTypes[BANNER].sizes;
|
|
@@ -24,7 +24,7 @@ const LOG_PREFIX = 'Criteo: ';
|
|
|
24
24
|
Unminified source code can be found in the privately shared repo: https://github.com/Prebid-org/prebid-js-external-js-criteo/blob/master/dist/prod.js
|
|
25
25
|
*/
|
|
26
26
|
const FAST_BID_VERSION_PLACEHOLDER = '%FAST_BID_VERSION%';
|
|
27
|
-
export const FAST_BID_VERSION_CURRENT =
|
|
27
|
+
export const FAST_BID_VERSION_CURRENT = 117;
|
|
28
28
|
const FAST_BID_VERSION_LATEST = 'latest';
|
|
29
29
|
const FAST_BID_VERSION_NONE = 'none';
|
|
30
30
|
const PUBLISHER_TAG_URL_TEMPLATE = 'https://static.criteo.net/js/ld/publishertag.prebid' + FAST_BID_VERSION_PLACEHOLDER + '.js';
|
|
@@ -33,15 +33,37 @@ function getFromAllStorages(key) {
|
|
|
33
33
|
return storage.getCookie(key) || storage.getDataFromLocalStorage(key);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
function saveOnAllStorages(key, value) {
|
|
36
|
+
function saveOnAllStorages(key, value, hostname) {
|
|
37
37
|
if (key && value) {
|
|
38
|
-
storage.setCookie(key, value, expirationString);
|
|
39
38
|
storage.setDataInLocalStorage(key, value);
|
|
39
|
+
setCookieOnAllDomains(key, value, expirationString, hostname, true);
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
function
|
|
44
|
-
|
|
43
|
+
function setCookieOnAllDomains(key, value, expiration, hostname, stopOnSuccess) {
|
|
44
|
+
const subDomains = hostname.split('.');
|
|
45
|
+
for (let i = 0; i < subDomains.length; ++i) {
|
|
46
|
+
// Try to write the cookie on this subdomain (we want it to be stored only on the TLD+1)
|
|
47
|
+
const domain = subDomains.slice(subDomains.length - i - 1, subDomains.length).join('.');
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
storage.setCookie(key, value, expiration, null, '.' + domain);
|
|
51
|
+
|
|
52
|
+
if (stopOnSuccess) {
|
|
53
|
+
// Try to read the cookie to check if we wrote it
|
|
54
|
+
const ck = storage.getCookie(key);
|
|
55
|
+
if (ck && ck === value) {
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
} catch (error) {
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function deleteFromAllStorages(key, hostname) {
|
|
66
|
+
setCookieOnAllDomains(key, '', pastDateString, hostname, true);
|
|
45
67
|
storage.removeDataFromLocalStorage(key);
|
|
46
68
|
}
|
|
47
69
|
|
|
@@ -89,15 +111,15 @@ function callCriteoUserSync(parsedCriteoData, gdprString, callback) {
|
|
|
89
111
|
const urlsToCall = typeof jsonResponse.acwsUrl === 'string' ? [jsonResponse.acwsUrl] : jsonResponse.acwsUrl;
|
|
90
112
|
urlsToCall.forEach(url => triggerPixel(url));
|
|
91
113
|
} else if (jsonResponse.bundle) {
|
|
92
|
-
saveOnAllStorages(bundleStorageKey, jsonResponse.bundle);
|
|
114
|
+
saveOnAllStorages(bundleStorageKey, jsonResponse.bundle, domain);
|
|
93
115
|
}
|
|
94
116
|
|
|
95
117
|
if (jsonResponse.bidId) {
|
|
96
|
-
saveOnAllStorages(bididStorageKey, jsonResponse.bidId);
|
|
118
|
+
saveOnAllStorages(bididStorageKey, jsonResponse.bidId, domain);
|
|
97
119
|
const criteoId = { criteoId: jsonResponse.bidId };
|
|
98
120
|
callback(criteoId);
|
|
99
121
|
} else {
|
|
100
|
-
deleteFromAllStorages(bididStorageKey);
|
|
122
|
+
deleteFromAllStorages(bididStorageKey, domain);
|
|
101
123
|
callback();
|
|
102
124
|
}
|
|
103
125
|
},
|
|
@@ -40,28 +40,21 @@ export const spec = {
|
|
|
40
40
|
* @returns {ServerRequest}
|
|
41
41
|
*/
|
|
42
42
|
buildRequests: (validBidRequests, bidderRequest) => {
|
|
43
|
-
const demo = config.getConfig('glimpse.demo') || false
|
|
44
|
-
const account = config.getConfig('glimpse.account') || -1
|
|
45
|
-
const demand = config.getConfig('glimpse.demand') || 'glimpse'
|
|
46
|
-
const keywords = config.getConfig('glimpse.keywords') || {}
|
|
47
|
-
|
|
48
43
|
const auth = getVaultJwt()
|
|
49
44
|
const referer = getReferer(bidderRequest)
|
|
50
45
|
const gdprConsent = getGdprConsentChoice(bidderRequest)
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
})
|
|
46
|
+
const bidRequests = validBidRequests.map(processBidRequest)
|
|
47
|
+
const firstPartyData = getFirstPartyData()
|
|
54
48
|
|
|
55
49
|
const data = {
|
|
56
50
|
auth,
|
|
57
51
|
data: {
|
|
58
|
-
bidderCode: spec.code,
|
|
59
|
-
demo,
|
|
60
|
-
account,
|
|
61
|
-
demand,
|
|
62
52
|
referer,
|
|
63
53
|
gdprConsent,
|
|
64
|
-
|
|
54
|
+
bidRequests,
|
|
55
|
+
site: firstPartyData.site,
|
|
56
|
+
user: firstPartyData.user,
|
|
57
|
+
bidderCode: spec.code,
|
|
65
58
|
}
|
|
66
59
|
}
|
|
67
60
|
|
|
@@ -91,35 +84,12 @@ export const spec = {
|
|
|
91
84
|
},
|
|
92
85
|
}
|
|
93
86
|
|
|
94
|
-
function
|
|
95
|
-
|
|
96
|
-
const bidKeywords = bidRequest.params.keywords || {}
|
|
97
|
-
const keywords = {
|
|
98
|
-
...globalKeywords,
|
|
99
|
-
...bidKeywords,
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return {
|
|
103
|
-
unitCode: bidRequest.adUnitCode,
|
|
104
|
-
bidId: bidRequest.bidId,
|
|
105
|
-
placementId: bidRequest.params.placementId,
|
|
106
|
-
keywords,
|
|
107
|
-
sizes,
|
|
108
|
-
}
|
|
87
|
+
function setVaultJwt(auth) {
|
|
88
|
+
storageManager.setDataInLocalStorage(LOCAL_STORAGE_KEY.vault.jwt, auth)
|
|
109
89
|
}
|
|
110
90
|
|
|
111
|
-
function
|
|
112
|
-
|
|
113
|
-
isArray(sizes) &&
|
|
114
|
-
sizes.length === 2 &&
|
|
115
|
-
!isArray(sizes[0]) &&
|
|
116
|
-
!isArray(sizes[1])
|
|
117
|
-
|
|
118
|
-
if (isSingleSize) {
|
|
119
|
-
return [sizes]
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
return sizes
|
|
91
|
+
function getVaultJwt() {
|
|
92
|
+
return storageManager.getDataFromLocalStorage(LOCAL_STORAGE_KEY.vault.jwt) || ''
|
|
123
93
|
}
|
|
124
94
|
|
|
125
95
|
function getReferer(bidderRequest) {
|
|
@@ -158,12 +128,64 @@ function getGdprConsentChoice(bidderRequest) {
|
|
|
158
128
|
}
|
|
159
129
|
}
|
|
160
130
|
|
|
161
|
-
function
|
|
162
|
-
|
|
131
|
+
function processBidRequest(bidRequest) {
|
|
132
|
+
const demand = bidRequest.params.demand || 'glimpse'
|
|
133
|
+
const sizes = normalizeSizes(bidRequest.sizes)
|
|
134
|
+
const keywords = bidRequest.params.keywords || {}
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
demand,
|
|
138
|
+
sizes,
|
|
139
|
+
keywords,
|
|
140
|
+
bidId: bidRequest.bidId,
|
|
141
|
+
placementId: bidRequest.params.placementId,
|
|
142
|
+
unitCode: bidRequest.adUnitCode,
|
|
143
|
+
}
|
|
163
144
|
}
|
|
164
145
|
|
|
165
|
-
function
|
|
166
|
-
|
|
146
|
+
function normalizeSizes(sizes) {
|
|
147
|
+
const isSingleSize =
|
|
148
|
+
isArray(sizes) &&
|
|
149
|
+
sizes.length === 2 &&
|
|
150
|
+
!isArray(sizes[0]) &&
|
|
151
|
+
!isArray(sizes[1])
|
|
152
|
+
|
|
153
|
+
if (isSingleSize) {
|
|
154
|
+
return [sizes]
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return sizes
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function getFirstPartyData() {
|
|
161
|
+
const siteKeywords = parseGlobalKeywords('site')
|
|
162
|
+
const userKeywords = parseGlobalKeywords('user')
|
|
163
|
+
|
|
164
|
+
const siteAttributes = getConfig('ortb2.site.ext.data', {})
|
|
165
|
+
const userAttributes = getConfig('ortb2.user.ext.data', {})
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
site: {
|
|
169
|
+
keywords: siteKeywords,
|
|
170
|
+
attributes: siteAttributes,
|
|
171
|
+
},
|
|
172
|
+
user: {
|
|
173
|
+
keywords: userKeywords,
|
|
174
|
+
attributes: userAttributes,
|
|
175
|
+
},
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function parseGlobalKeywords(scope) {
|
|
180
|
+
const keywords = getConfig(`ortb2.${scope}.keywords`, '')
|
|
181
|
+
|
|
182
|
+
return keywords
|
|
183
|
+
.split(', ')
|
|
184
|
+
.filter((keyword) => keyword !== '')
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function getConfig(path, defaultValue) {
|
|
188
|
+
return config.getConfig(path) || defaultValue
|
|
167
189
|
}
|
|
168
190
|
|
|
169
191
|
function isValidBidResponse(bidResponse) {
|
|
@@ -9,6 +9,7 @@ let conf;
|
|
|
9
9
|
const LOG_PRE_FIX = 'ID-Library: ';
|
|
10
10
|
const CONF_DEFAULT_OBSERVER_DEBOUNCE_MS = 250;
|
|
11
11
|
const CONF_DEFAULT_FULL_BODY_SCAN = false;
|
|
12
|
+
const CONF_DEFAULT_INPUT_SCAN = false;
|
|
12
13
|
const OBSERVER_CONFIG = {
|
|
13
14
|
subtree: true,
|
|
14
15
|
attributes: true,
|
|
@@ -78,7 +79,13 @@ function targetAction(mutations, observer) {
|
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
function addInputElementsElementListner(
|
|
82
|
+
function addInputElementsElementListner() {
|
|
83
|
+
if (doesInputElementsHaveEmail()) {
|
|
84
|
+
_logInfo('Email found in input elements ' + email);
|
|
85
|
+
_logInfo('Post data on email found in target without');
|
|
86
|
+
postData();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
82
89
|
_logInfo('Adding input element listeners');
|
|
83
90
|
const inputs = document.querySelectorAll('input[type=text], input[type=email]');
|
|
84
91
|
|
|
@@ -89,6 +96,19 @@ function addInputElementsElementListner(conf) {
|
|
|
89
96
|
}
|
|
90
97
|
}
|
|
91
98
|
|
|
99
|
+
function addFormInputElementsElementListner(id) {
|
|
100
|
+
_logInfo('Adding input element listeners');
|
|
101
|
+
if (doesFormInputElementsHaveEmail(id)) {
|
|
102
|
+
_logInfo('Email found in input elements ' + email);
|
|
103
|
+
postData();
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
_logInfo('Adding input element listeners');
|
|
107
|
+
const input = document.getElementById(id);
|
|
108
|
+
input.addEventListener('change', event => processInputChange(event));
|
|
109
|
+
input.addEventListener('blur', event => processInputChange(event));
|
|
110
|
+
}
|
|
111
|
+
|
|
92
112
|
function removeInputElementsElementListner() {
|
|
93
113
|
_logInfo('Removing input element listeners');
|
|
94
114
|
const inputs = document.querySelectorAll('input[type=text], input[type=email]');
|
|
@@ -149,12 +169,6 @@ function handleTargetElement() {
|
|
|
149
169
|
}
|
|
150
170
|
|
|
151
171
|
function handleBodyElements() {
|
|
152
|
-
if (doesInputElementsHaveEmail()) {
|
|
153
|
-
_logInfo('Email found in input elements ' + email);
|
|
154
|
-
_logInfo('Post data on email found in target without');
|
|
155
|
-
postData();
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
172
|
email = getEmail(document.body.innerHTML);
|
|
159
173
|
if (email !== null) {
|
|
160
174
|
_logInfo('Email found in body ' + email);
|
|
@@ -162,7 +176,7 @@ function handleBodyElements() {
|
|
|
162
176
|
postData();
|
|
163
177
|
return;
|
|
164
178
|
}
|
|
165
|
-
|
|
179
|
+
|
|
166
180
|
if (conf.fullscan === true) {
|
|
167
181
|
const bodyObserver = new MutationObserver(debounce(bodyAction, conf.debounce, false));
|
|
168
182
|
bodyObserver.observe(document.body, OBSERVER_CONFIG);
|
|
@@ -182,6 +196,17 @@ function doesInputElementsHaveEmail() {
|
|
|
182
196
|
return false;
|
|
183
197
|
}
|
|
184
198
|
|
|
199
|
+
function doesFormInputElementsHaveEmail(formElementId) {
|
|
200
|
+
const input = document.getElementById(formElementId);
|
|
201
|
+
if (input) {
|
|
202
|
+
email = getEmail(input.value);
|
|
203
|
+
if (email !== null) {
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
|
|
185
210
|
function syncCallback() {
|
|
186
211
|
return {
|
|
187
212
|
success: function () {
|
|
@@ -213,6 +238,10 @@ function associateIds() {
|
|
|
213
238
|
if (window.MutationObserver || window.WebKitMutationObserver) {
|
|
214
239
|
if (conf.target) {
|
|
215
240
|
handleTargetElement();
|
|
241
|
+
} else if (conf.formElementId) {
|
|
242
|
+
addFormInputElementsElementListner(conf.formElementId);
|
|
243
|
+
} else if (conf.inputscan) {
|
|
244
|
+
addInputElementsElementListner();
|
|
216
245
|
} else {
|
|
217
246
|
handleBodyElements();
|
|
218
247
|
}
|
|
@@ -236,6 +265,14 @@ export function setConfig(config) {
|
|
|
236
265
|
config.fullscan = CONF_DEFAULT_FULL_BODY_SCAN;
|
|
237
266
|
_logInfo('Set default fullscan ' + CONF_DEFAULT_FULL_BODY_SCAN);
|
|
238
267
|
}
|
|
268
|
+
if (typeof config.inputscan !== 'boolean') {
|
|
269
|
+
config.inputscan = CONF_DEFAULT_INPUT_SCAN;
|
|
270
|
+
_logInfo('Set default input scan ' + CONF_DEFAULT_INPUT_SCAN);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (typeof config.formElementId == 'string') {
|
|
274
|
+
_logInfo('Looking for formElementId ' + config.formElementId);
|
|
275
|
+
}
|
|
239
276
|
conf = config;
|
|
240
277
|
associateIds();
|
|
241
278
|
}
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
| `url` | Yes | String | N/A | URL endpoint used to post the hashed email and user IDs. |
|
|
9
9
|
| `debounce` | No | Number | 250 | Time in milliseconds before the email and IDs are fetched. |
|
|
10
10
|
| `fullscan` | No | Boolean | false | Enable/disable a full page body scan to get email. |
|
|
11
|
+
| `formElementId` | No | String | N/A | ID attribute of the input (type=text/email) from which the email can be read. |
|
|
12
|
+
| `inputscan` | No | Boolean | N/A | Enable/disable a input element (type=text/email) scan to get email. |
|
|
11
13
|
|
|
12
14
|
## Example
|
|
13
15
|
|
|
@@ -18,5 +20,7 @@ pbjs.setConfig({
|
|
|
18
20
|
url: 'https://example.com',
|
|
19
21
|
debounce: 250,
|
|
20
22
|
fullscan: false,
|
|
23
|
+
inputscan: false,
|
|
24
|
+
formElementId: "userid"
|
|
21
25
|
},
|
|
22
26
|
});
|