From 77c276fefe85ea19a5fc6c596dc96395a5e7e0b3 Mon Sep 17 00:00:00 2001 From: Sabe Jones Date: Fri, 5 Aug 2016 13:40:25 -0500 Subject: [PATCH] feat(analytics): Facebook "Pixel" (#7871) --- config.json.example | 1 + test/spec/services/analyticsServicesSpec.js | 26 ++++++++++--------- website/client/js/controllers/authCtrl.js | 1 + .../client/js/services/analyticsServices.js | 26 ++++++++++++++++--- website/server/middlewares/locals.js | 4 +-- website/views/index.jade | 2 ++ 6 files changed, 43 insertions(+), 17 deletions(-) diff --git a/config.json.example b/config.json.example index 025f46f482..2fd677c7d4 100644 --- a/config.json.example +++ b/config.json.example @@ -4,6 +4,7 @@ "IP":"0.0.0.0", "CORES":1, "BASE_URL":"http://localhost:3000", + "FACEBOOK_ANALYTICS":"1234567890123456", "FACEBOOK_KEY":"123456789012345", "FACEBOOK_SECRET":"aaaabbbbccccddddeeeeffff00001111", "NODE_DB_URI":"mongodb://localhost/habitrpg", diff --git a/test/spec/services/analyticsServicesSpec.js b/test/spec/services/analyticsServicesSpec.js index 92dd17e0e2..d062692e08 100644 --- a/test/spec/services/analyticsServicesSpec.js +++ b/test/spec/services/analyticsServicesSpec.js @@ -26,22 +26,14 @@ describe('Analytics Service', function () { describe('register', function() { beforeEach(function() { - sandbox.stub(amplitude, 'setUserId'); - sandbox.stub(window, 'ga'); + sandbox.stub(window, 'fbq'); }); - it('sets up user with Amplitude', function() { + it('records a registration event on Facebook', function() { analytics.register(); clock.tick(); - expect(amplitude.setUserId).to.have.been.calledOnce; - expect(amplitude.setUserId).to.have.been.calledWith(user._id); - }); - - it('sets up user with Google Analytics', function() { - analytics.register(); - clock.tick(); - expect(ga).to.have.been.calledOnce; - expect(ga).to.have.been.calledWith('set', {userId: user._id}); + expect(fbq).to.have.been.calledOnce; + expect(fbq).to.have.been.calledWith('track', 'CompleteRegistration'); }); }); @@ -74,6 +66,7 @@ describe('Analytics Service', function () { beforeEach(function() { sandbox.stub(amplitude, 'logEvent'); sandbox.stub(window, 'ga'); + sandbox.stub(window, 'fbq'); }); context('successful tracking', function() { @@ -113,6 +106,15 @@ describe('Analytics Service', function () { expect(ga).to.have.been.calledOnce; expect(ga).to.have.been.calledWith('send', properties); }); + + it('tracks a page view with Facebook', function() { + var properties = {'hitType':'pageview','eventCategory':'behavior','eventAction':'tasks'}; + analytics.track(properties); + clock.tick(); + + expect(fbq).to.have.been.calledOnce; + expect(fbq).to.have.been.calledWith('track', 'PageView'); + }); }); context('unsuccessful tracking', function() { diff --git a/website/client/js/controllers/authCtrl.js b/website/client/js/controllers/authCtrl.js index 13bc8ca1e6..6a380fe9c7 100644 --- a/website/client/js/controllers/authCtrl.js +++ b/website/client/js/controllers/authCtrl.js @@ -62,6 +62,7 @@ angular.module('habitrpg') $http.post(url, scope.registerVals).success(function(res, status, headers, config) { runAuth(res.data._id, res.data.apiToken); + Analytics.register(); }).error(errorAlert); }; diff --git a/website/client/js/services/analyticsServices.js b/website/client/js/services/analyticsServices.js index 19a7c5f095..7d4d1fd02a 100644 --- a/website/client/js/services/analyticsServices.js +++ b/website/client/js/services/analyticsServices.js @@ -32,6 +32,17 @@ }, window['ga'].l = 1 * new Date(); ga('create', window.env.GA_ID, user ? {'userId': user._id} : undefined); + // Facebook + var n = window.fbq = function() { + n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments) + }; + if (!window._fbq) window._fbq = n; + n.push = n; + n.loaded = !0; + n.version = '2.0'; + n.queue = []; + fbq('init', window.env.FACEBOOK_ANALYTICS); + function loadScripts() { setTimeout(function() { // Amplitude @@ -45,16 +56,22 @@ // Google Analytics var a = document.createElement('script'); var m = document.getElementsByTagName('script')[0]; - a.async = 1; + a.async = true; a.src = '//www.google-analytics.com/analytics.js'; m.parentNode.insertBefore(a, m); + + // Facebook + var t = document.createElement('script'); + var f = document.getElementsByTagName('script')[0]; + t.async = true; + t.src = 'https://connect.facebook.net/en_US/fbevents.js'; + f.parentNode.insertBefore(t, f); }); } function register() { setTimeout(function() { - amplitude.setUserId(user._id); - ga('set', {'userId':user._id}); + fbq('track', 'CompleteRegistration'); }); } @@ -72,6 +89,9 @@ amplitude.logEvent(properties.eventAction,properties); ga('send',properties); + if(properties.hitType === 'pageview') { + fbq('track', 'PageView'); + } }); } diff --git a/website/server/middlewares/locals.js b/website/server/middlewares/locals.js index 17a945f1fd..1a85f072cf 100644 --- a/website/server/middlewares/locals.js +++ b/website/server/middlewares/locals.js @@ -12,7 +12,7 @@ import { mods } from '../models/user'; // To avoid stringifying more data then we need, // items from `env` used on the client will have to be specified in this array const CLIENT_VARS = ['language', 'isStaticPage', 'availableLanguages', 'translations', - 'FACEBOOK_KEY', 'NODE_ENV', 'BASE_URL', 'GA_ID', + 'FACEBOOK_KEY', 'FACEBOOK_ANALYTICS', 'NODE_ENV', 'BASE_URL', 'GA_ID', 'AMAZON_PAYMENTS', 'STRIPE_PUB_KEY', 'AMPLITUDE_KEY', 'worldDmg', 'mods', 'IS_MOBILE', 'PUSHER:KEY', 'PUSHER:ENABLED']; @@ -30,7 +30,7 @@ let env = { }, }; -'NODE_ENV BASE_URL GA_ID STRIPE_PUB_KEY FACEBOOK_KEY AMPLITUDE_KEY PUSHER:KEY PUSHER:ENABLED' +'NODE_ENV BASE_URL GA_ID STRIPE_PUB_KEY FACEBOOK_ANALYTICS FACEBOOK_KEY AMPLITUDE_KEY PUSHER:KEY PUSHER:ENABLED' .split(' ') .forEach(key => { env[key] = nconf.get(key); diff --git a/website/views/index.jade b/website/views/index.jade index 5e04451e2d..77c44c3c06 100644 --- a/website/views/index.jade +++ b/website/views/index.jade @@ -12,6 +12,8 @@ html(ng-app='habitrpg', ng-controller='RootCtrl', ng-class='{"applying-action":a meta(name='viewport', content='width=device-width, initial-scale=1.0') meta(name='apple-mobile-web-app-capable', content='yes') meta(name='mobile-web-app-capable', content='yes') + noscript + img(height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=#{env.FACEBOOK_ANALYTICS}&ev=PageView&noscript=1") != env.getManifestFiles("app", "css")