Last active
February 13, 2018 14:54
-
-
Save RHeijnen/59c1751abf4ba2c34aeb4bc7533f4dbe to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
'use strict'; | |
/* | |
Config | |
*/ | |
const timeFormat = 'YYYYMMDD/HH:mm:ss' | |
const pollingTime = 1000; //ms | |
const fingerprinting = "uid"; | |
const scanWebElements = false; | |
const logCoords = true; | |
const destination = "none"; | |
/* ----------------------------------*/ | |
/** | |
* @function loadScripts is workaround I created to be in total control of imports from one JS file. | |
* @param {array} scriptURL - take 1 url from array of urls, shift it (select it) | |
* --------------------------------------- then create a script tag, add the url as src attribute - and append it to the head | |
* | |
* @param {callback} @function callback - calls the callback function when it is done importing scripts. | |
* -> see it as a window onload | |
*/ | |
function loadScripts(array,callback){ | |
var loader = function(src,handler){ | |
var script = document.createElement("script"); | |
script.src = src; | |
script.onload = script.onreadystatechange = function(){ | |
script.onreadystatechange = script.onload = null; | |
handler(); | |
}; | |
var head = document.getElementsByTagName("head")[0]; | |
(head || document.body).appendChild( script ); | |
}; | |
(function run(){ | |
if(array.length!=0){ | |
loader(array.shift(), run); | |
}else{ | |
callback && callback(); | |
}; | |
})(); | |
} | |
loadScripts([ | |
// load scripts.. | |
// todo make conditional imports based domain | |
// appbuilder already has these files minimized | |
"https://www.gstatic.com/firebasejs/4.1.3/firebase.js", | |
"https://momentjs.com/downloads/moment.js" | |
],function(){ | |
var coords = []; | |
var firstRun = false; | |
var CookieDate = new Date; | |
CookieDate.setFullYear(CookieDate.getFullYear( ) +10); | |
/** | |
* Generate a unique user ID | |
* @return {string} | |
* example: "f498a727-9987-bc60-7f66-b6fa28165af8" | |
*/ | |
function createID(){ | |
function createSubset(){ | |
return Math.floor((1 + Math.random()) * 0x10000) | |
.toString(16) | |
.substring(1); | |
} | |
return createSubset() + createSubset() + '-' + createSubset() + '-' + createSubset() | |
+ '-' + createSubset() + '-' + createSubset() + createSubset() + createSubset(); | |
}; | |
/** | |
* Find cookie by | |
* @param {string} [name] | |
* the name of the cookie, returns cookie if found | |
*/ | |
function getCookie(name) { | |
var value = "; " + document.cookie; | |
var parts = value.split("; " + name + "="); | |
if (parts.length == 2) { | |
return parts.pop().split(";").shift(); | |
}; | |
}; | |
/** | |
* creates getBrowserType() @function | |
* @returns {string} type of browser | |
* used to identify the browser types []; | |
*/ | |
navigator.getBrowserType = (function(){ | |
var ua= navigator.userAgent, tem, | |
M= ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || []; | |
if(/trident/i.test(M[1])){ | |
tem= /\brv[ :]+(\d+)/g.exec(ua) || []; | |
return 'IE '+(tem[1] || ''); | |
}; | |
if(M[1]=== 'Chrome'){ | |
tem= ua.match(/\b(OPR|Edge)\/(\d+)/); | |
if(tem!= null) return tem.slice(1).join(' ').replace('OPR', 'Opera'); | |
}; | |
M= M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?']; | |
if((tem= ua.match(/version\/(\d+)/i))!= null) M.splice(1, 1, tem[1]); | |
return M.join(' '); | |
})(); | |
/** | |
* @function @returns {boolean} based on matching in the userAgent | |
* | |
*/ | |
var isMobile = { | |
Android: function() { | |
return navigator.userAgent.match(/Android/i); | |
}, | |
BlackBerry: function() { | |
return navigator.userAgent.match(/BlackBerry/i); | |
}, | |
iPad: function() { | |
return navigator.userAgent.match(/iPad/i); | |
}, | |
iPhone: function() { | |
return navigator.userAgent.match(/iPhone/i); | |
}, | |
Opera: function() { | |
return navigator.userAgent.match(/Opera Mini/i); | |
}, | |
Windows: function() { | |
return navigator.userAgent.match(/IEMobile/i); | |
}, | |
any: function() { | |
return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows()); | |
} | |
}; | |
/** | |
* call @function isMobile and @returns {string} | |
* save @return value as mobileType | |
*/ | |
var mobileType = "none" | |
if(isMobile.Android()){ | |
mobileType = 'Android'; | |
}else if(isMobile.Opera()){ | |
mobileType = 'Opera'; | |
}else if (isMobile.BlackBerry()){ | |
mobileType = 'BlackBerry'; | |
}else if(isMobile.iPad()){ | |
mobileType = 'iPad'; | |
}else if(isMobile.iPhone()){ | |
mobileType = 'iPhone'; | |
}else if(isMobile.Windows()){ | |
mobileType = 'Windows mobile'; | |
} | |
/** | |
* @function (identifyOS) | |
* @returns {string} based on userAgent identification | |
*/ | |
var identifyOS = function(){ | |
var OSName = "Unknown OS"; // fallback | |
if (navigator.userAgent.indexOf("Win") != -1) OSName="Windows"; | |
if (navigator.userAgent.indexOf("Mac") != -1) OSName="Macintosh"; | |
if (navigator.userAgent.indexOf("Linux") != -1) OSName="Linux"; | |
if (navigator.userAgent.indexOf("Android") != -1) OSName="Android"; | |
if (navigator.userAgent.indexOf("like Mac") != -1) OSName = "iOS"; | |
return OSName | |
} | |
/** | |
* @function (identifyBrowser_version) | |
* @returns {string} returns browser version (based on user agent) | |
*/ | |
var identifyBrowser_version = function(){ | |
return navigator.appVersion; | |
} | |
/** | |
* @function (identifyOS_platform) | |
* @returns {string} returns platform the OS is based on | |
*/ | |
var identifyOS_platform = function(){ | |
return navigator.platform; | |
} | |
/** | |
* | |
* set up time options | |
* @var {string} start_date -> moment formated based on @const timeFormat | |
* TODO: found out if this is all the date magic we need - do we need unix etc ? | |
*/ | |
var start_date = moment().format(timeFormat) | |
var start_date_iso = moment().toISOString(); | |
/** | |
* Clean up host name | |
* Apps within appbuilder 'can' have prefix url's like -> appbuilder.tst... | |
* This @function removes_prefix | |
* @param hostname -> full url | |
* @returns @var {string} cleanURL (removed prefix and postfix) | |
*/ | |
var cleanUpHostName = function(hostname){ | |
var cleanHostName = hostname.replace(/([.])\w+/g,"") | |
if(cleanHostName == "appbuilder"){ | |
var workAroundString = window.location.href; | |
var regexResult1 = workAroundString.match(/(apps\/com.)(.*)(\/.)/); | |
var regexResult2 = regexResult1[2].match(/([.])\w+/g); | |
var regexResult3 = regexResult2[0].replace(".",""); | |
return regexResult3 | |
}else{ | |
return cleanHostName | |
} | |
} | |
/** @var fallback to "UnknownApp" if for some magical reason we can not determine the hostname */ | |
var application = cleanUpHostName(document.location.hostname) || "UnknownApp" ; | |
/** | |
* @function setUID - returns a UID if it already exists, if it does not exist it returns a new one based on | |
* config: @const fingerprinting values. [uid - adv - mix] | |
* @param {string} param values [existing - createNew] | |
* @returns either existing UID or creates a new UID and returns that one. | |
*/ | |
var setUID = function(param){ | |
if(param == "existing"){ | |
return getCookie("RA_UID"); | |
}else if(param == "createNew"){ | |
firstRun = true; | |
if(fingerprinting == "uid"){ | |
var uid = createID(); | |
document.cookie = "RA_UID="+uid+"; path=/; expires=" + CookieDate.toGMTString( ) + ';'; | |
return uid; | |
}else if(fingerprinting == "adv"){ | |
}else if(fingerprinting == "mix"){ | |
} | |
} | |
} | |
/** @var {simple} listings | |
* ---------------------- | |
* @var {string} currentPage - Get current location | |
* @var {string} referPage - Get referPage, even tho it has awefull support. | |
* @var {boolean} isCookieSet - Verify if there is already a cookie set | |
* @var {string} currentUser - Gets or Creates a userUID so we can identify this user | |
*/ | |
var currentPage = window.location.href; | |
var referPage = document.referrer; | |
var isCookieSet = getCookie('RA_UID'); | |
var currentUser = isCookieSet ? setUID("existing") : setUID('createNew'); | |
/** | |
* @function getScrollPercent returns % scrolled on current page | |
* @thanks https://stackoverflow.com/questions/2387136/cross-browser-method-to-determine-vertical-scroll-percentage-in-javascript | |
*/ | |
function getScrollPercent() { | |
var h = document.documentElement, | |
b = document.body, | |
st = 'scrollTop', | |
sh = 'scrollHeight'; | |
return (h[st]||b[st]) / ((h[sh]||b[sh]) - h.clientHeight) * 100; | |
} | |
/** @function getXpathTo - used as click event on dom | |
* @param element - event passess clicked element | |
* @return {string} - returns xpath to this element as string | |
* Used to determine what elements the user clicks on | |
*/ | |
function getXPathTo(element) { | |
// if the element has an ID | |
if (element.id!==''){ | |
return "//*[@id='"+element.id+"']"; | |
} | |
// if the element is the body | |
if (element===document.body){ | |
return element.tagName.toLowerCase(); | |
} | |
// if part of a nodelist | |
var ix= 0; | |
var siblings= element.parentNode.childNodes; | |
for (var i= 0; i<siblings.length; i++) { | |
var sibling= siblings[i]; | |
if (sibling===element){ | |
return getXPathTo(element.parentNode) + '/' + element.tagName.toLowerCase() + '[' + (ix + 1) + ']'; | |
}; | |
if (sibling.nodeType===1 && sibling.tagName === element.tagName) { | |
ix++; | |
}; | |
}; | |
}; | |
/** @function getCoordOnClick - used as click event on dom | |
* @param event - event passed | |
* @return {nothing} - saved data in | |
* Used to determine where the user clicks | |
*/ | |
var getCoordOnClick = function(event){ | |
coords.push({ | |
"x": event.clientX, | |
"y": event.clientY | |
}); | |
}; | |
if(logCoords) document.addEventListener("click", getCoordOnClick); | |
/** | |
* @plain javascript way of doing $(window).width(); | |
* [tested in: Chrome - Safari] | |
*/ | |
var getWindowWidth = function(){ | |
return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; | |
}; | |
/** | |
* @plain javascript way of doing $(window).height(); | |
* [tested in: Chrome - Safari] | |
*/ | |
var getWindowHeight = function(){ | |
return window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; | |
}; | |
/** | |
* @function getScreenHeight @returns screen.height from screen object | |
*/ | |
var getScreenHeight = function(){ | |
return screen.height; | |
}; | |
/** | |
* @function getScreenWidth @returns screen.width from screen object | |
*/ | |
var getScreenWidth = function(){ | |
return screen.width; | |
}; | |
/** | |
* Set up @var trackingObject tracking object | |
*/ | |
var trackingObject = { | |
_uid : currentUser, | |
_start_time : start_date, | |
_start_time_iso : start_date_iso, | |
_end_time : start_date, | |
_end_time_iso : start_date_iso, | |
}; | |
if(firstRun){ | |
trackingObject.device_Storage = { | |
screen_width : getScreenWidth(), | |
screen_height : getScreenHeight(), | |
window_width : getWindowWidth(), | |
window_height : getWindowHeight(), | |
os_system : identifyOS(), | |
os_platform : identifyOS_platform(), | |
browser_type : navigator.getBrowserType, | |
browser_v : identifyBrowser_version(), | |
mobile : mobileType | |
}; | |
firstRun = false; | |
} | |
(function update(){ | |
/** | |
* @function update call is made every @const pollingTime | |
* When we update we log datestamps: | |
* @var end_date - by polling time, and substracting that from each other we can determine how long a user's stay is. | |
* @var end_date_iso - converting the values to ISO for standards | |
* ---------------------------- | |
* Based on config we also update | |
* ---------------------------- | |
* @var scanWebElements - | |
* @var destination - the tracking object | |
* | |
*/ | |
var end_date = moment().format(timeFormat); | |
// userInformation.timeInfo.end_time = end_date; | |
var end_date_iso = moment().toISOString(); | |
if(destination == 'none'){ | |
console.log(trackingObject); | |
delete trackingObject.device_Storage; | |
}else{ | |
// upload to destination | |
}; | |
// database.ref('tracking/'+application+"/"+current_user+"/"+start_date).update(userInformation); | |
setTimeout(update, pollingTime); | |
})(); | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment