diff --git a/app/lib/analytics.js b/app/lib/analytics.js index f042947c6..e259aa453 100644 --- a/app/lib/analytics.js +++ b/app/lib/analytics.js @@ -5,9 +5,9 @@ Balanced.Analytics = (function() { var isMixpanelLoaded = !Ember.isBlank(ENV.BALANCED.MIXPANEL); var isGoogleAnalyticsLoaded = !Ember.isBlank(ENV.BALANCED.GOOGLE_ANALYTICS); - if (isGoogleAnalyticsLoaded) { - // This page will almost always be over https, so can just load this directly. + // This page will almost always be over https, so can just load this + // directly. $.getScript('https://ssl.google-analytics.com/ga.js', { cache: true }); @@ -65,17 +65,28 @@ Balanced.Analytics = (function() { // HACK: can't find an good way to track all events in ember atm // to track all click events - $(document).on('click', 'a,.btn,button', function() { - var e = $(this); - // trims text contained in element - var tt = e.text().replace(/^\s*([\S\s]*?)\s*$/, '$1'); - var eventName = 'click ' + tt; + $(document).on('click', 'a,.btn,button', Balanced.Analytics.trackClick); + }, + trackClick: function() { + var e = $(this); + // trims text contained in element + var tt = e.text().replace(/^\s*([\S\s]*?)\s*$/, '$1'); + var eventName = 'click ' + tt; - Balanced.Analytics.trackEvent(eventName, {}); - }); + Balanced.Analytics.trackEvent(eventName, {}); }, - trackPage: _.debounce(function(page) { - var currentLocation = page + location.hash; + trackPage: _.debounce(function(routerPath) { + /* + * `routerPath` will look like marketplaces/marketplace/marketplace.transactions + * It's all the names of the routers used to render the current + * view concatenated together. + * The search will look like ?foo=bar + * The hash will look like #/marketplaces/MP123123/transactions + * The final URL therefore will look like the components + * concatenated together. + * */ + + var currentLocation = routerPath + location.search + location.hash; if (isGoogleAnalyticsLoaded) { window._gaq.push(['_trackPageview', currentLocation]); @@ -86,6 +97,7 @@ Balanced.Analytics = (function() { }, 500), trackEvent: function(name, data) { data = data || {}; + data.pageTitle = document.title; if (Balanced.currentMarketplace) { data.marketplaceId = Balanced.currentMarketplace.get('id'); @@ -93,11 +105,12 @@ Balanced.Analytics = (function() { } var filteredData = Balanced.Utils.filterSensitivePropertiesMap(data); - if (isMixpanelLoaded) { + + if (Balanced.Analytics.isMixpanelLoaded) { window.mixpanel.track(name, filteredData); } - if (isGoogleAnalyticsLoaded) { + if (Balanced.Analytics.isGoogleAnalyticsLoaded) { window._gaq.push(['_trackEvent', 'dashboard', name]); } } diff --git a/app/routes/router.js b/app/routes/router.js index d38fc418e..75344c783 100644 --- a/app/routes/router.js +++ b/app/routes/router.js @@ -4,9 +4,8 @@ Balanced.Router = Ember.Router.extend({ /* * This function update page title when a transition is made */ - _update_title: function(infos) { + updatePageTitle: function(infos) { var last_info = infos[infos.length - 1]; - var title = last_info.handler.title; var route = last_info.handler; var page_title = route.get('pageTitle'); @@ -17,10 +16,9 @@ Balanced.Router = Ember.Router.extend({ var self = this; var set_title = function(title) { + document.title = self._doc_title; if (typeof title !== 'undefined') { - document.title = self._doc_title + ' | ' + title; - } else { - document.title = self._doc_title; + document.title += ' | ' + title; } }; @@ -39,9 +37,16 @@ Balanced.Router = Ember.Router.extend({ }, didTransition: function(infos) { - this._update_title(infos); - Balanced.Analytics.trackPage(_.pluck(infos, 'name').join('/')); + this.updatePageTitle(infos); + var controllerPath = this.generateControllerPath(infos); + Balanced.Analytics.trackPage(controllerPath); return this._super.apply(this, arguments); + }, + + generateControllerPath: function(infos) { + // will return the current set of routers used on this route e.g. + // marketplaces/marketplace/marketplace.transactions + return _.pluck(_.rest(infos), 'name').join('/'); } }); @@ -51,7 +56,7 @@ Balanced.Router.map(function() { this.route('logout'); this.route('setup_guest_user', { - path: "/start" + path: '/start' }); this.route('forgotPassword', { path: '/forgot_password' @@ -83,36 +88,36 @@ Balanced.Router.map(function() { this.resource('accounts', { path: '/accounts/:item_id' }); - this.route("redirect_activity_transactions", { + this.route('redirect_activity_transactions', { path: '/activity/transactions' }); - this.route("redirect_activity_orders", { + this.route('redirect_activity_orders', { path: '/activity/orders' }); - this.route("redirect_activity_customers", { + this.route('redirect_activity_customers', { path: 'activity/customers' }); - this.route("redirect_activity_funding_instruments", { + this.route('redirect_activity_funding_instruments', { path: 'activity/funding_instruments' }); - this.route("redirect_activity_disputes", { + this.route('redirect_activity_disputes', { path: 'activity/disputes' }); - this.route("redirect_invoices", { + this.route('redirect_invoices', { path: 'invoices' }); - this.route("orders"); + this.route('orders'); this.resource('orders', { path: '/orders/:item_id' }); - this.route("customers"); + this.route('customers'); this.resource('customer', { path: '/customers/:item_id' }); - this.route("disputes"); + this.route('disputes'); this.resource('dispute', { path: '/disputes/:item_id' }); @@ -127,7 +132,7 @@ Balanced.Router.map(function() { path: '/cards/:item_id' }); - this.route("transactions"); + this.route('transactions'); this.resource('credits', { path: '/credits/:item_id' }); @@ -148,9 +153,9 @@ Balanced.Router.map(function() { path: '/events/:item_id' }); - this.route("logs"); - this.resource("log", { - path: "/logs/:item_id" + this.route('logs'); + this.resource('log', { + path: '/logs/:item_id' }); this.route('invoices', { diff --git a/test/unit/lib/analytics.js b/test/unit/lib/analytics.js new file mode 100644 index 000000000..d750b1da0 --- /dev/null +++ b/test/unit/lib/analytics.js @@ -0,0 +1,39 @@ +module('Balanced.Analytics', { + setup: function() { + var mixPanelAPI = { + track: sinon.spy() + }; + var GACAPI = { + push: sinon.spy() + }; + + window.mixpanel = mixPanelAPI; + window._gaq = GACAPI; + Balanced.Analytics.isMixpanelLoaded = true; + Balanced.Analytics.isGoogleAnalyticsLoaded = true; + }, + teardown: function() { + Testing.restoreMethods( + window.mixpanel, + window._gaq + ); + Balanced.Analytics.isMixpanelLoaded = false; + Balanced.Analytics.isGoogleAnalyticsLoaded = false; + } +}); + +test('test click tracking', function(assert) { + var buttonText = 'sally sad sack'; + var ctx = $(''); + + Balanced.Analytics.trackClick.call(ctx); + + var expectedEventName = 'click ' + buttonText; + + assert.ok(window.mixpanel.track.calledWith(expectedEventName, { + pageTitle: 'QUnit basic example | Login' + })); + assert.ok(window._gaq.push.calledWith( + ['_trackEvent', 'dashboard', expectedEventName] + )); +});