Skip to content
This repository has been archived by the owner on Mar 5, 2020. It is now read-only.

Additional GA Event and Modal View Tracking #373

Merged
merged 1 commit into from
Mar 23, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions components/login.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ var Router = require('react-router');
var Link = Router.Link;

var TeachAPIClientMixin = require('../mixins/teach-api-client');
var ga = require('../lib/googleanalytics.js');

var Login = React.createClass({
mixins: [TeachAPIClientMixin],
Expand Down Expand Up @@ -32,16 +33,20 @@ var Login = React.createClass({
e.preventDefault();
this.setState({loggingIn: true});
this.getTeachAPI().startLogin();
ga.event({ category: 'Login', action: 'Start Login' });
},
handleLogoutClick: function(e) {
e.preventDefault();
this.getTeachAPI().logout();
ga.event({ category: 'Login', action: 'Clicked Logout' });
},
handleApiLoginError: function(err) {
this.setState({loggingIn: false});

if (process.env.NODE_ENV != "test") {
console.log("Teach API error", err);
ga.event({ category: 'Login', action: 'Teach API Error',
nonInteraction:true});
}

if (err.hasNoWebmakerAccount) {
Expand All @@ -50,19 +55,26 @@ var Login = React.createClass({
"have a Webmaker account associated with the email " +
"address you used?"
);
ga.event({ category: 'Login', action: 'Error: Has no Webmaker Account',
nonInteraction:true});
} else {
this.props.alert("An error occurred! Please try again later.");
ga.event({ category: 'Login', action: 'Error Occurred',
nonInteraction:true});
}
},
handleApiLoginCancel: function() {
this.setState({loggingIn: false});
ga.event({ category: 'Login', action: 'Cancelled Login' });
},
handleApiLoginSuccess: function(info) {
this.setState({username: this.getTeachAPI().getUsername(),
loggingIn: false});
ga.event({ category: 'Login', action: 'Logged In' });
},
handleApiLogout: function() {
this.setState({username: null, loggingIn: false});
ga.event({ category: 'Login', action: 'Logged Out' });
},
render: function() {
var content;
Expand Down
64 changes: 61 additions & 3 deletions lib/googleanalytics.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
function warn (s) {
console.warn('[googleanalytics.js', s);
}

module.exports = {
initialize: function() {
if (!process.env.GA_ACCOUNT) {
return;
}

// https://developers.google.com/analytics/devguides/collection/analyticsjs/
(function(i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r;
Expand All @@ -21,15 +24,70 @@ module.exports = {
ga('create', process.env.GA_ACCOUNT, 'auto');
ga('send', 'pageview');
},

/**
* pageview:
* a proxy to basic GA pageview tracking
* @param {[type]} path [description]
* @return {[type]} [description]
* @param {String} path - the current page page e.g. '/about'
*/
pageview: function (path) {
if (typeof ga === 'function') {
ga('send', 'pageview', path);
}
},

/**
* modalview:
* a proxy to basic GA pageview tracking
* @param {String} modalName e.g. 'add-or-edit-club'
*/
modalview: function (modalName) {
path = '/modal/' + modalName;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we decide to make the modals visible at their own URLs so that e.g. the "add your club" modal is visible at "/mozilla-web-clubs/add/", is this solution compatible with that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to clarify, would that mean there are two ways to the display the form? (ie as a modal, and as a standalone page)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, it'd just be the case that /mozilla-web-clubs/add would show you the "darkened" page in the background w/ the modal focused in front of it, and anything that currently opens the modal via JS would instead just be a clickable link to /mozilla-web-clubs/add. The fancypants router would then trigger the transition to the modal.

If that is really weird and nobody else does it then we don't have to... I just like every "thing" on a page to have a URL I guess. It's also a bit annoying to implement in the current architecture so it wouldn't be implemented in v1.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, aside from that, it would theoretically allow us to support people actually using those modals on browsers with JS disabled. Additional work beyond just making the modals have their own URLs would need to be done, though. Again though, not sure whether the modals are considered "progressive" or "required" functionality--I'd think at least the "learn more" would be required, but I suppose we could always have that link be a mailto: link w/ the progressive enhancement being the modal...

Anyways, that's off-topic for now I guess!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's interesting, and I've not seen it done before.

If we make that switch, I think we would have pageview tracking via the router, and we could remove the extra tracking in the modal module.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, cool--I just wanted to make sure it wouldn't screw up metrics that we track over time, e.g. because what used to be the '/modal/addclub"route" in ga suddenly changes to/mozilla-web-clubs/add`.

Thanks!

if (typeof ga === 'function') {
ga('send', 'pageview', path);
}
},

/**
* event:
* GA event tracking
* @param args.category {String} required
* @param args.action {String} required
* @param args.label {String} optional
* @param args.value {Int} optional
* @param args.nonInteraction {Int} 1 = true, 0 = false
*/
event: function (args) {
if (typeof ga === 'function') {

// Simple Validation
if (!args.category || !args.action) {
warn('args.category AND args.action are required');
return;
}

// Required Fields
var fieldObject = {
'hitType': 'event',
'eventCategory': args.category,
'eventAction': args.action
};

// Optional Fields
if (args.eventLabel) {
fieldObject.eventLabel = args.label;
}

if (args.eventValue) {
fieldObject.eventValue = args.value;
}

if (args.nonInteraction) {
fieldObject.nonInteraction = args.nonInteraction;
}

// Send to GA
ga('send', fieldObject);
}
}
};
4 changes: 4 additions & 0 deletions lib/teach-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ var util = require('util');
var urlResolve = require('url').resolve;
var _ = require('underscore');
var request = require('superagent');
var ga = require('../lib/googleanalytics.js');

var STORAGE_KEY = 'TEACH_API_LOGIN_INFO';

Expand Down Expand Up @@ -117,6 +118,7 @@ _.extend(TeachAPI.prototype, {
return callback(err);
}
this.updateClubs();
ga.event({ category: 'Clubs', action: 'Added a Club' });
callback(null, res.body);
}.bind(this));
},
Expand All @@ -130,6 +132,7 @@ _.extend(TeachAPI.prototype, {
return callback(err);
}
this.updateClubs();
ga.event({ category: 'Clubs', action: 'Edited a Club' });
callback(null, res.body);
}.bind(this));
},
Expand All @@ -142,6 +145,7 @@ _.extend(TeachAPI.prototype, {
return callback(err);
}
this.updateClubs();
ga.event({ category: 'Clubs', action: 'Deleted a Club' });
callback(null);
}.bind(this));
}
Expand Down
2 changes: 2 additions & 0 deletions mixins/modal-manager.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
var React = require('react');
var ga = require('../lib/googleanalytics.js');

module.exports = {
contextTypes: {
showModal: React.PropTypes.func.isRequired,
hideModal: React.PropTypes.func.isRequired
},
showModal: function(modalClass, modalProps) {
ga.modalview(modalClass.displayName);
this.context.showModal(modalClass, modalProps);
},
hideModal: function() {
Expand Down
5 changes: 5 additions & 0 deletions pages/clubs.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ var PageEndCTA = require('../components/page-end-cta.jsx');
var Modal = require('../components/modal.jsx');
var ModalManagerMixin = require('../mixins/modal-manager');
var TeachAPIClientMixin = require('../mixins/teach-api-client');
var ga = require('../lib/googleanalytics.js');

var WebLitMap = React.createClass({
render: function() {
Expand Down Expand Up @@ -262,6 +263,10 @@ var ModalAddOrChangeYourClub = React.createClass({

var ModalLearnMore = React.createClass({
handleSubmit: function(e) {

// Once this is wired up, the GA tracking should be fired after validation
ga.event({ category: 'Enquiries', action: 'Request to Find Out More' });

e.preventDefault();
window.alert("Sorry, this functionality has not yet been implemented.");
},
Expand Down