File "burst.js"
Full path: /home/satkhirabarta/public_html/wp-content/plugins/burst-statistics/assets/js/src/burst.js
File
size: 12.24 B (12.24 KB bytes)
MIME-type: text/plain
Charset: utf-8
Download Open Edit Advanced Editor &nnbsp; Back
// TimeMe.js should be loaded and running to track time as soon as it is loaded.
let burst_track_hit_running = false;
let burst_initial_track_hit = false;
let burst_cookieless_option = burst.options.enable_cookieless_tracking; // User cookieless option
// add option to window so a consent plugin can change this value
window.burst_enable_cookieless_tracking = burst.options.enable_cookieless_tracking; // Consent plugin cookieless option
let burst_page_url = window.location.href;
let burst_completed_goals = [];
let burst_goals_script_url = burst.goals_script_url ? burst.goals_script_url : './burst-goals.js';
/**
* Setup Goals if they exist for current page
* @returns {Promise<void>}
*/
const burst_import_goals = async() => {
const goals = await import( burst_goals_script_url );
goals.default();
};
// If has goals and a goal has this page_url, import
if ( 0 < burst.goals.length ) {
for ( let i = 0; i < burst.goals.length; i++ ) {
if ( '' !== burst.goals[i].page_url || burst.goals[i].page_url === burst_page_url ) {
burst_import_goals();
break;
}
}
}
/**
* Get a cookie by name
* @param name
* @returns {Promise}
*/
let burst_get_cookie = ( name ) => {
return new Promise( ( resolve, reject ) => {
name = name + '='; //Create the cookie name variable with cookie name concatenate with = sign
let cArr = window.document.cookie.split( ';' ); //Create cookie array by split the cookie by ';'
//Loop through the cookies and return the cookie value if we find the cookie name
for ( let i = 0; i < cArr.length; i++ ) {
let c = cArr[i].trim();
//If the name is the cookie string at position 0, we found the cookie and return the cookie value
if ( 0 === c.indexOf( name ) ) {
resolve( c.substring( name.length, c.length ) );
}
}
reject( false );
});
};
/**
* Set a cookie
* @param name
* @param value
*/
let burst_set_cookie = ( name, value ) => {
let cookiePath = '/';
let domain = '';
let secure = ';secure';
let date = new Date();
let days = burst.cookie_retention_days;
date.setTime( date.getTime() + ( days * 24 * 60 * 60 * 1000 ) );
let expires = ';expires=' + date.toGMTString();
if ( 'https:' !== window.location.protocol ) {
secure = '';
}
//if we want to dynamically be able to change the domain, we can use this.
if ( 0 < domain.length ) {
domain = ';domain=' + domain;
}
document.cookie = name + '=' + value + ';SameSite=Strict' + secure + expires + domain + ';path=' + cookiePath;
};
/**
* Should we use cookies for tracking
* @returns {boolean}
*/
let burst_use_cookies = () => {
if ( ! navigator.cookieEnabled ) {
return false;
} // cookies blocked by browser
if ( burst_cookieless_option && window.burst_enable_cookieless_tracking ) {
return false;
} // cookieless is enabled by user or consent plugin
return true; // cookies are enabled
};
/**
* Enable or disable cookies
* @returns {boolean}
*/
function burst_enable_cookies() {
window.burst_enable_cookieless_tracking = 0;
if ( burst_use_cookies() ) {
burst_uid().then( obj => {
burst_set_cookie( 'burst_uid', obj.uid ); // set uid cookie
});
}
}
/**
* Get or set the user identifier
* @returns {Promise}
*/
const burst_uid = () => {
return new Promise( ( resolve ) => {
burst_get_cookie( 'burst_uid' ).then( cookie_uid => {
resolve( cookie_uid );
}).catch( () => {
// if no cookie, generate a uid and set it
let uid = burst_generate_uid();
burst_set_cookie( 'burst_uid', uid );
resolve( uid );
});
});
};
/**
* Generate a random string
* @returns {string}
*/
let burst_generate_uid = () => {
let uid = '';
for ( let i = 0; 32 > i; i++ ) {
uid += Math.floor( Math.random() * 16 ).toString( 16 );
}
return uid;
};
/**
* Generate a fingerprint
* @returns {Promise}
*/
const burst_fingerprint = () => {
return new Promise( ( resolve, reject ) => {
let browserTests = [
'availableScreenResolution',
'canvas',
'colorDepth',
'cookies',
'cpuClass',
'deviceDpi',
'doNotTrack',
'indexedDb',
'language',
'localStorage',
'pixelRatio',
'platform',
'plugins',
'processorCores',
'screenResolution',
'sessionStorage',
'timezoneOffset',
'touchSupport',
'userAgent',
'webGl'
];
imprint.test( browserTests ).then( function( fingerprint ) {
resolve( fingerprint );
}).catch( ( error ) => {
reject( error );
});
});
};
let burst_get_time_on_page = () => {
return new Promise( ( resolve ) => {
// wait for timeMe.js to be loaded
if ( 'undefined' === typeof TimeMe ) {
resolve( 0 ); // return 0 if timeMe.js is not (yet) loaded
}
let current_time_on_page = TimeMe.getTimeOnCurrentPageInMilliseconds();
// reset time on page
TimeMe.resetAllRecordedPageTimes();
TimeMe.initialize({
idleTimeoutInSeconds: 30 // seconds
});
resolve( current_time_on_page );
});
};
/**
* Check if this is a user agent
* @returns {boolean}
*/
let burst_is_user_agent = () => {
const botPattern = '(googlebot\/|bot|Googlebot-Mobile|Googlebot-Image|Google favicon|Mediapartners-Google|bingbot|slurp|java|wget|curl|Commons-HttpClient|Python-urllib|libwww|httpunit|nutch|phpcrawl|msnbot|jyxobot|FAST-WebCrawler|FAST Enterprise Crawler|biglotron|teoma|convera|seekbot|gigablast|exabot|ngbot|ia_archiver|GingerCrawler|webmon |httrack|webcrawler|grub.org|UsineNouvelleCrawler|antibot|netresearchserver|speedy|fluffy|bibnum.bnf|findlink|msrbot|panscient|yacybot|AISearchBot|IOI|ips-agent|tagoobot|MJ12bot|dotbot|woriobot|yanga|buzzbot|mlbot|yandexbot|purebot|Linguee Bot|Voyager|CyberPatrol|voilabot|baiduspider|citeseerxbot|spbot|twengabot|postrank|turnitinbot|scribdbot|page2rss|sitebot|linkdex|Adidxbot|blekkobot|ezooms|dotbot|Mail.RU_Bot|discobot|heritrix|findthatfile|europarchive.org|NerdByNature.Bot|sistrix crawler|ahrefsbot|Aboundex|domaincrawler|wbsearchbot|summify|ccbot|edisterbot|seznambot|ec2linkfinder|gslfbot|aihitbot|intelium_bot|facebookexternalhit|yeti|RetrevoPageAnalyzer|lb-spider|sogou|lssbot|careerbot|wotbox|wocbot|ichiro|DuckDuckBot|lssrocketcrawler|drupact|webcompanycrawler|acoonbot|openindexspider|gnam gnam spider|web-archive-net.com.bot|backlinkcrawler|coccoc|integromedb|content crawler spider|toplistbot|seokicks-robot|it2media-domain-crawler|ip-web-crawler.com|siteexplorer.info|elisabot|proximic|changedetection|blexbot|arabot|WeSEE:Search|niki-bot|CrystalSemanticsBot|rogerbot|360Spider|psbot|InterfaxScanBot|Lipperhey SEO Service|CC Metadata Scaper|g00g1e.net|GrapeshotCrawler|urlappendbot|brainobot|fr-crawler|binlar|SimpleCrawler|Livelapbot|Twitterbot|cXensebot|smtbot|bnf.fr_bot|A6-Indexer|ADmantX|Facebot|Twitterbot|OrangeBot|memorybot|AdvBot|MegaIndex|SemanticScholarBot|ltx71|nerdybot|xovibot|BUbiNG|Qwantify|archive.org_bot|Applebot|TweetmemeBot|crawler4j|findxbot|SemrushBot|yoozBot|lipperhey|y!j-asr|Domain Re-Animator Bot|AddThis)';
let re = new RegExp( botPattern, 'i' );
let userAgent = navigator.userAgent;
return re.test( userAgent );
};
let burst_is_do_not_track = () => {
if ( burst.options.do_not_track ) {
// check for doNotTrack and globalPrivacyControl headers
return '1' === navigator.doNotTrack || 'yes' === navigator.doNotTrack ||
'1' === navigator.msDoNotTrack || '1' === window.doNotTrack || 1 === navigator.globalPrivacyControl;
}
return false;
};
/**
* Make a XMLHttpRequest and return a promise
* @param obj
* @returns {Promise<unknown>}
*/
let burst_api_request = obj => {
// generate a new token every request
return new Promise( ( resolve, reject ) => {
// if browser supports sendBeacon use it
if ( burst.options.beacon_enabled ) {
// send the request using sendBeacon
window.navigator.sendBeacon( burst.beacon_url, JSON.stringify( obj.data ) );
resolve( 'ok' );
} else {
let burst_token = 'token=' + Math.random().toString( 36 ).replace( /[^a-z]+/g, '' ).substring( 0, 7 );
// if browser supports fetch keepalive, it will use it. Otherwise, it will use a normal XMLHttpRequest
wp.apiFetch({
path: '/burst/v1/track/?' + burst_token,
keepalive: true,
method: 'POST',
data: obj.data
}).then(
( res ) => {
if ( 202 === res.status ) {
res.json().then(
( data ) => console.warn( data )
);
}
},
( error ) => console.log( error )
);
}
});
};
/**
* Update the tracked hit
* Mostly used for updating time spent on a page
* Also used for updating the UID (from fingerprint to a cookie)
*/
async function burst_update_hit( update_uid = false ) {
if ( burst_is_user_agent() ) {
return;
}
if ( burst_is_do_not_track() ) {
return;
}
if ( ! burst_initial_track_hit ) {
return;
}
let event = new CustomEvent( 'burst_before_update_hit', {detail: burst});
document.dispatchEvent( event );
let data = {
'fingerprint': false,
'uid': false,
'url': location.href,
'time_on_page': await burst_get_time_on_page(),
'completed_goals': burst_completed_goals
};
if ( update_uid ) {
// add both the uid and the fingerprint to the data
// this way we can update the fingerprint with the uid
// this is useful for consent plugins
data.uid = await burst_uid();
data.fingerprint = await burst_fingerprint();
} else if ( burst_use_cookies() ) {
data.uid = await burst_uid();
} else {
data.fingerprint = await burst_fingerprint();
}
if ( 0 < data.time_on_page || false !== data.uid ) {
await burst_api_request({
data: JSON.stringify( data )
}).catch( error => {
}); // @todo handle error and send notice to the user. If multiple errors send to backend
}
}
/**
* Track a hit
*
*/
async function burst_track_hit() {
if ( burst_initial_track_hit ) { // if the initial track hit has already been fired, we just update the hit
burst_update_hit();
return;
}
burst_initial_track_hit = true;
if ( burst_is_user_agent() ) {
return;
}
if ( burst_is_do_not_track() ) {
return;
}
if ( burst_track_hit_running ) {
return;
}
burst_track_hit_running = true;
let event = new CustomEvent( 'burst_before_track_hit', {detail: burst});
document.dispatchEvent( event );
// add browser data to the hit
let data = {
'uid': false,
'fingerprint': false,
'url': location.href,
'page_id': burst.page_id,
'referrer_url': document.referrer,
'user_agent': navigator.userAgent || 'unknown',
'device_resolution': window.screen.width * window.devicePixelRatio + 'x' + window.screen.height * window.devicePixelRatio,
'time_on_page': await burst_get_time_on_page(),
'completed_goals': burst_completed_goals
};
if ( burst_use_cookies() ) {
data.uid = await burst_uid();
} else {
data.fingerprint = await burst_fingerprint();
}
event = new CustomEvent( 'burst_track_hit', {detail: data});
document.dispatchEvent( event );
let request_params = {
method: 'POST',
data: JSON.stringify( data )
};
burst_api_request( request_params ).catch( error => {
burst_track_hit_running = false;
});
burst_track_hit_running = false;
}
/**
* Initialize events
* @returns {Promise<void>}
*
* More information on why we just use visibilitychange instead of beforeunload
* to update the hits:
* https://www.igvita.com/2015/11/20/dont-lose-user-and-app-state-use-page-visibility/
* https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilitychange_event
* https://xgwang.me/posts/you-may-not-know-beacon/#the-confusion
*
*/
function burst_init_events() {
// Initial track hit
let turbo_mode = burst.options.enable_turbo_mode;
if ( turbo_mode ) { // if turbo mode is enabled, we track the hit after the whole page has loaded
if ( 'loading' !== document.readyState ) {
burst_track_hit();
} else {
document.addEventListener( 'load', burst_track_hit );
}
} else { // if default, we track the hit immediately
burst_track_hit();
}
// Update hit on visibility change (Navigating away from the page)
// Supported by most browsers
document.addEventListener( 'visibilitychange', function() {
if (
'hidden' === document.visibilityState ||
'unloaded' === document.visibilityState
) {
burst_update_hit();
}
});
// This is a fallback for Safari
document.addEventListener( 'pagehide', burst_update_hit );
// Add event so other plugins can add their own events
document.addEventListener( 'burst_fire_hit', function() {
burst_track_hit();
});
// add event so other plugins can add their own events
document.addEventListener( 'burst_enable_cookies', function() {
burst_enable_cookies();
burst_update_hit( true );
});
}
burst_init_events();