// 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 = 49; // 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 = {}; // Change from initializing with Array() ERE20211025
// 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) {
// I don't know why I have to use JSON.parse() twice here. - ERE20211026
simpleAnalytics_data = JSON.parse(JSON.parse(resp));
// alert(simpleAnalytics_data.visitorStamp); // - Debug ERE20231106
// alert(resp); // - debug ERE20231106
// console.log('****====>>>> simpleAnalytics_data: ', simpleAnalytics_data); // ERE202010118
}
);
}