Initial commit: Atomaste website
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* Setup event listeners for goals.
|
||||
*/
|
||||
|
||||
let viewportGoals = [];
|
||||
const burst_goals_setup = () => {
|
||||
|
||||
// loop through goals and remove any that don't match the current path or
|
||||
// don't have a path
|
||||
for ( let i = 0; i < burst.goals.length; i++ ) {
|
||||
let goal = burst.goals[i];
|
||||
if ( goal.url && ( goal.url !== window.location.pathname && '*' !== goal.url ) ) {
|
||||
burst.goals.splice( i, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
// loop through all goals and setup event listeners
|
||||
for ( let i = 0; i < burst.goals.length; i++ ) {
|
||||
let goal = burst.goals[i];
|
||||
switch ( goal.type ) {
|
||||
case 'views':
|
||||
burst_setup_viewport_tracker( goal );
|
||||
break;
|
||||
case 'clicks':
|
||||
default:
|
||||
burst_setup_click_tracker( goal );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener( 'scroll', handle_viewport_goals, true );
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if any goals are in the viewport.
|
||||
*/
|
||||
const handle_viewport_goals = () => {
|
||||
viewportGoals.forEach( ( goalData, index ) => {
|
||||
if ( burst_is_element_in_viewport( goalData.element ) ) {
|
||||
burst_goal_triggered( goalData.goal );
|
||||
|
||||
// Remove the goal from the viewportGoals array
|
||||
viewportGoals.splice( index, 1 );
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Setup a viewport tracker for a goal.
|
||||
* @param goal
|
||||
*/
|
||||
const burst_setup_viewport_tracker = ( goal ) => {
|
||||
if ( 0 === goal.attribute_value.length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
let selector = 'id' === goal.attribute ? '#' : '.';
|
||||
let elements = document.querySelectorAll( selector + goal.attribute_value );
|
||||
|
||||
for ( let i = 0; i < elements.length; i++ ) {
|
||||
let element = elements[i];
|
||||
|
||||
// Check if already in viewport
|
||||
if ( burst_is_element_in_viewport( element ) ) {
|
||||
burst_goal_triggered( goal );
|
||||
|
||||
// remove from list of elements to monitor
|
||||
} else {
|
||||
|
||||
// Add to our list of elements to monitor
|
||||
viewportGoals.push({element, goal});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Recursive function to check all parents.
|
||||
* @param element
|
||||
* @return {boolean|boolean|*}
|
||||
*/
|
||||
const is_element_truly_visible = ( element ) => {
|
||||
if ( ! element ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const style = window.getComputedStyle( element );
|
||||
|
||||
if ( 'none' === style.display || '0' === style.opacity ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return is_element_truly_visible( element.parentElement );
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if an element is in the viewport.
|
||||
* @param element
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const burst_is_element_in_viewport = ( element ) => {
|
||||
if ( ! is_element_truly_visible( element ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let rect = element.getBoundingClientRect();
|
||||
return (
|
||||
0 <= rect.top &&
|
||||
0 <= rect.left &&
|
||||
rect.bottom <=
|
||||
( window.innerHeight || document.documentElement.clientHeight ) && /* or $(window).height() */
|
||||
rect.right <= ( window.innerWidth || document.documentElement.clientWidth ) /* or $(window).width() */
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Function to check and trigger a goal when an element is in the viewport.
|
||||
* @param element
|
||||
* @param goal
|
||||
*/
|
||||
const burst_listener_view = ( element, goal ) => {
|
||||
if ( burst_is_element_in_viewport( element ) ) {
|
||||
burst_goal_triggered( goal );
|
||||
|
||||
// @todo event listener does not get removed
|
||||
window.removeEventListener( 'scroll',
|
||||
() => burst_listener_view( element, goal ), true );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Setup a click tracker for a goal.
|
||||
* @param goal
|
||||
*/
|
||||
const burst_setup_click_tracker = ( goal ) => {
|
||||
document.body.addEventListener( 'click', function( event ) {
|
||||
burst_recursive_trigger_check( event.target, goal );
|
||||
});
|
||||
};
|
||||
|
||||
const burst_recursive_trigger_check = ( target, goal ) => {
|
||||
|
||||
//if there is no attribute value, exit
|
||||
if ( 0 === goal.attribute_value.length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
let selector = 'id' === goal.attribute ? '#' : '.';
|
||||
if ( target.matches( selector + goal.attribute_value ) ) {
|
||||
burst_goal_triggered( goal );
|
||||
} else if ( target.parentElement ) {
|
||||
burst_recursive_trigger_check( target.parentElement, goal );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Trigger a goal and add to the completed goals array.
|
||||
* @param goal
|
||||
*/
|
||||
const burst_goal_triggered = ( goal ) => {
|
||||
|
||||
// if burst_completed_goals does not contain goal.id, add it
|
||||
if ( -1 === burst_completed_goals.indexOf( goal.ID ) ) {
|
||||
burst_completed_goals.push( goal.ID );
|
||||
viewportGoals = viewportGoals.filter( goalData => goalData.goal.ID !== goal.ID );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Default export for goals.
|
||||
*/
|
||||
export default () => {
|
||||
burst_goals_setup();
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
let viewportGoals=[];const burst_goals_setup=()=>{for(let e=0;e<burst.goals.length;e++){var t=burst.goals[e];t.url&&t.url!==window.location.pathname&&"*"!==t.url&&burst.goals.splice(e,1)}for(let e=0;e<burst.goals.length;e++){var r=burst.goals[e];("views"===r.type?burst_setup_viewport_tracker:burst_setup_click_tracker)(r)}window.addEventListener("scroll",handle_viewport_goals,!0)},handle_viewport_goals=()=>{viewportGoals.forEach((e,t)=>{burst_is_element_in_viewport(e.element)&&(burst_goal_triggered(e.goal),viewportGoals.splice(t,1))})},burst_setup_viewport_tracker=t=>{if(0!==t.attribute_value.length){var e="id"===t.attribute?"#":".",r=document.querySelectorAll(e+t.attribute_value);for(let e=0;e<r.length;e++){var l=r[e];burst_is_element_in_viewport(l)?burst_goal_triggered(t):viewportGoals.push({element:l,goal:t})}}},is_element_truly_visible=e=>{var t;return!e||"none"!==(t=window.getComputedStyle(e)).display&&"0"!==t.opacity&&is_element_truly_visible(e.parentElement)},burst_is_element_in_viewport=e=>{return!!is_element_truly_visible(e)&&0<=(e=e.getBoundingClientRect()).top&&0<=e.left&&e.bottom<=(window.innerHeight||document.documentElement.clientHeight)&&e.right<=(window.innerWidth||document.documentElement.clientWidth)},burst_listener_view=(e,t)=>{burst_is_element_in_viewport(e)&&(burst_goal_triggered(t),window.removeEventListener("scroll",()=>burst_listener_view(e,t),!0))},burst_setup_click_tracker=t=>{document.body.addEventListener("click",function(e){burst_recursive_trigger_check(e.target,t)})},burst_recursive_trigger_check=(e,t)=>{var r;0!==t.attribute_value.length&&(r="id"===t.attribute?"#":".",e.matches(r+t.attribute_value)?burst_goal_triggered(t):e.parentElement&&burst_recursive_trigger_check(e.parentElement,t))},burst_goal_triggered=t=>{-1===burst_completed_goals.indexOf(t.ID)&&(burst_completed_goals.push(t.ID),viewportGoals=viewportGoals.filter(e=>e.goal.ID!==t.ID))};export default()=>{burst_goals_setup()};
|
||||
@@ -0,0 +1,493 @@
|
||||
// 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_update_hit_count = 0;
|
||||
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';
|
||||
|
||||
// Set up a promise for when the page is activated,
|
||||
// which is needed for prerendered pages.
|
||||
const pageIsRendered = new Promise( ( resolve ) => {
|
||||
if ( document.prerendering ) {
|
||||
document.addEventListener( 'prerenderingchange', resolve, {once: true});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 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 ) {
|
||||
const headers = {
|
||||
type: 'application/json'
|
||||
};
|
||||
const blob = new Blob([ JSON.stringify( obj.data ) ], headers );
|
||||
window.navigator.sendBeacon( burst.beacon_url, blob );
|
||||
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 ) {
|
||||
await pageIsRendered;
|
||||
if ( burst_is_user_agent() ) {
|
||||
return;
|
||||
}
|
||||
if ( burst_is_do_not_track() ) {
|
||||
return;
|
||||
}
|
||||
if ( ! burst_initial_track_hit ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( burst_update_hit_count > 5 ) {
|
||||
return;
|
||||
}
|
||||
burst_update_hit_count++;
|
||||
|
||||
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() {
|
||||
await pageIsRendered;
|
||||
|
||||
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,
|
||||
'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();
|
||||
});
|
||||
|
||||
//for Single Page Applications, we listen to the url changes as well.
|
||||
const originalPushState = history.pushState;
|
||||
const originalReplaceState = history.replaceState;
|
||||
const handleUrlChange = () => {
|
||||
if ( ! burst.options.track_url_change ) {
|
||||
return;
|
||||
}
|
||||
burst_initial_track_hit = false;
|
||||
burst_track_hit();
|
||||
};
|
||||
|
||||
history.pushState = function( state, title, url ) {
|
||||
originalPushState.apply( history, arguments );
|
||||
handleUrlChange();
|
||||
};
|
||||
|
||||
history.replaceState = function( state, title, url ) {
|
||||
originalReplaceState.apply( history, arguments );
|
||||
handleUrlChange();
|
||||
};
|
||||
|
||||
window.addEventListener( 'popstate', handleUrlChange );
|
||||
|
||||
// add event so other plugins can add their own events
|
||||
document.addEventListener( 'burst_enable_cookies', function() {
|
||||
burst_enable_cookies();
|
||||
burst_update_hit( true );
|
||||
});
|
||||
}
|
||||
|
||||
// Listen for consent changes for wp consent api
|
||||
document.addEventListener( 'wp_listen_for_consent_change', function( e ) {
|
||||
var changedConsentCategory = e.detail;
|
||||
for ( var key in changedConsentCategory ) {
|
||||
if ( changedConsentCategory.hasOwnProperty( key ) ) {
|
||||
if ( 'statistics' === key && 'allow' === changedConsentCategory[key]) {
|
||||
burst_init_events();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if ( 'function' !== typeof wp_has_consent ) {
|
||||
|
||||
// no wp consent api available, just track the hit
|
||||
burst_init_events();
|
||||
} else {
|
||||
|
||||
// wp consent api is available, check if there is consent for statistics
|
||||
if ( wp_has_consent( 'statistics' ) ) {
|
||||
burst_init_events();
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user