prebid.js 6.26.0 → 6.27.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/adWMGAnalyticsAdapter.js +1 -1
- package/dist/adagioAnalyticsAdapter.js +1 -1
- package/dist/adagioBidAdapter.js +1 -1
- package/dist/adbookpspBidAdapter.js +1 -1
- package/dist/adgenerationBidAdapter.js +1 -1
- package/dist/adkernelAdnAnalyticsAdapter.js +1 -1
- package/dist/adlooxAdServerVideo.js +1 -1
- package/dist/adlooxAnalyticsAdapter.js +1 -1
- package/dist/adlooxRtdProvider.js +1 -1
- package/dist/adomikAnalyticsAdapter.js +1 -1
- package/dist/adrelevantisBidAdapter.js +1 -1
- package/dist/adxcgAnalyticsAdapter.js +1 -1
- package/dist/adxcgBidAdapter.js +1 -1
- package/dist/adxpremiumAnalyticsAdapter.js +1 -1
- package/dist/ajaBidAdapter.js +1 -1
- package/dist/akamaiDapRtdProvider.js +1 -1
- package/dist/amxBidAdapter.js +1 -1
- package/dist/amxIdSystem.js +1 -1
- package/dist/appierAnalyticsAdapter.js +1 -1
- package/dist/appnexusAnalyticsAdapter.js +1 -1
- package/dist/appnexusBidAdapter.js +1 -1
- package/dist/asoBidAdapter.js +1 -1
- package/dist/atsAnalyticsAdapter.js +1 -1
- package/dist/axonixBidAdapter.js +1 -1
- package/dist/bidglassBidAdapter.js +1 -1
- package/dist/bidwatchAnalyticsAdapter.js +1 -1
- package/dist/big-richmediaBidAdapter.js +1 -1
- package/dist/bridgewellBidAdapter.js +1 -1
- package/dist/brightMountainMediaBidAdapter.js +1 -1
- package/dist/byDataAnalyticsAdapter.js +1 -1
- package/dist/colossussspBidAdapter.js +1 -1
- package/dist/concertAnalyticsAdapter.js +1 -1
- package/dist/concertBidAdapter.js +1 -1
- package/dist/connectadBidAdapter.js +1 -1
- package/dist/consumableBidAdapter.js +1 -1
- package/dist/conversantBidAdapter.js +1 -1
- package/dist/craftBidAdapter.js +1 -1
- package/dist/criteoBidAdapter.js +1 -1
- package/dist/datablocksAnalyticsAdapter.js +1 -1
- package/dist/dspxBidAdapter.js +1 -1
- package/dist/eplanningAnalyticsAdapter.js +1 -1
- package/dist/eplanningBidAdapter.js +1 -1
- package/dist/fintezaAnalyticsAdapter.js +1 -1
- package/dist/ftrackIdSystem.js +1 -1
- package/dist/glimpseBidAdapter.js +1 -1
- package/dist/gmosspBidAdapter.js +1 -1
- package/dist/goldbachBidAdapter.js +1 -1
- package/dist/gridBidAdapter.js +1 -1
- package/dist/gridNMBidAdapter.js +1 -1
- package/dist/gumgumBidAdapter.js +1 -1
- package/dist/h12mediaBidAdapter.js +1 -1
- package/dist/hadronAnalyticsAdapter.js +1 -1
- package/dist/id5AnalyticsAdapter.js +1 -1
- package/dist/id5IdSystem.js +1 -1
- package/dist/improvedigitalBidAdapter.js +1 -1
- package/dist/inmarBidAdapter.js +1 -1
- package/dist/insticatorBidAdapter.js +1 -1
- package/dist/invisiblyAnalyticsAdapter.js +1 -1
- package/dist/ixBidAdapter.js +1 -1
- package/dist/justpremiumBidAdapter.js +1 -1
- package/dist/kargoAnalyticsAdapter.js +1 -1
- package/dist/koblerBidAdapter.js +1 -1
- package/dist/konduitAnalyticsAdapter.js +1 -1
- package/dist/livewrappedAnalyticsAdapter.js +1 -1
- package/dist/liveyieldAnalyticsAdapter.js +1 -1
- package/dist/logicadBidAdapter.js +1 -1
- package/dist/loglyliftBidAdapter.js +1 -1
- package/dist/malltvAnalyticsAdapter.js +1 -1
- package/dist/marsmediaAnalyticsAdapter.js +1 -1
- package/dist/marsmediaBidAdapter.js +1 -1
- package/dist/mediafuseBidAdapter.js +1 -1
- package/dist/medianetAnalyticsAdapter.js +1 -1
- package/dist/mediasquareBidAdapter.js +1 -1
- package/dist/mgidBidAdapter.js +1 -1
- package/dist/minutemediaBidAdapter.js +1 -1
- package/dist/naveggIdSystem.js +1 -1
- package/dist/not-for-prod/prebid.js +153 -152
- package/dist/novatiqIdSystem.js +1 -1
- package/dist/oguryBidAdapter.js +1 -1
- package/dist/oneVideoBidAdapter.js +1 -1
- package/dist/onetagBidAdapter.js +1 -1
- package/dist/ooloAnalyticsAdapter.js +1 -1
- package/dist/openxAnalyticsAdapter.js +1 -1
- package/dist/optimonAnalyticsAdapter.js +1 -1
- package/dist/outbrainBidAdapter.js +1 -1
- package/dist/parrableIdSystem.js +1 -1
- package/dist/pixfutureBidAdapter.js +1 -1
- package/dist/prebid-core.js +3 -3
- package/dist/prebidmanagerAnalyticsAdapter.js +1 -1
- package/dist/publinkIdSystem.js +1 -1
- package/dist/pubmaticAnalyticsAdapter.js +1 -1
- package/dist/pubmaticBidAdapter.js +1 -1
- package/dist/pubperfAnalyticsAdapter.js +1 -1
- package/dist/pubstackAnalyticsAdapter.js +1 -1
- package/dist/pubwiseAnalyticsAdapter.js +1 -1
- package/dist/pubxaiAnalyticsAdapter.js +1 -1
- package/dist/pulsepointAnalyticsAdapter.js +1 -1
- package/dist/pxyzBidAdapter.js +1 -1
- package/dist/quantcastBidAdapter.js +1 -1
- package/dist/readpeakBidAdapter.js +1 -1
- package/dist/realvuAnalyticsAdapter.js +1 -1
- package/dist/relaidoBidAdapter.js +1 -1
- package/dist/relevantAnalyticsAdapter.js +1 -1
- package/dist/rhythmoneBidAdapter.js +1 -1
- package/dist/riseBidAdapter.js +1 -1
- package/dist/rivrAnalyticsAdapter.js +1 -1
- package/dist/roxotAnalyticsAdapter.js +1 -1
- package/dist/rubiconAnalyticsAdapter.js +1 -1
- package/dist/rubiconBidAdapter.js +1 -1
- package/dist/scaleableAnalyticsAdapter.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/sigmoidAnalyticsAdapter.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/sonobiAnalyticsAdapter.js +1 -1
- package/dist/sonobiBidAdapter.js +1 -1
- package/dist/sortableAnalyticsAdapter.js +1 -1
- package/dist/sortableBidAdapter.js +1 -1
- package/dist/sovrnAnalyticsAdapter.js +1 -1
- package/dist/sovrnBidAdapter.js +1 -1
- package/dist/sspBCBidAdapter.js +1 -1
- package/dist/staqAnalyticsAdapter.js +1 -1
- package/dist/sublimeBidAdapter.js +1 -1
- package/dist/synacormediaBidAdapter.js +1 -1
- package/dist/taboolaBidAdapter.js +1 -0
- package/dist/targetVideoBidAdapter.js +1 -1
- package/dist/teadsBidAdapter.js +1 -1
- package/dist/terceptAnalyticsAdapter.js +1 -1
- package/dist/trionBidAdapter.js +1 -1
- package/dist/tripleliftBidAdapter.js +1 -1
- package/dist/trustxBidAdapter.js +1 -1
- package/dist/ttdBidAdapter.js +1 -1
- package/dist/ucfunnelAnalyticsAdapter.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/dist/yuktamediaAnalyticsAdapter.js +1 -1
- package/dist/zeta_global_sspAnalyticsAdapter.js +1 -1
- package/integrationExamples/gpt/akamaidap_segments_example.html +5 -3
- package/modules/.submodules.json +1 -0
- package/modules/adlooxAnalyticsAdapter.js +9 -5
- package/modules/adlooxAnalyticsAdapter.md +3 -3
- package/modules/adlooxRtdProvider.js +3 -5
- package/modules/adlooxRtdProvider.md +2 -2
- package/modules/akamaiDapRtdProvider.js +460 -130
- package/modules/akamaiDapRtdProvider.md +5 -3
- package/modules/colossussspBidAdapter.js +17 -17
- package/modules/conversantBidAdapter.js +2 -2
- package/modules/ftrackIdSystem.js +3 -4
- package/modules/hadronAnalyticsAdapter.js +5 -1
- package/modules/koblerBidAdapter.js +54 -45
- package/modules/koblerBidAdapter.md +12 -17
- package/modules/naveggIdSystem.js +3 -2
- package/modules/novatiqIdSystem.js +6 -1
- package/modules/relaidoBidAdapter.js +0 -3
- package/modules/taboolaBidAdapter.js +265 -0
- package/modules/taboolaBidAdapter.md +49 -0
- package/package.json +1 -1
- package/src/AnalyticsAdapter.js +5 -1
- package/src/adloader.js +2 -1
- package/test/mocks/analyticsStub.js +13 -0
- package/test/mocks/xhr.js +22 -0
- package/test/spec/AnalyticsAdapter_spec.js +4 -0
- package/test/spec/modules/akamaiDapRtdProvider_spec.js +402 -108
- package/test/spec/modules/conversantBidAdapter_spec.js +36 -5
- package/test/spec/modules/datablocksBidAdapter_spec.js +9 -8
- package/test/spec/modules/fintezaAnalyticsAdapter_spec.js +4 -4
- package/test/spec/modules/ftrackIdSystem_spec.js +1 -9
- package/test/spec/modules/koblerBidAdapter_spec.js +160 -124
- package/test/spec/modules/naveggIdSystem_spec.js +25 -1
- package/test/spec/modules/proxistoreBidAdapter_spec.js +0 -2
- package/test/spec/modules/sovrnBidAdapter_spec.js +253 -264
- package/test/spec/modules/taboolaBidAdapter_spec.js +455 -0
- package/test/test_deps.js +1 -0
|
@@ -10,12 +10,22 @@ import {config} from '../src/config.js';
|
|
|
10
10
|
import {getStorageManager} from '../src/storageManager.js';
|
|
11
11
|
import {submodule} from '../src/hook.js';
|
|
12
12
|
import {isPlainObject, mergeDeep, logMessage, logInfo, logError} from '../src/utils.js';
|
|
13
|
+
import { loadExternalScript } from '../src/adloader.js';
|
|
13
14
|
|
|
14
15
|
const MODULE_NAME = 'realTimeData';
|
|
15
16
|
const SUBMODULE_NAME = 'dap';
|
|
17
|
+
const MODULE_CODE = 'akamaidap';
|
|
18
|
+
|
|
19
|
+
export const DAP_TOKEN = 'async_dap_token';
|
|
20
|
+
export const DAP_MEMBERSHIP = 'async_dap_membership';
|
|
21
|
+
export const DAP_ENCRYPTED_MEMBERSHIP = 'encrypted_dap_membership';
|
|
22
|
+
export const DAP_SS_ID = 'dap_ss_id';
|
|
23
|
+
export const DAP_DEFAULT_TOKEN_TTL = 3600; // in seconds
|
|
24
|
+
export const DAP_MAX_RETRY_TOKENIZE = 1;
|
|
25
|
+
export const DAP_CLIENT_ENTROPY = 'dap_client_entropy'
|
|
16
26
|
|
|
17
|
-
export const SEGMENTS_STORAGE_KEY = 'akamaiDapSegments';
|
|
18
27
|
export const storage = getStorageManager({gvlid: null, moduleName: SUBMODULE_NAME});
|
|
28
|
+
let dapRetryTokenize = 0;
|
|
19
29
|
|
|
20
30
|
/**
|
|
21
31
|
* Lazy merge objects.
|
|
@@ -53,60 +63,92 @@ export function addRealTimeData(rtd) {
|
|
|
53
63
|
* Real-time data retrieval from Audigent
|
|
54
64
|
* @param {Object} reqBidsConfigObj
|
|
55
65
|
* @param {function} onDone
|
|
56
|
-
* @param {Object}
|
|
66
|
+
* @param {Object} rtdConfig
|
|
57
67
|
* @param {Object} userConsent
|
|
58
68
|
*/
|
|
59
69
|
export function getRealTimeData(bidConfig, onDone, rtdConfig, userConsent) {
|
|
60
|
-
|
|
70
|
+
let entropyDict = JSON.parse(storage.getDataFromLocalStorage(DAP_CLIENT_ENTROPY));
|
|
71
|
+
let loadScriptPromise = new Promise((resolve, reject) => {
|
|
72
|
+
if (rtdConfig && rtdConfig.params && rtdConfig.params.dapFpTimeout && Number.isInteger(rtdConfig.params.dapFpTimeout)) {
|
|
73
|
+
setTimeout(reject, rtdConfig.params.dapFpTimeout, Error('DapFP script could not be loaded'));
|
|
74
|
+
}
|
|
75
|
+
if (entropyDict && entropyDict.expires_at > Math.round(Date.now() / 1000.0)) {
|
|
76
|
+
logMessage('Using cached entropy');
|
|
77
|
+
resolve();
|
|
78
|
+
} else {
|
|
79
|
+
if (typeof window.dapCalculateEntropy === 'function') {
|
|
80
|
+
window.dapCalculateEntropy(resolve, reject);
|
|
81
|
+
} else {
|
|
82
|
+
if (rtdConfig && rtdConfig.params && dapUtils.isValidHttpsUrl(rtdConfig.params.dapFpUrl)) {
|
|
83
|
+
loadExternalScript(rtdConfig.params.dapFpUrl, MODULE_CODE, () => { dapUtils.dapGetEntropy(resolve, reject) });
|
|
84
|
+
} else {
|
|
85
|
+
reject(Error('Please check if dapFpUrl is specified and is valid under config.params'));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
loadScriptPromise
|
|
91
|
+
.catch((error) => {
|
|
92
|
+
logError('Entropy could not be calculated due to: ', error.message);
|
|
93
|
+
})
|
|
94
|
+
.finally(() => {
|
|
95
|
+
generateRealTimeData(bidConfig, onDone, rtdConfig, userConsent);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function generateRealTimeData(bidConfig, onDone, rtdConfig, userConsent) {
|
|
100
|
+
logInfo('DEBUG(generateRealTimeData) - ENTER');
|
|
61
101
|
logMessage(' - apiHostname: ' + rtdConfig.params.apiHostname);
|
|
62
102
|
logMessage(' - apiVersion: ' + rtdConfig.params.apiVersion);
|
|
63
|
-
|
|
103
|
+
dapRetryTokenize = 0;
|
|
104
|
+
var jsonData = null;
|
|
105
|
+
if (rtdConfig && isPlainObject(rtdConfig.params)) {
|
|
106
|
+
if (rtdConfig.params.segtax == 504) {
|
|
107
|
+
let encMembership = dapUtils.dapGetEncryptedMembershipFromLocalStorage();
|
|
108
|
+
if (encMembership) {
|
|
109
|
+
jsonData = dapUtils.dapGetEncryptedRtdObj(encMembership, rtdConfig.params.segtax)
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
112
|
+
let membership = dapUtils.dapGetMembershipFromLocalStorage();
|
|
113
|
+
if (membership) {
|
|
114
|
+
jsonData = dapUtils.dapGetRtdObj(membership, rtdConfig.params.segtax)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
64
118
|
if (jsonData) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
addRealTimeData(data.rtd);
|
|
119
|
+
if (jsonData.rtd) {
|
|
120
|
+
addRealTimeData(jsonData.rtd);
|
|
68
121
|
onDone();
|
|
69
|
-
logInfo('DEBUG(
|
|
122
|
+
logInfo('DEBUG(generateRealTimeData) - 1');
|
|
70
123
|
// Don't return - ensure the data is always fresh.
|
|
71
124
|
}
|
|
72
125
|
}
|
|
126
|
+
// Calling setTimeout to release the main thread so that the bid request could be sent.
|
|
127
|
+
setTimeout(callDapAPIs, 0, bidConfig, onDone, rtdConfig, userConsent);
|
|
128
|
+
}
|
|
73
129
|
|
|
130
|
+
function callDapAPIs(bidConfig, onDone, rtdConfig, userConsent) {
|
|
74
131
|
if (rtdConfig && isPlainObject(rtdConfig.params)) {
|
|
75
132
|
let config = {
|
|
76
133
|
api_hostname: rtdConfig.params.apiHostname,
|
|
77
134
|
api_version: rtdConfig.params.apiVersion,
|
|
78
135
|
domain: rtdConfig.params.domain,
|
|
79
|
-
segtax: rtdConfig.params.segtax
|
|
80
|
-
|
|
81
|
-
let identity = {
|
|
82
|
-
type: rtdConfig.params.identityType
|
|
136
|
+
segtax: rtdConfig.params.segtax,
|
|
137
|
+
identity: {type: rtdConfig.params.identityType}
|
|
83
138
|
};
|
|
84
|
-
let
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
]
|
|
96
|
-
},
|
|
97
|
-
site: {
|
|
98
|
-
ext: {
|
|
99
|
-
data: {
|
|
100
|
-
dapSAID: membership.said
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
storage.setDataInLocalStorage(SEGMENTS_STORAGE_KEY, JSON.stringify(data));
|
|
108
|
-
onDone();
|
|
139
|
+
let refreshMembership = true;
|
|
140
|
+
let token = dapUtils.dapGetTokenFromLocalStorage();
|
|
141
|
+
logMessage('token is: ', token);
|
|
142
|
+
if (token !== null) { // If token is not null then check the membership in storage and add the RTD object
|
|
143
|
+
if (config.segtax == 504) { // Follow the encrypted membership path
|
|
144
|
+
dapUtils.dapRefreshEncryptedMembership(config, token, onDone) // Get the encrypted membership from server
|
|
145
|
+
refreshMembership = false;
|
|
146
|
+
} else {
|
|
147
|
+
dapUtils.dapRefreshMembership(config, token, onDone) // Get the membership from server
|
|
148
|
+
refreshMembership = false;
|
|
149
|
+
}
|
|
109
150
|
}
|
|
151
|
+
dapUtils.dapRefreshToken(config, refreshMembership, onDone) // Refresh Token and membership in all the cases
|
|
110
152
|
}
|
|
111
153
|
}
|
|
112
154
|
|
|
@@ -117,6 +159,9 @@ export function getRealTimeData(bidConfig, onDone, rtdConfig, userConsent) {
|
|
|
117
159
|
* @return {boolean}
|
|
118
160
|
*/
|
|
119
161
|
function init(provider, userConsent) {
|
|
162
|
+
if (dapUtils.checkConsent(userConsent) === false) {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
120
165
|
return true;
|
|
121
166
|
}
|
|
122
167
|
|
|
@@ -128,104 +173,190 @@ export const akamaiDapRtdSubmodule = {
|
|
|
128
173
|
};
|
|
129
174
|
|
|
130
175
|
submodule(MODULE_NAME, akamaiDapRtdSubmodule);
|
|
131
|
-
|
|
132
176
|
export const dapUtils = {
|
|
177
|
+
dapGetEntropy: function(resolve, reject) {
|
|
178
|
+
if (typeof window.dapCalculateEntropy === 'function') {
|
|
179
|
+
window.dapCalculateEntropy(resolve, reject);
|
|
180
|
+
} else {
|
|
181
|
+
reject(Error('window.dapCalculateEntropy function is not defined'))
|
|
182
|
+
}
|
|
183
|
+
},
|
|
133
184
|
|
|
134
|
-
|
|
185
|
+
dapGetTokenFromLocalStorage: function(ttl) {
|
|
135
186
|
let now = Math.round(Date.now() / 1000.0); // in seconds
|
|
136
|
-
let storageName = 'async_dap_token';
|
|
137
187
|
let token = null;
|
|
138
|
-
|
|
139
|
-
if (
|
|
140
|
-
|
|
188
|
+
let item = JSON.parse(storage.getDataFromLocalStorage(DAP_TOKEN));
|
|
189
|
+
if (item) {
|
|
190
|
+
if (now < item.expires_at) {
|
|
191
|
+
token = item.token;
|
|
192
|
+
}
|
|
141
193
|
}
|
|
194
|
+
return token;
|
|
195
|
+
},
|
|
142
196
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
token
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
197
|
+
dapRefreshToken: function(config, refreshMembership, onDone) {
|
|
198
|
+
dapUtils.dapLog('Token missing or expired, fetching a new one...');
|
|
199
|
+
// Trigger a refresh
|
|
200
|
+
let now = Math.round(Date.now() / 1000.0); // in seconds
|
|
201
|
+
let item = {}
|
|
202
|
+
let configAsync = {...config};
|
|
203
|
+
dapUtils.dapTokenize(configAsync, config.identity, onDone,
|
|
204
|
+
function(token, status, xhr, onDone) {
|
|
205
|
+
item.expires_at = now + DAP_DEFAULT_TOKEN_TTL;
|
|
206
|
+
let exp = dapUtils.dapExtractExpiryFromToken(token)
|
|
207
|
+
if (typeof exp == 'number') {
|
|
208
|
+
item.expires_at = exp - 10;
|
|
209
|
+
}
|
|
210
|
+
item.token = token;
|
|
211
|
+
storage.setDataInLocalStorage(DAP_TOKEN, JSON.stringify(item));
|
|
212
|
+
dapUtils.dapLog('Successfully updated and stored token; expires at ' + item.expires_at);
|
|
213
|
+
let dapSSID = xhr.getResponseHeader('Akamai-DAP-SS-ID');
|
|
214
|
+
if (dapSSID) {
|
|
215
|
+
storage.setDataInLocalStorage(DAP_SS_ID, JSON.stringify(dapSSID));
|
|
216
|
+
}
|
|
217
|
+
let deviceId100 = xhr.getResponseHeader('Akamai-DAP-100');
|
|
218
|
+
if (deviceId100 != null) {
|
|
219
|
+
storage.setDataInLocalStorage('dap_deviceId100', deviceId100);
|
|
220
|
+
dapUtils.dapLog('Successfully stored DAP 100 Device ID: ' + deviceId100);
|
|
221
|
+
}
|
|
222
|
+
if (refreshMembership) {
|
|
223
|
+
if (config.segtax == 504) {
|
|
224
|
+
dapUtils.dapRefreshEncryptedMembership(config, token, onDone);
|
|
225
|
+
} else {
|
|
226
|
+
dapUtils.dapRefreshMembership(config, token, onDone);
|
|
167
227
|
}
|
|
168
|
-
},
|
|
169
|
-
function(xhr, status, error) {
|
|
170
|
-
logError('ERROR(' + error + '): failed to retrieve token! ' + status);
|
|
171
228
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
229
|
+
},
|
|
230
|
+
function(xhr, status, error, onDone) {
|
|
231
|
+
logError('ERROR(' + error + '): failed to retrieve token! ' + status);
|
|
232
|
+
onDone()
|
|
233
|
+
}
|
|
234
|
+
);
|
|
176
235
|
},
|
|
177
236
|
|
|
178
|
-
|
|
237
|
+
dapGetMembershipFromLocalStorage: function() {
|
|
179
238
|
let now = Math.round(Date.now() / 1000.0); // in seconds
|
|
180
|
-
let storageName = 'async_dap_membership';
|
|
181
|
-
let maxTtl = 3600; // if the cached membership is older than this, return null
|
|
182
239
|
let membership = null;
|
|
183
|
-
let item = JSON.parse(
|
|
184
|
-
if (item
|
|
185
|
-
item
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
membership = {
|
|
193
|
-
said: item.said,
|
|
194
|
-
cohorts: item.cohorts,
|
|
195
|
-
attributes: null
|
|
196
|
-
};
|
|
240
|
+
let item = JSON.parse(storage.getDataFromLocalStorage(DAP_MEMBERSHIP));
|
|
241
|
+
if (item) {
|
|
242
|
+
if (now < item.expires_at) {
|
|
243
|
+
membership = {
|
|
244
|
+
said: item.said,
|
|
245
|
+
cohorts: item.cohorts,
|
|
246
|
+
attributes: null
|
|
247
|
+
};
|
|
248
|
+
}
|
|
197
249
|
}
|
|
250
|
+
return membership;
|
|
251
|
+
},
|
|
198
252
|
|
|
199
|
-
|
|
253
|
+
dapRefreshMembership: function(config, token, onDone) {
|
|
254
|
+
let now = Math.round(Date.now() / 1000.0); // in seconds
|
|
255
|
+
let item = {}
|
|
200
256
|
let configAsync = {...config};
|
|
201
|
-
dapUtils.dapMembership(configAsync, token,
|
|
202
|
-
function(membership, status, xhr) {
|
|
203
|
-
item.expires_at = now +
|
|
257
|
+
dapUtils.dapMembership(configAsync, token, onDone,
|
|
258
|
+
function(membership, status, xhr, onDone) {
|
|
259
|
+
item.expires_at = now + DAP_DEFAULT_TOKEN_TTL;
|
|
260
|
+
let exp = dapUtils.dapExtractExpiryFromToken(membership.said)
|
|
261
|
+
if (typeof exp == 'number') {
|
|
262
|
+
item.expires_at = exp - 10;
|
|
263
|
+
}
|
|
204
264
|
item.said = membership.said;
|
|
205
265
|
item.cohorts = membership.cohorts;
|
|
206
|
-
|
|
266
|
+
storage.setDataInLocalStorage(DAP_MEMBERSHIP, JSON.stringify(item));
|
|
207
267
|
dapUtils.dapLog('Successfully updated and stored membership:');
|
|
208
268
|
dapUtils.dapLog(item);
|
|
269
|
+
|
|
270
|
+
let data = dapUtils.dapGetRtdObj(item, config.segtax)
|
|
271
|
+
dapUtils.checkAndAddRealtimeData(data, config.segtax);
|
|
272
|
+
onDone();
|
|
209
273
|
},
|
|
210
|
-
function(xhr, status, error) {
|
|
274
|
+
function(xhr, status, error, onDone) {
|
|
211
275
|
logError('ERROR(' + error + '): failed to retrieve membership! ' + status);
|
|
276
|
+
if (status == 403 && dapRetryTokenize < DAP_MAX_RETRY_TOKENIZE) {
|
|
277
|
+
dapRetryTokenize++;
|
|
278
|
+
dapUtils.dapRefreshToken(config, true, onDone);
|
|
279
|
+
} else {
|
|
280
|
+
onDone();
|
|
281
|
+
}
|
|
212
282
|
}
|
|
213
283
|
);
|
|
284
|
+
},
|
|
214
285
|
|
|
215
|
-
|
|
286
|
+
dapGetEncryptedMembershipFromLocalStorage: function() {
|
|
287
|
+
let now = Math.round(Date.now() / 1000.0); // in seconds
|
|
288
|
+
let encMembership = null;
|
|
289
|
+
let item = JSON.parse(storage.getDataFromLocalStorage(DAP_ENCRYPTED_MEMBERSHIP));
|
|
290
|
+
if (item) {
|
|
291
|
+
if (now < item.expires_at) {
|
|
292
|
+
encMembership = {
|
|
293
|
+
encryptedSegments: item.encryptedSegments
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return encMembership;
|
|
298
|
+
},
|
|
299
|
+
|
|
300
|
+
dapRefreshEncryptedMembership: function(config, token, onDone) {
|
|
301
|
+
let now = Math.round(Date.now() / 1000.0); // in seconds
|
|
302
|
+
let item = {};
|
|
303
|
+
let configAsync = {...config};
|
|
304
|
+
dapUtils.dapEncryptedMembership(configAsync, token, onDone,
|
|
305
|
+
function(encToken, status, xhr, onDone) {
|
|
306
|
+
item.expires_at = now + DAP_DEFAULT_TOKEN_TTL;
|
|
307
|
+
let exp = dapUtils.dapExtractExpiryFromToken(encToken)
|
|
308
|
+
if (typeof exp == 'number') {
|
|
309
|
+
item.expires_at = exp - 10;
|
|
310
|
+
}
|
|
311
|
+
item.encryptedSegments = encToken;
|
|
312
|
+
storage.setDataInLocalStorage(DAP_ENCRYPTED_MEMBERSHIP, JSON.stringify(item));
|
|
313
|
+
dapUtils.dapLog('Successfully updated and stored encrypted membership:');
|
|
314
|
+
dapUtils.dapLog(item);
|
|
315
|
+
|
|
316
|
+
let encData = dapUtils.dapGetEncryptedRtdObj(item, config.segtax);
|
|
317
|
+
dapUtils.checkAndAddRealtimeData(encData, config.segtax);
|
|
318
|
+
onDone();
|
|
319
|
+
},
|
|
320
|
+
function(xhr, status, error, onDone) {
|
|
321
|
+
logError('ERROR(' + error + '): failed to retrieve encrypted membership! ' + status);
|
|
322
|
+
if (status == 403 && dapRetryTokenize < DAP_MAX_RETRY_TOKENIZE) {
|
|
323
|
+
dapRetryTokenize++;
|
|
324
|
+
dapUtils.dapRefreshToken(config, true, onDone);
|
|
325
|
+
} else {
|
|
326
|
+
onDone();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
);
|
|
330
|
+
},
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* DESCRIPTION
|
|
334
|
+
* Extract expiry value from a token
|
|
335
|
+
*/
|
|
336
|
+
dapExtractExpiryFromToken: function(token) {
|
|
337
|
+
let exp = null;
|
|
338
|
+
if (token) {
|
|
339
|
+
const tokenArray = token.split('..');
|
|
340
|
+
if (tokenArray && tokenArray.length > 0) {
|
|
341
|
+
let decode = atob(tokenArray[0])
|
|
342
|
+
let header = JSON.parse(decode.replace(/"/g, '"'));
|
|
343
|
+
exp = header.exp;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return exp
|
|
216
347
|
},
|
|
217
348
|
|
|
218
349
|
/**
|
|
219
350
|
* DESCRIPTION
|
|
220
351
|
*
|
|
221
352
|
* Convert a DAP membership response to an OpenRTB2 segment object suitable
|
|
222
|
-
* for insertion into user.data.segment or site.data.segment.
|
|
353
|
+
* for insertion into user.data.segment or site.data.segment and add it to the rtd obj.
|
|
223
354
|
*/
|
|
224
|
-
|
|
355
|
+
dapGetRtdObj: function(membership, segtax) {
|
|
225
356
|
let segment = {
|
|
226
357
|
name: 'dap.akamai.com',
|
|
227
358
|
ext: {
|
|
228
|
-
'segtax':
|
|
359
|
+
'segtax': segtax
|
|
229
360
|
},
|
|
230
361
|
segment: []
|
|
231
362
|
};
|
|
@@ -234,7 +365,83 @@ export const dapUtils = {
|
|
|
234
365
|
segment.segment.push({ id: i });
|
|
235
366
|
}
|
|
236
367
|
}
|
|
237
|
-
|
|
368
|
+
let data = {
|
|
369
|
+
rtd: {
|
|
370
|
+
ortb2: {
|
|
371
|
+
user: {
|
|
372
|
+
data: [
|
|
373
|
+
segment
|
|
374
|
+
]
|
|
375
|
+
},
|
|
376
|
+
site: {
|
|
377
|
+
ext: {
|
|
378
|
+
data: {
|
|
379
|
+
dapSAID: membership.said
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
return data;
|
|
387
|
+
},
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* DESCRIPTION
|
|
391
|
+
*
|
|
392
|
+
* Convert a DAP membership response to an OpenRTB2 segment object suitable
|
|
393
|
+
* for insertion into user.data.segment or site.data.segment and add it to the rtd obj.
|
|
394
|
+
*/
|
|
395
|
+
dapGetEncryptedRtdObj: function(encToken, segtax) {
|
|
396
|
+
let segment = {
|
|
397
|
+
name: 'dap.akamai.com',
|
|
398
|
+
ext: {
|
|
399
|
+
'segtax': segtax
|
|
400
|
+
},
|
|
401
|
+
segment: []
|
|
402
|
+
};
|
|
403
|
+
if (encToken != null) {
|
|
404
|
+
segment.segment.push({ id: encToken.encryptedSegments });
|
|
405
|
+
}
|
|
406
|
+
let encData = {
|
|
407
|
+
rtd: {
|
|
408
|
+
ortb2: {
|
|
409
|
+
user: {
|
|
410
|
+
data: [
|
|
411
|
+
segment
|
|
412
|
+
]
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
return encData;
|
|
418
|
+
},
|
|
419
|
+
|
|
420
|
+
checkAndAddRealtimeData: function(data, segtax) {
|
|
421
|
+
if (data.rtd) {
|
|
422
|
+
if (segtax == 504 && dapUtils.checkIfSegmentsAlreadyExist(data.rtd, 504)) {
|
|
423
|
+
logMessage('DEBUG(handleInit): rtb Object already added');
|
|
424
|
+
} else {
|
|
425
|
+
addRealTimeData(data.rtd);
|
|
426
|
+
}
|
|
427
|
+
logInfo('DEBUG(checkAndAddRealtimeData) - 1');
|
|
428
|
+
}
|
|
429
|
+
},
|
|
430
|
+
|
|
431
|
+
checkIfSegmentsAlreadyExist: function(rtd, segtax) {
|
|
432
|
+
let segmentsExist = false
|
|
433
|
+
let ortb2 = config.getConfig('ortb2') || {};
|
|
434
|
+
if (ortb2.user && ortb2.user.data && ortb2.user.data.length > 0) {
|
|
435
|
+
for (let i = 0; i < ortb2.user.data.length; i++) {
|
|
436
|
+
let element = ortb2.user.data[i]
|
|
437
|
+
if (element.ext && element.ext.segtax == segtax) {
|
|
438
|
+
segmentsExist = true
|
|
439
|
+
logMessage('DEBUG(checkIfSegmentsAlreadyExist): rtb Object already added: ', ortb2.user.data);
|
|
440
|
+
break;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
return segmentsExist
|
|
238
445
|
},
|
|
239
446
|
|
|
240
447
|
dapLog: function(args) {
|
|
@@ -248,6 +455,35 @@ export const dapUtils = {
|
|
|
248
455
|
logInfo('%cDAP Client', css, args);
|
|
249
456
|
},
|
|
250
457
|
|
|
458
|
+
isValidHttpsUrl: function(urlString) {
|
|
459
|
+
let url;
|
|
460
|
+
try {
|
|
461
|
+
url = new URL(urlString);
|
|
462
|
+
} catch (_) {
|
|
463
|
+
return false;
|
|
464
|
+
}
|
|
465
|
+
return url.protocol === 'https:';
|
|
466
|
+
},
|
|
467
|
+
|
|
468
|
+
checkConsent: function(userConsent) {
|
|
469
|
+
let consent = true;
|
|
470
|
+
|
|
471
|
+
if (userConsent && userConsent.gdpr && userConsent.gdpr.gdprApplies) {
|
|
472
|
+
const gdpr = userConsent.gdpr;
|
|
473
|
+
const hasGdpr = (gdpr && typeof gdpr.gdprApplies === 'boolean' && gdpr.gdprApplies) ? 1 : 0;
|
|
474
|
+
const gdprConsentString = hasGdpr ? gdpr.consentString : '';
|
|
475
|
+
if (hasGdpr && (!gdprConsentString || gdprConsentString === '')) {
|
|
476
|
+
logError('akamaiDapRtd submodule requires consent string to call API');
|
|
477
|
+
consent = false;
|
|
478
|
+
}
|
|
479
|
+
} else if (userConsent && userConsent.usp) {
|
|
480
|
+
const usp = userConsent.usp;
|
|
481
|
+
consent = usp[1] !== 'N' && usp[2] !== 'Y';
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
return consent;
|
|
485
|
+
},
|
|
486
|
+
|
|
251
487
|
/*******************************************************************************
|
|
252
488
|
*
|
|
253
489
|
* V2 (And Beyond) API
|
|
@@ -293,23 +529,23 @@ export const dapUtils = {
|
|
|
293
529
|
* function( response, status, xhr } { token = response; },
|
|
294
530
|
* function( xhr, status, error ) { ; } // handle error
|
|
295
531
|
*/
|
|
296
|
-
dapTokenize: function(config, identity, onSuccess = null, onError = null) {
|
|
532
|
+
dapTokenize: function(config, identity, onDone, onSuccess = null, onError = null) {
|
|
297
533
|
if (onError == null) {
|
|
298
|
-
onError = function(xhr, status, error) {};
|
|
534
|
+
onError = function(xhr, status, error, onDone) {};
|
|
299
535
|
}
|
|
300
536
|
|
|
301
537
|
if (config == null || typeof (config) == typeof (undefined)) {
|
|
302
|
-
onError(null, 'Invalid config object', 'ClientError');
|
|
538
|
+
onError(null, 'Invalid config object', 'ClientError', onDone);
|
|
303
539
|
return;
|
|
304
540
|
}
|
|
305
541
|
|
|
306
542
|
if (typeof (config.domain) != 'string') {
|
|
307
|
-
onError(null, 'Invalid config.domain: must be a string', 'ClientError');
|
|
543
|
+
onError(null, 'Invalid config.domain: must be a string', 'ClientError', onDone);
|
|
308
544
|
return;
|
|
309
545
|
}
|
|
310
546
|
|
|
311
547
|
if (config.domain.length <= 0) {
|
|
312
|
-
onError(null, 'Invalid config.domain: must have non-zero length', 'ClientError');
|
|
548
|
+
onError(null, 'Invalid config.domain: must have non-zero length', 'ClientError', onDone);
|
|
313
549
|
return;
|
|
314
550
|
}
|
|
315
551
|
|
|
@@ -318,22 +554,22 @@ export const dapUtils = {
|
|
|
318
554
|
}
|
|
319
555
|
|
|
320
556
|
if (typeof (config.api_version) != 'string') {
|
|
321
|
-
onError(null, "Invalid api_version: must be a string like 'x1', etc.", 'ClientError');
|
|
557
|
+
onError(null, "Invalid api_version: must be a string like 'x1', etc.", 'ClientError', onDone);
|
|
322
558
|
return;
|
|
323
559
|
}
|
|
324
560
|
|
|
325
561
|
if (!(('api_hostname') in config) || typeof (config.api_hostname) != 'string' || config.api_hostname.length == 0) {
|
|
326
|
-
onError(null, 'Invalid api_hostname: must be a non-empty string', 'ClientError');
|
|
562
|
+
onError(null, 'Invalid api_hostname: must be a non-empty string', 'ClientError', onDone);
|
|
327
563
|
return;
|
|
328
564
|
}
|
|
329
565
|
|
|
330
566
|
if (identity == null || typeof (identity) == typeof (undefined)) {
|
|
331
|
-
onError(null, 'Invalid identity object', 'ClientError');
|
|
567
|
+
onError(null, 'Invalid identity object', 'ClientError', onDone);
|
|
332
568
|
return;
|
|
333
569
|
}
|
|
334
570
|
|
|
335
571
|
if (!('type' in identity) || typeof (identity.type) != 'string' || identity.type.length <= 0) {
|
|
336
|
-
onError(null, "Identity must contain a valid 'type' field", 'ClientError');
|
|
572
|
+
onError(null, "Identity must contain a valid 'type' field", 'ClientError', onDone);
|
|
337
573
|
return;
|
|
338
574
|
}
|
|
339
575
|
|
|
@@ -348,6 +584,11 @@ export const dapUtils = {
|
|
|
348
584
|
apiParams.attributes = identity.attributes;
|
|
349
585
|
}
|
|
350
586
|
|
|
587
|
+
let entropyDict = JSON.parse(storage.getDataFromLocalStorage(DAP_CLIENT_ENTROPY));
|
|
588
|
+
if (entropyDict && entropyDict.entropy) {
|
|
589
|
+
apiParams.entropy = entropyDict.entropy;
|
|
590
|
+
}
|
|
591
|
+
|
|
351
592
|
let method;
|
|
352
593
|
let body;
|
|
353
594
|
let path;
|
|
@@ -359,10 +600,16 @@ export const dapUtils = {
|
|
|
359
600
|
body = JSON.stringify(apiParams);
|
|
360
601
|
break;
|
|
361
602
|
default:
|
|
362
|
-
onError(null, 'Invalid api_version: ' + config.api_version, 'ClientError');
|
|
603
|
+
onError(null, 'Invalid api_version: ' + config.api_version, 'ClientError', onDone);
|
|
363
604
|
return;
|
|
364
605
|
}
|
|
365
606
|
|
|
607
|
+
let customHeaders = {'Content-Type': 'application/json'};
|
|
608
|
+
let dapSSID = JSON.parse(storage.getDataFromLocalStorage(DAP_SS_ID));
|
|
609
|
+
if (dapSSID) {
|
|
610
|
+
customHeaders['Akamai-DAP-SS-ID'] = dapSSID;
|
|
611
|
+
}
|
|
612
|
+
|
|
366
613
|
let url = 'https://' + config.api_hostname + path;
|
|
367
614
|
let cb = {
|
|
368
615
|
success: (response, request) => {
|
|
@@ -373,19 +620,16 @@ export const dapUtils = {
|
|
|
373
620
|
token = request.getResponseHeader('Akamai-DAP-Token');
|
|
374
621
|
break;
|
|
375
622
|
}
|
|
376
|
-
onSuccess(token, request.status, request);
|
|
623
|
+
onSuccess(token, request.status, request, onDone);
|
|
377
624
|
},
|
|
378
625
|
error: (request, error) => {
|
|
379
|
-
onError(request, request.statusText, error);
|
|
626
|
+
onError(request, request.statusText, error, onDone);
|
|
380
627
|
}
|
|
381
628
|
};
|
|
382
629
|
|
|
383
630
|
ajax(url, cb, body, {
|
|
384
631
|
method: method,
|
|
385
|
-
customHeaders:
|
|
386
|
-
'Content-Type': 'application/json',
|
|
387
|
-
'Pragma': 'akamai-x-cache-on'
|
|
388
|
-
}
|
|
632
|
+
customHeaders: customHeaders
|
|
389
633
|
});
|
|
390
634
|
},
|
|
391
635
|
|
|
@@ -411,7 +655,7 @@ export const dapUtils = {
|
|
|
411
655
|
* api_hostname: 'api.dap.akadns.net',
|
|
412
656
|
* };
|
|
413
657
|
*
|
|
414
|
-
* // token from
|
|
658
|
+
* // token from dap_tokenize
|
|
415
659
|
*
|
|
416
660
|
* dapMembership( config, token,
|
|
417
661
|
* function( membership, status, xhr ) {
|
|
@@ -422,13 +666,13 @@ export const dapUtils = {
|
|
|
422
666
|
* } );
|
|
423
667
|
*
|
|
424
668
|
*/
|
|
425
|
-
dapMembership: function(config, token, onSuccess = null, onError = null) {
|
|
669
|
+
dapMembership: function(config, token, onDone, onSuccess = null, onError = null) {
|
|
426
670
|
if (onError == null) {
|
|
427
|
-
onError = function(xhr, status, error) {};
|
|
671
|
+
onError = function(xhr, status, error, onDone) {};
|
|
428
672
|
}
|
|
429
673
|
|
|
430
674
|
if (config == null || typeof (config) == typeof (undefined)) {
|
|
431
|
-
onError(null, 'Invalid config object', 'ClientError');
|
|
675
|
+
onError(null, 'Invalid config object', 'ClientError', onDone);
|
|
432
676
|
return;
|
|
433
677
|
}
|
|
434
678
|
|
|
@@ -437,32 +681,32 @@ export const dapUtils = {
|
|
|
437
681
|
}
|
|
438
682
|
|
|
439
683
|
if (typeof (config.api_version) != 'string') {
|
|
440
|
-
onError(null, "Invalid api_version: must be a string like 'x1', etc.", 'ClientError');
|
|
684
|
+
onError(null, "Invalid api_version: must be a string like 'x1', etc.", 'ClientError', onDone);
|
|
441
685
|
return;
|
|
442
686
|
}
|
|
443
687
|
|
|
444
688
|
if (!(('api_hostname') in config) || typeof (config.api_hostname) != 'string' || config.api_hostname.length == 0) {
|
|
445
|
-
onError(null, 'Invalid api_hostname: must be a non-empty string', 'ClientError');
|
|
689
|
+
onError(null, 'Invalid api_hostname: must be a non-empty string', 'ClientError', onDone);
|
|
446
690
|
return;
|
|
447
691
|
}
|
|
448
692
|
|
|
449
693
|
if (token == null || typeof (token) != 'string') {
|
|
450
|
-
onError(null, 'Invalid token: must be a non-null string', 'ClientError');
|
|
694
|
+
onError(null, 'Invalid token: must be a non-null string', 'ClientError', onDone);
|
|
451
695
|
return;
|
|
452
696
|
}
|
|
453
697
|
let path = '/data-activation/' +
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
698
|
+
config.api_version +
|
|
699
|
+
'/token/' + token +
|
|
700
|
+
'/membership';
|
|
457
701
|
|
|
458
702
|
let url = 'https://' + config.api_hostname + path;
|
|
459
703
|
|
|
460
704
|
let cb = {
|
|
461
705
|
success: (response, request) => {
|
|
462
|
-
onSuccess(JSON.parse(response), request.status, request);
|
|
706
|
+
onSuccess(JSON.parse(response), request.status, request, onDone);
|
|
463
707
|
},
|
|
464
708
|
error: (error, request) => {
|
|
465
|
-
onError(request, request.status, error);
|
|
709
|
+
onError(request, request.status, error, onDone);
|
|
466
710
|
}
|
|
467
711
|
};
|
|
468
712
|
|
|
@@ -470,5 +714,91 @@ export const dapUtils = {
|
|
|
470
714
|
method: 'GET',
|
|
471
715
|
customHeaders: {}
|
|
472
716
|
});
|
|
717
|
+
},
|
|
718
|
+
|
|
719
|
+
/**
|
|
720
|
+
* SYNOPSIS
|
|
721
|
+
*
|
|
722
|
+
* dapEncryptedMembership( config, token, onSuccess, onError );
|
|
723
|
+
*
|
|
724
|
+
* DESCRIPTION
|
|
725
|
+
*
|
|
726
|
+
* Return the audience segment membership along with a new Secure Advertising
|
|
727
|
+
* ID for this token in encrypted format.
|
|
728
|
+
*
|
|
729
|
+
* PARAMETERS
|
|
730
|
+
*
|
|
731
|
+
* config: an array of system configuration parameters
|
|
732
|
+
*
|
|
733
|
+
* token: the token previously returned from the tokenize API
|
|
734
|
+
*
|
|
735
|
+
* EXAMPLE
|
|
736
|
+
*
|
|
737
|
+
* config = {
|
|
738
|
+
* api_hostname: 'api.dap.akadns.net',
|
|
739
|
+
* };
|
|
740
|
+
*
|
|
741
|
+
* // token from dap_tokenize
|
|
742
|
+
*
|
|
743
|
+
* dapEncryptedMembership( config, token,
|
|
744
|
+
* function( membership, status, xhr ) {
|
|
745
|
+
* // Run auction with membership.segments and membership.said after decryption
|
|
746
|
+
* },
|
|
747
|
+
* function( xhr, status, error ) {
|
|
748
|
+
* // error
|
|
749
|
+
* } );
|
|
750
|
+
*
|
|
751
|
+
*/
|
|
752
|
+
dapEncryptedMembership: function(config, token, onDone, onSuccess = null, onError = null) {
|
|
753
|
+
if (onError == null) {
|
|
754
|
+
onError = function(xhr, status, error, onDone) {};
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
if (config == null || typeof (config) == typeof (undefined)) {
|
|
758
|
+
onError(null, 'Invalid config object', 'ClientError', onDone);
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
if (!('api_version' in config) || (typeof (config.api_version) == 'string' && config.api_version.length == 0)) {
|
|
763
|
+
config.api_version = 'x1';
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
if (typeof (config.api_version) != 'string') {
|
|
767
|
+
onError(null, "Invalid api_version: must be a string like 'x1', etc.", 'ClientError', onDone);
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
if (!(('api_hostname') in config) || typeof (config.api_hostname) != 'string' || config.api_hostname.length == 0) {
|
|
772
|
+
onError(null, 'Invalid api_hostname: must be a non-empty string', 'ClientError', onDone);
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
if (token == null || typeof (token) != 'string') {
|
|
777
|
+
onError(null, 'Invalid token: must be a non-null string', 'ClientError', onDone);
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
780
|
+
let path = '/data-activation/' +
|
|
781
|
+
config.api_version +
|
|
782
|
+
'/token/' + token +
|
|
783
|
+
'/membership/encrypt';
|
|
784
|
+
|
|
785
|
+
let url = 'https://' + config.api_hostname + path;
|
|
786
|
+
|
|
787
|
+
let cb = {
|
|
788
|
+
success: (response, request) => {
|
|
789
|
+
let encToken = request.getResponseHeader('Akamai-DAP-Token');
|
|
790
|
+
onSuccess(encToken, request.status, request, onDone);
|
|
791
|
+
},
|
|
792
|
+
error: (error, request) => {
|
|
793
|
+
onError(request, request.status, error, onDone);
|
|
794
|
+
}
|
|
795
|
+
};
|
|
796
|
+
ajax(url, cb, undefined, {
|
|
797
|
+
method: 'GET',
|
|
798
|
+
customHeaders: {
|
|
799
|
+
'Content-Type': 'application/json',
|
|
800
|
+
'Pragma': 'akamai-x-get-extracted-values'
|
|
801
|
+
}
|
|
802
|
+
});
|
|
473
803
|
}
|
|
474
804
|
}
|