Skip to content

Commit d1e86a7

Browse files
DimaIntentIQeyvazahmadzadadmytro-podLepetynskyiIntentiqEyvaz Ahmadzada
authored
IntentIq ID & Analytics Modules: Supports additional configuration parameters (prebid#13122)
* V 0 29 (prebid#31) * AGT-403: Add adType parameter to payload in report * AGT-403: Test for partner report, adType parameter * AGT-403: Test refactoring * AGT-403: Documentation updated * IntentIq Analytics Module: adUnitCode or placemetId to report (#9) * AGT-446: adUnitCode or placemetId to report * AGT-446: Description of changes, example * AGT-446: Fix documentation * AGT-446: Changes after review * Agt 409 full url in prebid modules (#8) * add sync * update full url * set url param * fix comment * fix issue fix sync mode * update url * update full url * add test * move browser_blacklist (#10) * add is optedOut (#11) * update date in FPD after sync (#12) * update sync logic for new user (#13) * fix unit tests * change version name * IntentIq ID: Support sourceMetaData and sourceMetaDataExternal (#17) * AGT-453: Support sourceMetaData * AGT-453: sourceMetaDataExternal * AGT-453: Documentation * AGT-453: Changes after review * AGT-453: Fix doc * Fix doc * AGT-453: Fix test * update test * update endpoint (#16) * update endpoint * update test * add tests * update test * fix conflict * fix conflict * add test for reportingServerAddress * add test for reportingServerAddress * AGT-498: support report method parameter (#22) * AGT-498: reportMethod * AGT-498: Tests and refactoring * AGT-498: method refactoring * AGT-498: get method refactoring * AGT-498: reportMethod parameter description (#23) * AGT-498: reportMethod * AGT-498: Tests and refactoring * AGT-498: method refactoring * AGT-498: get method refactoring * AGT-498: Documentation * Agt 452 server call counters (#18) * add counters * add unit tests and fixes * counters additions * clear counters when a request is made --------- Co-authored-by: Eyvaz Ahmadzada <[email protected]> * add siloEnabled feature (#19) * add siloEnabled feature * add siloEnabled feature to analytics adapter * add unit tests for siloEnabled feature * add siloenabled to docs --------- Co-authored-by: Eyvaz Ahmadzada <[email protected]> * fix unit test issues * AGT-455: Source parameter in requests (prebid#28) * AGT-508: Spd parameter (prebid#29) * AGT-508: Spd parameter * AGT-508: Move appendSpd to utils * AGT-499: Support partnerClientIdType and partnerClientId (prebid#30) * AGT-499: partnerClientId and partnerClientIdType in requests * AGT-499: Clean comment * AGT-499: Refactoring * add groupchanged parameter (prebid#25) * add groupchanged parameter * fix md file issue * add groupChanged example in docs * remove group from example * add unit tests and fix groupChanged issue --------- Co-authored-by: Eyvaz Ahmadzada <[email protected]> Co-authored-by: DimaIntentIQ <[email protected]> * Agt 501 support additional params (#24) * additionalParams feature init * additional params add features * additionalparams fix analytics adapter * add unit tests for additionalParams * fix currentBrowser issue --------- Co-authored-by: Eyvaz Ahmadzada <[email protected]> Co-authored-by: DimaIntentIQ <[email protected]> * fix linter error --------- Co-authored-by: dmytro-po <[email protected]> Co-authored-by: DimaIntentIQ <[email protected]> Co-authored-by: dLepetynskyiIntentiq <[email protected]> Co-authored-by: DimaIntentIQ <[email protected]> Co-authored-by: Eyvaz Ahmadzada <[email protected]> * fix unit tests (prebid#32) Co-authored-by: Eyvaz Ahmadzada <[email protected]> * Agt 547 vr bug for module (prebid#33) * save progress * fix calling server * add "dbsaved" parameter * add tests * AGT-552: Additional query params (prebid#34) * AGT-552: Additional query params * update documentation --------- Co-authored-by: DimaIntentIQ <[email protected]> * Fix unit test for specific browser * fix spelling --------- Co-authored-by: Eyvaz <[email protected]> Co-authored-by: dmytro-po <[email protected]> Co-authored-by: dLepetynskyiIntentiq <[email protected]> Co-authored-by: Eyvaz Ahmadzada <[email protected]>
1 parent b927a87 commit d1e86a7

File tree

10 files changed

+1131
-128
lines changed

10 files changed

+1131
-128
lines changed

libraries/intentIqConstants/intentIqConstants.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,12 @@ export const BLACK_LIST = 'L';
99
export const CLIENT_HINTS_KEY = '_iiq_ch';
1010
export const EMPTY = 'EMPTY';
1111
export const GVLID = '1323';
12-
export const VERSION = 0.28;
12+
export const VERSION = 0.29;
13+
export const PREBID = 'pbjs';
14+
export const HOURS_24 = 86400000;
1315

14-
export const VR_ENDPOINT = 'https://api.intentiq.com';
15-
export const GDPR_ENDPOINT = 'https://api-gdpr.intentiq.com';
1616
export const INVALID_ID = 'INVALID_ID';
1717

18-
export const SYNC_ENDPOINT = 'https://sync.intentiq.com'
19-
export const GDPR_SYNC_ENDPOINT = 'https://sync-gdpr.intentiq.com'
2018
export const SCREEN_PARAMS = {
2119
0: 'windowInnerHeight',
2220
1: 'windowInnerWidth',
@@ -27,3 +25,14 @@ export const SCREEN_PARAMS = {
2725
};
2826

2927
export const SYNC_REFRESH_MILL = 3600000;
28+
export const META_DATA_CONSTANT = 256;
29+
30+
export const MAX_REQUEST_LENGTH = {
31+
// https://www.geeksforgeeks.org/maximum-length-of-a-url-in-different-browsers/
32+
chrome: 2097152,
33+
safari: 80000,
34+
opera: 2097152,
35+
edge: 2048,
36+
firefox: 65536,
37+
ie: 2048
38+
};
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { MAX_REQUEST_LENGTH } from "../intentIqConstants/intentIqConstants.js";
2+
3+
/**
4+
* Appends additional parameters to a URL if they are valid and applicable for the given request destination.
5+
*
6+
* @param {string} browser - The name of the current browser; used to look up the maximum URL length.
7+
* @param {string} url - The base URL to which additional parameters may be appended.
8+
* @param {(string|number)} requestTo - The destination identifier; used as an index to check if a parameter applies.
9+
* @param {Array<Object>} additionalParams - An array of parameter objects to append.
10+
* Each parameter object should have the following properties:
11+
* - `parameterName` {string}: The name of the parameter.
12+
* - `parameterValue` {*}: The value of the parameter.
13+
* - `destination` {Object|Array}: An object or array indicating the applicable destinations. Sync = 0, VR = 1, reporting = 2
14+
*
15+
* @return {string} The resulting URL with additional parameters appended if valid; otherwise, the original URL.
16+
*/
17+
export function handleAdditionalParams(browser, url, requestTo, additionalParams) {
18+
let queryString = '';
19+
20+
if (!Array.isArray(additionalParams)) return url;
21+
22+
for (let i = 0; i < additionalParams.length; i++) {
23+
const param = additionalParams[i];
24+
25+
if (
26+
typeof param !== 'object' ||
27+
!param.parameterName ||
28+
!param.parameterValue ||
29+
!param.destination ||
30+
!Array.isArray(param.destination)
31+
) {
32+
continue;
33+
}
34+
35+
if (param.destination[requestTo]) {
36+
queryString += `&agp_${encodeURIComponent(param.parameterName)}=${param.parameterValue}`;
37+
}
38+
}
39+
40+
const maxLength = MAX_REQUEST_LENGTH[browser] ?? 2048;
41+
if ((url.length + queryString.length) > maxLength) return url;
42+
43+
return url + queryString;
44+
}

libraries/intentIqUtils/intentIqConfig.js

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libraries/intentIqUtils/storageUtils.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,16 @@ export function defineStorageType(params) {
8787
const filteredArr = params.filter(item => SUPPORTED_TYPES.includes(item));
8888
return filteredArr.length ? filteredArr : ['html5'];
8989
}
90+
91+
/**
92+
* Parse json if possible, else return null
93+
* @param data
94+
*/
95+
export function tryParse(data) {
96+
try {
97+
return JSON.parse(data);
98+
} catch (err) {
99+
logError(err);
100+
return null;
101+
}
102+
}

libraries/intentIqUtils/urlUtils.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export function appendSPData (url, firstPartyData) {
2+
const spdParam = firstPartyData?.spd ? encodeURIComponent(typeof firstPartyData.spd === 'object' ? JSON.stringify(firstPartyData.spd) : firstPartyData.spd) : '';
3+
url += spdParam ? '&spd=' + spdParam : '';
4+
return url
5+
};

modules/intentIqAnalyticsAdapter.js

Lines changed: 67 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,16 @@ import {config} from '../src/config.js';
77
import {EVENTS} from '../src/constants.js';
88
import {MODULE_TYPE_ANALYTICS} from '../src/activities/modules.js';
99
import {detectBrowser} from '../libraries/intentIqUtils/detectBrowserUtils.js';
10+
import {appendSPData} from '../libraries/intentIqUtils/urlUtils.js';
1011
import {appendVrrefAndFui, getReferrer} from '../libraries/intentIqUtils/getRefferer.js';
1112
import {getCmpData} from '../libraries/intentIqUtils/getCmpData.js'
12-
import {CLIENT_HINTS_KEY, FIRST_PARTY_KEY, VERSION} from '../libraries/intentIqConstants/intentIqConstants.js';
13+
import {CLIENT_HINTS_KEY, FIRST_PARTY_KEY, VERSION, PREBID} from '../libraries/intentIqConstants/intentIqConstants.js';
1314
import {readData, defineStorageType} from '../libraries/intentIqUtils/storageUtils.js';
15+
import {reportingServerAddress} from '../libraries/intentIqUtils/intentIqConfig.js';
16+
import { handleAdditionalParams } from '../libraries/intentIqUtils/handleAdditionalParams.js';
1417

1518
const MODULE_NAME = 'iiqAnalytics'
1619
const analyticsType = 'endpoint';
17-
const REPORT_ENDPOINT = 'https://reports.intentiq.com/report';
18-
const REPORT_ENDPOINT_GDPR = 'https://reports-gdpr.intentiq.com/report';
1920
const storage = getStorageManager({moduleType: MODULE_TYPE_ANALYTICS, moduleName: MODULE_NAME});
2021
const prebidVersion = '$prebid.version$';
2122
export const REPORTER_ID = Date.now() + '_' + getRandom(0, 1000);
@@ -59,7 +60,21 @@ const PARAMS_NAMES = {
5960
adType: 'adType'
6061
};
6162

62-
let iiqAnalyticsAnalyticsAdapter = Object.assign(adapter({defaultUrl: REPORT_ENDPOINT, analyticsType}), {
63+
function getIntentIqConfig() {
64+
return config.getConfig('userSync.userIds')?.find(m => m.name === 'intentIqId');
65+
}
66+
67+
const DEFAULT_URL = 'https://reports.intentiq.com/report'
68+
69+
const getDataForDefineURL = () => {
70+
const iiqConfig = getIntentIqConfig()
71+
const cmpData = getCmpData();
72+
const gdprDetected = cmpData.gdprString;
73+
74+
return [iiqConfig, gdprDetected]
75+
}
76+
77+
let iiqAnalyticsAnalyticsAdapter = Object.assign(adapter({url: DEFAULT_URL, analyticsType}), {
6378
initOptions: {
6479
lsValueInitialized: false,
6580
partner: null,
@@ -69,7 +84,10 @@ let iiqAnalyticsAnalyticsAdapter = Object.assign(adapter({defaultUrl: REPORT_END
6984
eidl: null,
7085
lsIdsInitialized: false,
7186
manualWinReportEnabled: false,
72-
domainName: null
87+
domainName: null,
88+
siloEnabled: false,
89+
reportMethod: null,
90+
additionalParams: null
7391
},
7492
track({eventType, args}) {
7593
switch (eventType) {
@@ -91,11 +109,7 @@ const {
91109
BID_REQUESTED
92110
} = EVENTS;
93111

94-
function getIntentIqConfig() {
95-
return config.getConfig('userSync.userIds')?.find(m => m.name === 'intentIqId');
96-
}
97-
98-
function initLsValues() {
112+
function initAdapterConfig() {
99113
if (iiqAnalyticsAnalyticsAdapter.initOptions.lsValueInitialized) return;
100114
let iiqConfig = getIntentIqConfig()
101115

@@ -108,16 +122,24 @@ function initLsValues() {
108122
typeof iiqConfig.params?.browserBlackList === 'string' ? iiqConfig.params.browserBlackList.toLowerCase() : '';
109123
iiqAnalyticsAnalyticsAdapter.initOptions.manualWinReportEnabled = iiqConfig.params?.manualWinReportEnabled || false;
110124
iiqAnalyticsAnalyticsAdapter.initOptions.domainName = iiqConfig.params?.domainName || '';
125+
iiqAnalyticsAnalyticsAdapter.initOptions.siloEnabled =
126+
typeof iiqConfig.params?.siloEnabled === 'boolean' ? iiqConfig.params.siloEnabled : false;
127+
iiqAnalyticsAnalyticsAdapter.initOptions.reportMethod = parseReportingMethod(iiqConfig.params?.reportMethod);
128+
iiqAnalyticsAnalyticsAdapter.initOptions.additionalParams = iiqConfig.params?.additionalParams || null;
111129
} else {
112130
iiqAnalyticsAnalyticsAdapter.initOptions.lsValueInitialized = false;
113131
iiqAnalyticsAnalyticsAdapter.initOptions.partner = -1;
132+
iiqAnalyticsAnalyticsAdapter.initOptions.reportMethod = 'GET';
114133
}
115134
}
116135

117136
function initReadLsIds() {
118137
try {
119138
iiqAnalyticsAnalyticsAdapter.initOptions.dataInLs = null;
120-
iiqAnalyticsAnalyticsAdapter.initOptions.fpid = JSON.parse(readData(FIRST_PARTY_KEY, allowedStorage, storage));
139+
iiqAnalyticsAnalyticsAdapter.initOptions.fpid = JSON.parse(readData(
140+
`${FIRST_PARTY_KEY}${iiqAnalyticsAnalyticsAdapter.initOptions.siloEnabled ? '_p_' + iiqAnalyticsAnalyticsAdapter.initOptions.partner : ''}`,
141+
allowedStorage, storage
142+
));
121143
if (iiqAnalyticsAnalyticsAdapter.initOptions.fpid) {
122144
iiqAnalyticsAnalyticsAdapter.initOptions.currentGroup = iiqAnalyticsAnalyticsAdapter.initOptions.fpid.group;
123145
}
@@ -144,7 +166,7 @@ function initReadLsIds() {
144166

145167
function bidWon(args, isReportExternal) {
146168
if (!iiqAnalyticsAnalyticsAdapter.initOptions.lsValueInitialized) {
147-
initLsValues();
169+
initAdapterConfig();
148170
}
149171

150172
if (isNaN(iiqAnalyticsAnalyticsAdapter.initOptions.partner) || iiqAnalyticsAnalyticsAdapter.initOptions.partner == -1) return;
@@ -159,13 +181,32 @@ function bidWon(args, isReportExternal) {
159181
initReadLsIds();
160182
}
161183
if ((isReportExternal && iiqAnalyticsAnalyticsAdapter.initOptions.manualWinReportEnabled) || (!isReportExternal && !iiqAnalyticsAnalyticsAdapter.initOptions.manualWinReportEnabled)) {
162-
ajax(constructFullUrl(preparePayload(args, true)), undefined, null, {method: 'GET'});
163-
logInfo('IIQ ANALYTICS -> BID WON')
184+
const { url, method, payload } = constructFullUrl(preparePayload(args, true));
185+
if (method === 'POST') {
186+
ajax(url, undefined, payload, {method, contentType: 'application/x-www-form-urlencoded'});
187+
} else {
188+
ajax(url, undefined, null, {method});
189+
}
190+
logInfo('IIQ ANALYTICS -> BID WON');
164191
return true;
165192
}
166193
return false;
167194
}
168195

196+
function parseReportingMethod(reportMethod) {
197+
if (typeof reportMethod === 'string') {
198+
switch (reportMethod.toUpperCase()) {
199+
case 'GET':
200+
return 'GET';
201+
case 'POST':
202+
return 'POST';
203+
default:
204+
return 'GET';
205+
}
206+
}
207+
return 'GET';
208+
}
209+
169210
function defineGlobalVariableName() {
170211
function reportExternalWin(args) {
171212
return bidWon(args, true);
@@ -302,30 +343,36 @@ function getDefaultDataObject() {
302343

303344
function constructFullUrl(data) {
304345
let report = [];
346+
const reportMethod = iiqAnalyticsAnalyticsAdapter.initOptions.reportMethod;
347+
const currentBrowserLowerCase = detectBrowser();
305348
data = btoa(JSON.stringify(data));
306349
report.push(data);
307350

308351
const cmpData = getCmpData();
309-
const gdprDetected = cmpData.gdprString;
310-
const baseUrl = gdprDetected ? REPORT_ENDPOINT_GDPR : REPORT_ENDPOINT;
352+
const baseUrl = reportingServerAddress(...getDataForDefineURL());
311353

312354
let url = baseUrl + '?pid=' + iiqAnalyticsAnalyticsAdapter.initOptions.partner +
313355
'&mct=1' +
314356
((iiqAnalyticsAnalyticsAdapter.initOptions?.fpid)
315357
? '&iiqid=' + encodeURIComponent(iiqAnalyticsAnalyticsAdapter.initOptions.fpid.pcid) : '') +
316358
'&agid=' + REPORTER_ID +
317359
'&jsver=' + VERSION +
318-
'&source=pbjs' +
319-
'&payload=' + JSON.stringify(report) +
360+
'&source=' + PREBID +
320361
'&uh=' + encodeURIComponent(iiqAnalyticsAnalyticsAdapter.initOptions.clientsHints) +
321362
(cmpData.uspString ? '&us_privacy=' + encodeURIComponent(cmpData.uspString) : '') +
322363
(cmpData.gppString ? '&gpp=' + encodeURIComponent(cmpData.gppString) : '') +
323364
(cmpData.gdprString
324365
? '&gdpr_consent=' + encodeURIComponent(cmpData.gdprString) + '&gdpr=1'
325366
: '&gdpr=0');
326-
367+
url = appendSPData(url, iiqAnalyticsAnalyticsAdapter.initOptions.fpid)
327368
url = appendVrrefAndFui(url, iiqAnalyticsAnalyticsAdapter.initOptions.domainName);
328-
return url;
369+
370+
if (reportMethod === 'POST') {
371+
return { url, method: 'POST', payload: JSON.stringify(report) };
372+
}
373+
url += '&payload=' + encodeURIComponent(JSON.stringify(report));
374+
url = handleAdditionalParams(currentBrowserLowerCase, url, 2, iiqAnalyticsAnalyticsAdapter.initOptions.additionalParams);
375+
return { url, method: 'GET' };
329376
}
330377

331378
iiqAnalyticsAnalyticsAdapter.originEnableAnalytics = iiqAnalyticsAnalyticsAdapter.enableAnalytics;

0 commit comments

Comments
 (0)