Skip to content

Commit

Permalink
Upgrade eventTracker to 1.0 feature set
Browse files Browse the repository at this point in the history
  • Loading branch information
philipwalton committed Apr 19, 2016
1 parent dd2d7f4 commit 6f9768e
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 60 deletions.
2 changes: 1 addition & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"linebreak-style": [2, "unix"],
"max-len": [2, 80, {"ignoreUrls": true}],
"no-multiple-empty-lines": [2, {"max": 2}],
"no-unused-vars": ["error", {"vars": "all", "args": "all"}],
"no-unused-vars": ["error", {"vars": "all"}],
"no-trailing-spaces": 2,
"object-curly-spacing": [2, "never"],
"quotes": [2, "single"],
Expand Down
58 changes: 42 additions & 16 deletions lib/plugins/event-tracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@


var delegate = require('delegate');
var getAttributes = require('dom-utils/src/get-attributes');
var camelCase = require('../utilities').camelCase;
var createFieldsObj = require('../utilities').createFieldsObj;
var defaults = require('../utilities').defaults;
var provide = require('../provide');

Expand All @@ -32,45 +35,68 @@ function EventTracker(tracker, opts) {
if (!window.addEventListener) return;

this.opts = defaults(opts, {
attributePrefix: 'data-'
events: ['click'],
attributePrefix: 'ga-',
fieldsObj: null,
hitFilter: null
});

this.tracker = tracker;

var prefix = this.opts.attributePrefix;
var selector = '[' + prefix + 'event-category][' + prefix + 'event-action]';
// Binds methods.
this.handleEvents = this.handleEvents.bind(this);

var selector = '[' + this.opts.attributePrefix + 'on]';

this.delegate = delegate(document, selector,
'click', this.handleEventClicks.bind(this));
// Creates a mapping of events to their delegates
this.delegates = {};
this.opts.events.forEach(function(event) {
this.delegates[event] = delegate(
document, selector, event, this.handleEvents, true);
}.bind(this));
}


/**
* Handles all clicks on elements with event attributes.
* @param {Event} event The DOM click event.
*/
EventTracker.prototype.handleEventClicks = function(event) {
EventTracker.prototype.handleEvents = function(event) {

var link = event.delegateTarget;
var element = event.delegateTarget;
var prefix = this.opts.attributePrefix;

this.tracker.send('event', {
eventCategory: link.getAttribute(prefix + 'event-category'),
eventAction: link.getAttribute(prefix + 'event-action'),
eventLabel: link.getAttribute(prefix + 'event-label'),
eventValue: link.getAttribute(prefix + 'event-value')
// Ensures the event type matches the one specified on the element.
if (event.type != element.getAttribute(prefix + 'on')) return;

var defaultFields = {};
var attributes = getAttributes(element);

Object.keys(attributes).forEach(function(attribute) {
if (attribute.indexOf(prefix) === 0 && attribute != prefix + 'on') {
var value = attributes[attribute];

// Detects Boolean value strings.
if (value == 'true') value = true;
if (value == 'false') value = false;

var field = camelCase(attribute.slice(prefix.length));
defaultFields[field] = value;
}
});

this.tracker.send(defaultFields.hitType || 'event', createFieldsObj(
defaultFields, this.opts.fieldsObj, this.tracker, this.opts.hitFilter));
};


/**
* Removes all event listeners and instance properties.
*/
EventTracker.prototype.remove = function() {
this.delegate.destroy();
this.delegate = null;
this.tracker = null;
this.opts = null;
Object.keys(this.delegates).forEach(function(key) {
this.delegates[key].destroy();
}.bind(this));
};


Expand Down
55 changes: 47 additions & 8 deletions lib/utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,46 @@
*/


var assign = require('object-assign');


var utilities = {


/**
* Accepts default and user override fields and an optional tracker and hit
* filter and returns a single object that can be used in ga('send') commands.
* @param {Object} defaultFields The default fields to return.
* @param {Object} userFields Fields set by the user to override the defaults.
* @param {Object} opt_tracker The tracker object to apply the hit filter to.
* @param {Function} opt_hitFilter A filter function that gets
* called with the tracker model right before the `buildHitTask`. It can
* be used to modify the model for the current hit only.
* @return {Object} The final fields object.
*/
createFieldsObj: function(defaultFields, userFields,
opt_tracker, opt_hitFilter) {

if (!utilities.isObject(defaultFields)) defaultFields = {};
if (!utilities.isObject(userFields)) userFields = {};

if (typeof opt_hitFilter == 'function') {
var originalBuildHitTask = opt_tracker.get('buildHitTask');
return {
buildHitTask: function(model) {
model.set(defaultFields);
model.set(userFields);
opt_hitFilter(model);
originalBuildHitTask(model);
}
};
}
else {
return assign({}, defaultFields, userFields);
}
},


/**
* Accepts a function and returns a wrapped version of the function that is
* expected to be called elsewhere in the system. If it's not called
Expand Down Expand Up @@ -49,14 +87,8 @@ var utilities = {
*/
defaults: function(overrides, defaults) {
var result = {};

if (typeof overrides != 'object') {
overrides = {};
}

if (typeof defaults != 'object') {
defaults = {};
}
if (!utilities.isObject(overrides)) overrides = {};
if (!utilities.isObject(defaults)) defaults = {};

for (var key in defaults) {
if (defaults.hasOwnProperty(key)) {
Expand All @@ -68,6 +100,13 @@ var utilities = {
},


camelCase: function(str) {
return str.replace(/[\-\_]+(\w?)/g, function(match, p1) {
return p1.toUpperCase();
});
},


/**
* Capitalizes the first letter of a string.
* @param {string} str The input string.
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
"homepage": "https://github.com/googleanalytics/autotrack#readme",
"dependencies": {
"debounce": "^1.0.0",
"delegate": "^3.0.0"
"delegate": "^3.0.0",
"dom-utils": "^0.1.1",
"object-assign": "^4.0.1"
},
"devDependencies": {
"browserify": "^13.0.0",
Expand Down
1 change: 1 addition & 0 deletions test/analytics.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ module.exports = {
socialTarget: model.get('socialTarget'),
dimension1: model.get('dimension1'),
dimension2: model.get('dimension2'),
nonInteraction: model.get('nonInteraction'),
devId: model.get('&did')
});
});
Expand Down
52 changes: 35 additions & 17 deletions test/event-tracker.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,55 @@
<body>

<button
id="event-button"
data-event-category="foo"
data-event-action="bar"
data-event-label="qux"
data-event-value="42">
id="click-test"
ga-on="click"
ga-event-category="foo"
ga-event-action="bar"
ga-event-label="qux"
ga-event-value="42"
ga-dimension-1="baz"
ga-non-interaction="true">
Click
</button>

<button
id="event-button-some-fields"
data-event-category="foo"
data-event-action="bar"
data-event-label="qux">
id="custom-prefix"
data-ga-on="click"
data-ga-event-category="foo"
data-ga-event-action="bar">
Click
</button>

<button
id="event-button-missing-fields"
data-event-label="qux"
data-event-value="42">
id="social-hit-type"
ga-on="click"
ga-hit-type="social"
ga-social-network="Facebook"
ga-social-action="like"
ga-social-target="me">
Click
</button>

<button
id="event-button-custom-prefix"
event-category="foo"
event-action="bar"
event-label="qux"
event-value="42">
id="pageview-hit-type"
ga-on="click"
ga-hit-type="pageview"
ga-page="/foobar.html">
Click
</button>

<input
id="focus-test"
ga-on="focus"
ga-event-category="Input"
ga-event-action="focus">

<form
ga-on="submit"
ga-event-category="Forms"
ga-event-action="submit">
<button id="submit-test">Submit</button>
</form>

</body>
</html>
Loading

0 comments on commit 6f9768e

Please sign in to comment.