modules/fintezaAnalyticsAdapter.js
import { parseUrl, logError } from '../src/utils.js';
import { ajax } from '../src/ajax.js';
import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js';
import adapterManager from '../src/adapterManager.js';
import {getStorageManager} from '../src/storageManager.js';
import { EVENTS } from '../src/constants.js';
import {MODULE_TYPE_ANALYTICS} from '../src/activities/modules.js';
const MODULE_CODE = 'finteza';
const storage = getStorageManager({moduleType: MODULE_TYPE_ANALYTICS, moduleName: MODULE_CODE});
const ANALYTICS_TYPE = 'endpoint';
const FINTEZA_HOST = 'https://content.mql5.com/tr';
const BID_REQUEST_TRACK = 'Bid Request %BIDDER%';
const BID_RESPONSE_PRICE_TRACK = 'Bid Response Price %BIDDER%';
const BID_RESPONSE_TIME_TRACK = 'Bid Response Time %BIDDER%';
const BID_TIMEOUT_TRACK = 'Bid Timeout %BIDDER%';
const BID_WON_TRACK = 'Bid Won %BIDDER%';
const FIRST_VISIT_DATE = '_fz_fvdt';
const SESSION_ID = '_fz_ssn';
const SESSION_DURATION = 30 * 60 * 1000;
const SESSION_RAND_PART = 9;
const TRACK_TIME_KEY = '_fz_tr';
const UNIQ_ID_KEY = '_fz_uniq';
function getPageInfo() {
const pageInfo = {
domain: window.location.hostname,
}
if (document.referrer) {
pageInfo.referrerDomain = parseUrl(document.referrer).hostname;
}
return pageInfo;
}
function getUniqId() {
let isUniqFromLS;
let uniq = storage.getCookie(UNIQ_ID_KEY);
if (!uniq) {
try {
if (storage.hasLocalStorage()) {
uniq = storage.getDataFromLocalStorage(UNIQ_ID_KEY) || '';
isUniqFromLS = true;
}
} catch (b) {}
}
if (uniq && isNaN(uniq)) {
uniq = null;
}
if (uniq && isUniqFromLS) {
let expires = new Date();
expires.setFullYear(expires.getFullYear() + 10);
try {
storage.setCookie(UNIQ_ID_KEY, uniq, expires.toUTCString());
} catch (e) {}
}
return uniq;
}
function initFirstVisit() {
let now;
let visitDate;
let cookies;
try {
// TODO: commented out because of rule violations
cookies = {} // parseCookies(document.cookie);
} catch (a) {
cookies = {};
}
visitDate = cookies[ FIRST_VISIT_DATE ];
if (!visitDate) {
now = new Date();
visitDate = parseInt(now.getTime() / 1000, 10);
now.setFullYear(now.getFullYear() + 20);
try {
storage.setCookie(FIRST_VISIT_DATE, visitDate, now.toUTCString());
} catch (e) {}
}
return visitDate;
}
// TODO: commented out because of rule violations
/*
function trim(string) {
if (string.trim) {
return string.trim();
}
return string.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
}
function parseCookies(cookie) {
let values = {};
let arr, item;
let param, value;
let i, j;
if (!cookie || !storage.cookiesAreEnabled()) {
return {};
}
arr = cookie.split(';');
for (i = 0, j = arr.length; i < j; i++) {
item = arr[ i ];
if (!item) {
continue;
}
param = item.split('=');
if (param.length <= 1) {
continue;
}
value = decodeURIComponent(param[0]);
value = trim(value);
values[value] = decodeURIComponent(param[1]);
}
return values;
}
*/
function getRandAsStr(digits) {
let str = '';
let rand = 0;
let i;
digits = digits || 4;
for (i = 0; i < digits; i++) {
rand = (Math.random() * 10) >>> 0;
str += '' + rand;
}
return str;
}
function getSessionBegin(session) {
if (!session || (typeof session !== 'string')) {
return 0;
}
const len = session.length;
if (len && len <= SESSION_RAND_PART) {
return 0;
}
const timestamp = session.substring(0, len - SESSION_RAND_PART);
return parseInt(timestamp, 10);
}
function initSession() {
const now = new Date();
const expires = new Date(now.getTime() + SESSION_DURATION);
const timestamp = Math.floor(now.getTime() / 1000);
let begin = 0;
let cookies;
let sessionId;
let sessionDuration;
let isNew = false;
try {
// TODO: commented out because of rule violations
cookies = {} // parseCookies(document.cookie);
} catch (a) {
cookies = {};
}
sessionId = cookies[ SESSION_ID ];
if (!sessionId ||
!checkSessionByExpires() ||
!checkSessionByReferer() ||
!checkSessionByDay()) {
sessionId = '' + timestamp + getRandAsStr(SESSION_RAND_PART); // lgtm [js/insecure-randomness]
begin = timestamp;
isNew = true;
} else {
begin = getSessionBegin(sessionId);
}
if (begin > 0) {
sessionDuration = Math.floor(timestamp - begin);
} else {
sessionDuration = -1;
}
try {
storage.setCookie(SESSION_ID, sessionId, expires.toUTCString());
} catch (e) {}
return {
isNew: isNew,
id: sessionId,
duration: sessionDuration
};
}
function checkSessionByExpires() {
const timestamp = getTrackRequestLastTime();
const now = new Date().getTime();
if (now > timestamp + SESSION_DURATION) {
return false;
}
return true;
}
function checkSessionByReferer() {
const referrer = fntzAnalyticsAdapter.context.pageInfo.referrerDomain;
const domain = fntzAnalyticsAdapter.context.pageInfo.domain;
return referrer === '' || domain === referrer;
}
function checkSessionByDay() {
let last = getTrackRequestLastTime();
if (last) {
last = new Date(last);
const now = new Date();
return last.getUTCDate() === now.getUTCDate() &&
last.getUTCMonth() === now.getUTCMonth() &&
last.getUTCFullYear() === now.getUTCFullYear();
}
return false;
}
function saveTrackRequestTime() {
const now = new Date().getTime();
const expires = new Date(now + SESSION_DURATION);
try {
if (storage.hasLocalStorage()) {
storage.setDataInLocalStorage(TRACK_TIME_KEY, now.toString());
} else {
storage.setCookie(TRACK_TIME_KEY, now.toString(), expires.toUTCString());
}
} catch (a) {}
}
function getTrackRequestLastTime() {
let cookie;
try {
if (storage.hasLocalStorage()) {
return parseInt(
storage.getDataFromLocalStorage(TRACK_TIME_KEY) || 0,
10,
);
}
// TODO: commented out because of rule violations
cookie = {} // parseCookies(document.cookie);
cookie = cookie[ TRACK_TIME_KEY ];
if (cookie) {
return parseInt(cookie, 10);
}
} catch (e) {}
return 0;
}
function getAntiCacheParam() {
const date = new Date();
const rand = (Math.random() * 99999 + 1) >>> 0;
return ([ date.getTime(), rand ].join(''));
}
function replaceBidder(str, bidder) {
let _str = str;
_str = _str.replace(/\%bidder\%/, bidder.toLowerCase());
_str = _str.replace(/\%BIDDER\%/, bidder.toUpperCase());
_str = _str.replace(/\%Bidder\%/, bidder.charAt(0).toUpperCase() + bidder.slice(1).toLowerCase());
return _str;
}
function prepareBidRequestedParams(args) {
return [{
event: encodeURIComponent(replaceBidder(fntzAnalyticsAdapter.context.bidRequestTrack, args.bidderCode)),
ref: encodeURIComponent(window.location.href),
}];
}
function prepareBidResponseParams(args) {
return [{
event: encodeURIComponent(replaceBidder(fntzAnalyticsAdapter.context.bidResponsePriceTrack, args.bidderCode)),
value: args.cpm,
unit: 'usd'
}, {
event: encodeURIComponent(replaceBidder(fntzAnalyticsAdapter.context.bidResponseTimeTrack, args.bidderCode)),
value: args.timeToRespond,
unit: 'ms'
}];
}
function prepareBidWonParams(args) {
return [{
event: encodeURIComponent(replaceBidder(fntzAnalyticsAdapter.context.bidWonTrack, args.bidderCode)),
value: args.cpm,
unit: 'usd'
}];
}
function prepareBidTimeoutParams(args) {
return args.map(function(bid) {
return {
event: encodeURIComponent(replaceBidder(fntzAnalyticsAdapter.context.bidTimeoutTrack, bid.bidder)),
value: bid.timeout,
unit: 'ms'
};
})
}
function prepareTrackData(evtype, args) {
let prepareParams = null;
switch (evtype) {
case EVENTS.BID_REQUESTED:
prepareParams = prepareBidRequestedParams;
break;
case EVENTS.BID_RESPONSE:
prepareParams = prepareBidResponseParams;
break;
case EVENTS.BID_WON:
prepareParams = prepareBidWonParams;
break;
case EVENTS.BID_TIMEOUT:
prepareParams = prepareBidTimeoutParams;
break;
}
if (!prepareParams) { return null; }
const data = prepareParams(args);
if (!data) { return null; }
const session = initSession();
return data.map(d => {
const trackData = Object.assign(d, {
id: fntzAnalyticsAdapter.context.id,
ref: encodeURIComponent(window.location.href),
title: encodeURIComponent(document.title),
scr_res: fntzAnalyticsAdapter.context.screenResolution,
fv_date: fntzAnalyticsAdapter.context.firstVisit,
ac: getAntiCacheParam(),
})
if (fntzAnalyticsAdapter.context.uniqId) {
trackData.fz_uniq = fntzAnalyticsAdapter.context.uniqId;
}
if (session.id) {
trackData.ssn = session.id;
}
if (session.isNew) {
session.isNew = false;
trackData.ssn_start = 1;
}
trackData.ssn_dr = session.duration;
return trackData;
});
}
function sendTrackRequest(trackData) {
try {
ajax(
fntzAnalyticsAdapter.context.host,
null,
trackData,
{
method: 'GET',
withCredentials: true,
contentType: 'application/x-www-form-urlencoded'
},
);
saveTrackRequestTime();
} catch (err) {
logError('Error on send data: ', err);
}
}
const fntzAnalyticsAdapter = Object.assign(
adapter({
FINTEZA_HOST,
ANALYTICS_TYPE
}),
{
track({ eventType, args }) {
if (typeof args !== 'undefined') {
const trackData = prepareTrackData(eventType, args);
if (!trackData) { return; }
trackData.forEach(sendTrackRequest);
}
}
}
);
fntzAnalyticsAdapter.originEnableAnalytics = fntzAnalyticsAdapter.enableAnalytics;
fntzAnalyticsAdapter.enableAnalytics = function (config) {
if (!config.options.id) {
logError('Client ID (id) option is not defined. Analytics won\'t work');
return;
}
fntzAnalyticsAdapter.context = {
host: config.options.host || FINTEZA_HOST,
id: config.options.id,
bidRequestTrack: config.options.bidRequestTrack || BID_REQUEST_TRACK,
bidResponsePriceTrack: config.options.bidResponsePriceTrack || BID_RESPONSE_PRICE_TRACK,
bidResponseTimeTrack: config.options.bidResponseTimeTrack || BID_RESPONSE_TIME_TRACK,
bidTimeoutTrack: config.options.bidTimeoutTrack || BID_TIMEOUT_TRACK,
bidWonTrack: config.options.bidWonTrack || BID_WON_TRACK,
firstVisit: initFirstVisit(),
screenResolution: `${window.screen.width}x${window.screen.height}`,
uniqId: getUniqId(),
pageInfo: getPageInfo(),
};
fntzAnalyticsAdapter.originEnableAnalytics(config);
};
adapterManager.registerAnalyticsAdapter({
adapter: fntzAnalyticsAdapter,
code: MODULE_CODE,
});
export default fntzAnalyticsAdapter;