// PREPARE FOR CONFIGURATION var updateInterval, scriptElementId, analyticsFolder; var loadTime, autoRefreshTime, selectedType, paginationEnabled, paginationCount; var googleStaticMapsAPIkey; // SETTINGS FOR CLIENT'S BROWSER updateInterval = 5; //the interval to update a visitor's log (in seconds) scriptElementId = 'analytics'; //the id attribute of the script element used to call the analytix.js file analyticsFolder = 'analytics/'; //path to the folder containing analytix.php // SETTINGS FOR CONTROL PANEL loadTime = 0; //the speed at which counters are incremented (the smaller, the faster) (0 bypasses ticker animation completely) autoRefreshTime = 1000; //the speed at which data auto-refreshes (in milleseconds) selectedType = 0; //the selected timeframe (whatever is initialized here is the default value) paginationEnabled = 0; //whether or not to paginate visitors in the control panel paginationCount = 25; //how many visitors to display per page if using pagination // SETTINGS FOR EXTERNAL APIs var googleStaticMapsAPIkey = ''; //optional; the API key, if you need to include one, that you have obtained for the Google Static Maps API that is used by this analytics system // CREATE GOOGLE STATIC MAPS API KEY STRING // if an API key was provided above, create a string to append to all Google // Static Maps API requests var googleStaticMapsAPIkeyString = '' if (googleStaticMapsAPIkey != '' && googleStaticMapsAPIkey.length >= 0) { googleStaticMapsAPIkeyString = '&key=' + googleStaticMapsAPIkey; } // OPEN POPUP // opens a popup window (new window, not new tab) with a width of 640 and // a height of 480 to the specified url // // url: the location to load in the popup function openPopup(url) { var newWindow = window.open(url, '_blank', 'width=640, height=480, location=no, menubar=no, resizable=yes, scrollbars=yes, status=no, toolbar=no'); return newWindow; } // GET QUERY // returns the value of the requested 'variable' from the URL's query // string, or returns false if the variable is not found function get(variable) { var query, vars; query = window.location.search.slice(1); vars = query.split('&'); for (var i = 0; i < vars.length; i++) { var pair = vars[i].split('='); if (pair[0] == variable) { return decodeURIComponent(pair[1]); } } return false; } // AJAX CALL // asynchronously connects to a server and requests a file, then processes // the responses with the given function // // url: file to call // data: post or get data // method: either post or get // respond: function to call and pass xmlhttp.responseText as argument to function ajaxCall(url, data, method, respond) { var xmlhttp; data = data || ''; method = method || 'GET'; // console.log('inside AJAXCall Data:==>', data); // ERE20210901 if (window.XMLHttpRequest) { //IE7+, Firefox, Chrome, Opera, Safari xmlhttp = new XMLHttpRequest(); } else {//IE6, IE5 xmlhttp = new ActiveXObject('Microsoft.XMLHTTP'); } xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200 && !(!respond)) { respond(xmlhttp.responseText); } } xmlhttp.open(method, url, true); xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded'); xmlhttp.send(data); } // PARSE SECONDS // takes seconds and returns a time string in the format of HH:MM:SS function parseSeconds(seconds) { var min, sec, hr; min = Math.floor(seconds / 60); sec = (seconds - (min * 60)); hr = Math.floor(min / 60); min = (min - (hr * 60)); return padNumber(hr, 2) + ':' + padNumber(min, 2) + ':' + padNumber(sec, 2); } // PAD NUMBER // adds zeros in front of the given 'number' until it is of the desired // 'length', then returns it as a string function padNumber(number, length){ var num = number + ''; while (num.length < length) { num = '0' + num; } return num; } // PARSE TIME // parses a time given the time since the UNIX epoch in seconds function parseTime(seconds) { var sec, date, ret; sec = (seconds * 1000); date = new Date(sec); ret = padNumber(date.getUTCDate(), 2) + '.' + padNumber((date.getUTCMonth() + 1), 2) + '.' + padNumber(date.getUTCFullYear(), 2) + ' @ ' + padNumber(date.getUTCHours(), 2) + ':' + padNumber(date.getUTCMinutes(), 2) + ':' + padNumber(date.getUTCSeconds(), 2); return ret; } // API KEY // give the code the API key to use when making AJAX requests for // JSON data var APIkey = ''; var companyStatsId = 55; // ERE20201006 - add a unique stats ID for the current company/property // INITIALIZATION var intervalCounter, msTimestamp, specialNote, windowLocation, simpleAnalytics_data; window.onload = function() { intervalCounter = (0 - updateInterval); msTimestamp = Date.now(); let saveClientTimestamp = msTimestamp; // ERE20210118 // change file name to analytix.php - ERE20210118 // Insert a call to the server for UTC time. Check to see if the user's system time is correct - ERE20210112 ajaxCall(analyticsFolder + 'analytix.php', 'action=9', 'POST', function(resp) { let server = JSON.parse(resp); let serverTime = server.UTCTimeStamp; // Check that msTimestamp falls within a day's boundary of X seconds prior and X seconds in the future if (isInDateRange(serverTime, msTimestamp, 300)) { // Range is currently set to 5 minutes (300 seconds) // ERE20210118 // Do nothing } else { // console.log('***> server time is being used for the date stamp. the bad stamp is: ', msTimestamp); msTimestamp = serverTime; } let diff = serverTime - saveClientTimestamp // console.log('*-*-*-*-*-> jsTimestamp: ' + saveClientTimestamp + ' servertime: ' + serverTime + ' <-*-*-*-*-*-> diff: ' + diff + ' milliseconds'); specialNote = document.getElementById(scriptElementId).getAttribute('note'); windowLocation = escape(window.location.href); simpleAnalytics_data = new Array(); // console.log('-+-+-+-+-+>>>> companyStatsId: ', companyStatsId); // ERE20201118 update(); setInterval(update, (updateInterval * 1000)); } ); }; // Date range check on the client's time stamp. If the client's timestamp is outside of the specified range // plus or minus, then use the Server timestamp instead. function isInDateRange(serverTime, clientTime, timeRangeInSec) { const oneDayPrior = serverTime - (timeRangeInSec * 1000); const oneDayFuture = serverTime + (timeRangeInSec * 1000); if ( oneDayPrior <= clientTime && clientTime <= oneDayFuture) { // console.log('*****>*****> The client\'s time stamp is WITHIN range'); return true; } // console.log('*****>>>>>>'); // console.log('*****>*****> The client\'s time stamp is OUT of range <<<<******'); // console.log('*****>>>>>>'); return false; } // UPDATE function update() { intervalCounter += updateInterval; // ERE20201006 - CompanyStatsId was added to the Ajax call // change file name to analytix.php - ERE20210118 ajaxCall(analyticsFolder + 'analytix.php', 'windowLocation=' + windowLocation + '&msTimestamp=' + msTimestamp + '&specialNote=' + specialNote + '&intervalCounter=' + intervalCounter + '&companyStatsId=' + companyStatsId, 'POST', function(resp) { simpleAnalytics_data = JSON.parse(resp); //alert(simpleAnalytics_data.visitorStamp); //alert(resp); //console.log('****====>>>> update() response: ', JSON.parse(resp)); // ERE202010118 } ); }