Skip to content

Instantly share code, notes, and snippets.

@jguthmiller
Created September 29, 2013 21:56
Show Gist options
  • Save jguthmiller/6756953 to your computer and use it in GitHub Desktop.
Save jguthmiller/6756953 to your computer and use it in GitHub Desktop.
Google Analytics Event Tracking directive in AngularJS
angular.directive('gaTrack', ['$log', 'GoogleAnalyticsService', '$timeout', function ($log, GoogleAnalyticsService, $timeout) {
return {
//should always be defined as an attribute
restrict: 'A',
//make sure it executes before other directives applied to the same scope
priority: 10,
link: function (scope, element, attrs) {
//initialize variables for use later
var fieldFocus = 0;
var fieldSeconds = 0;
var ms;
var opts = {};
//gaAction is required
if(angular.isUndefined(attrs.gaAction)) {
$log.error('You must specify an action for Google Analytics event tracking');
return;
}
//gaLabel is optional
//TODO possibly add noninteraction as a supported attribute
if(angular.isDefined(attrs.gaLabel)) {
opts.label = attrs.gaLabel;
}
switch(attrs.gaAction) {
case 'Click':
//bind any click actions to the click event (duh)
element.bind('click', function (event) {
GoogleAnalyticsService._trackEvent(attrs.gaTrack, attrs.gaAction, opts);
//If the click action is bound to an outbound link,
//we need to delay the redirect action so that the tracking event has enough time to register
//see https://support.google.com/analytics/answer/1136920?hl=en
if(element.prop('tagName').toLowerCase() == 'a' && angular.isDefined(element.prop('href')) && angular.isDefined(attrs.gaDelay)) {
event.preventDefault();
$timeout(function () {
document.location.href = element.prop('href');
}, 100)
}
});
break;
//If the action specified is 'Field Completed',
//count the number of seconds the user spent in the field
case 'Field Completed':
//radio buttons, checkboxes, and submit buttons are ususally clicked
//so we'll bind those fields to click events
var excludeTypes = ['radio', 'checkbox', 'submit'];
//valid html tag types that we want to track the time spent in the field
var tagTypes = ['input', 'textarea', 'select'];
var tagName = element.prop('tagName').toLowerCase();
var tagType = element.prop('type').toLowerCase();
var timerStarted = false;
//only count time spent in inputs, textareas, and select boxes
if(tagTypes.indexOf(tagName) !== -1) {
//if the input type isn't in the excludeTypes array, count the time spent in the field
if(excludeTypes.indexOf(tagType) === -1) {
//start the timer on focus
element.bind('focus', function () {
if(timerStarted === false) {
fieldFocus = (new Date()).getTime();
timerStarted = true;
}
});
element.bind('blur', function () {
if(timerStarted) {
//stop the timer, and convert milliseconds to seconds
timerStarted = false;
ms = (new Date()).getTime() - fieldFocus;
fieldSeconds = (ms - (ms % 1000)) / 1000;
//send the tracking event
opts.value = fieldSeconds;
GoogleAnalyticsService._trackEvent(attrs.gaTrack, attrs.gaAction, opts);
}
});
//if the element is not a textarea,
//we also need to stop the timer if the user hits enter to submit the form
if(tagName != 'textarea') {
element.keypress(function (e) {
if(e.keyCode == 13) {
if(timerStarted) {
//stop the timer, and convert milliseconds to seconds
timerStarted = false;
ms = (new Date()).getTime() - fieldFocus;
fieldSeconds = (ms - (ms % 1000)) / 1000;
//send the tracking event
opts.value = fieldSeconds;
GoogleAnalyticsService._trackEvent(attrs.gaTrack, attrs.gaAction, opts);
}
}
})
}
}
//if the input type IS in the excludeTypes array, trigger the event on click
else {
element.bind('click', function () {
GoogleAnalyticsService._trackEvent(attrs.gaTrack, attrs.gaAction, opts);
})
}
}
break;
default:
$log.error(attrs.gaAction + ' is not a valid action');
break;
}
}
}
}])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment