Skip to content

Commit

Permalink
initial work for autotrack
Browse files Browse the repository at this point in the history
  • Loading branch information
prabrisha-rudder authored and sayan-rudder committed Feb 17, 2020
1 parent 4cd09c0 commit 95c98fe
Show file tree
Hide file tree
Showing 4 changed files with 443 additions and 0 deletions.
4 changes: 4 additions & 0 deletions analytics.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import RudderElementBuilder from "./utils/RudderElementBuilder";
import Storage from "./utils/storage";
import { EventRepository } from "./utils/EventRepository";
import logger from "./utils/logUtil";
import { addDomEventHandlers } from "./utils/autotrack.js";

//https://unpkg.com/[email protected]/dist/browser.js

Expand Down Expand Up @@ -75,6 +76,9 @@ class Analytics {
processResponse(status, response) {
logger.debug("===in process response=== " + status);
response = JSON.parse(response);
if (response.source.useAutoTracking || true) {
addDomEventHandlers(this);
}
response.source.destinations.forEach(function(destination, index) {
logger.debug(
"Destination " +
Expand Down
8 changes: 8 additions & 0 deletions rudder-client-javascript/analytics/dist/rudder.min.js

Large diffs are not rendered by default.

204 changes: 204 additions & 0 deletions rudder-client-javascript/analytics/utils/autotrack.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
import {getDefaultPageProperties} from "./utils"
function addDomEventHandlers(rudderanalytics) {
/* var handler = bind(function(e) {
console.log("handler");
e = e || window.event;
console.log("handler");
}, this); */
var handler = e => {
e = e || window.event;
var target = e.target || e.srcElement;

if (isTextNode(target)) {
target = target.parentNode;
}
if(shouldTrackDomEvent(target, e)){
console.log("to be tracked ", e.type);
} else {
console.log("not to be tracked ", e.type);
}
trackWindowEvent(e, rudderanalytics);

}
register_event(document, 'submit', handler, true);
register_event(document, 'change', handler, true);
register_event(document, 'click', handler, true);
rudderanalytics.page();
};

function register_event (element, type, handler, useCapture) {
if (!element) {
console.error('No valid element provided to register_event');
return;
}
element.addEventListener(type, handler, !!useCapture);
};

function shouldTrackDomEvent(el, event) {
if (!el || isTag(el, 'html') || !isElementNode(el)) {
return false;
}
var tag = el.tagName.toLowerCase();
switch (tag) {
case 'html':
return false;
case 'form':
return event.type === 'submit';
case 'input':
if (['button', 'submit'].indexOf(el.getAttribute('type')) === -1) {
return event.type === 'change';
} else {
return event.type === 'click';
}
case 'select':
case 'textarea':
return event.type === 'change';
default:
return event.type === 'click';
}
}

function isTag(el, tag) {
return el && el.tagName && el.tagName.toLowerCase() === tag.toLowerCase();
}

function isElementNode(el) {
return el && el.nodeType === 1; // Node.ELEMENT_NODE - use integer constant for browser portability
}

function isTextNode(el) {
return el && el.nodeType === 3; // Node.TEXT_NODE - use integer constant for browser portability
}

function shouldTrackElement(el){
if(!el.parentNode || isTag(el, 'body'))
return false
return true
}

function getClassName(el) {
switch(typeof el.className) {
case 'string':
return el.className;
case 'object': // handle cases where className might be SVGAnimatedString or some other type
return el.className.baseVal || el.getAttribute('class') || '';
default: // future proof
return '';
}
}

function trackWindowEvent(e, rudderanalytics) {
var target = e.target || e.srcElement;
if (isTextNode(target)) {
target = target.parentNode;
}

if (shouldTrackDomEvent(target, e)) {
var targetElementList = [target];
console.log(targetElementList)
var curEl = target;
while (curEl.parentNode && !isTag(curEl, 'body')) {
targetElementList.push(curEl.parentNode);
curEl = curEl.parentNode;
}
console.log(targetElementList)

var elementsJson = [];
var href, explicitNoTrack = false;

targetElementList.forEach(el => {
var shouldTrackEl = shouldTrackElement(el);

// if the element or a parent element is an anchor tag
// include the href as a property
if (el.tagName.toLowerCase() === 'a') {
href = el.getAttribute('href');
href = shouldTrackEl && href;
}

// allow users to programatically prevent tracking of elements by adding class 'rudder-no-track'
var classes = getClassName(el).split(' ');
if (classes.indexOf('rudder-no-track') >= 0) {
explicitNoTrack = true;
}

elementsJson.push(getPropertiesFromElement(el));
});

if (explicitNoTrack) {
return false;
}


var elementText="";
var text = getText(target)//target.innerText//target.textContent//getSafeText(target);
if (text && text.length) {
elementText = text;
}
var props = {
'event_type': e.type,
'page': getDefaultPageProperties(),
'elements': elementsJson,
'el_attr_href': href,
'el_text': elementText
}
console.log('web_event', props);
rudderanalytics.track('autotrack', props);
return true;
}
}

function getText(el){
var text = "";
el.childNodes.forEach(function(value){
if(value.nodeType === Node.TEXT_NODE) {
console.log("Current textNode value is : ", value.nodeValue.trim())
text += value.nodeValue;
}
});
return text.trim();
}

function getPropertiesFromElement(elem) {
var props = {
'classes': getClassName(elem).split(' '),
'tag_name': elem.tagName.toLowerCase()
};
console.log(elem.attributes)

let attrLength = elem.attributes.length;
console.log(elem.attributes.length, typeof(elem.attributes))
for(let i=0;i<attrLength;i++){
let name = elem.attributes[i].name;
let value = elem.attributes[i].value;
if(value){
props['attr__' + name] = value;
}
}

var nthChild = 1;
var nthOfType = 1;
var currentElem = elem;
while (currentElem = previousElementSibling(currentElem)) {
nthChild++;
if (currentElem.tagName === elem.tagName) {
nthOfType++;
}
}
props['nth_child'] = nthChild;
props['nth_of_type'] = nthOfType;

return props;
}

function previousElementSibling(el) {
if (el.previousElementSibling) {
return el.previousElementSibling;
} else {
do {
el = el.previousSibling;
} while (el && !isElementNode(el));
return el;
}
}
export {addDomEventHandlers}
Loading

0 comments on commit 95c98fe

Please sign in to comment.