Skip to content

Commit

Permalink
Basic Google analytics (#92)
Browse files Browse the repository at this point in the history
* Added trackig of page views.

* Added moment play/pause event tracking.

* Switched to double quoted strings.

* Fixed a linting error.

* Started tracking play time with periodic events.

* Minor improvements.

* Better throttling for GA events

* Added Google Analytics as a webpack external.

* Moved Google Analytics initialization code to the header.

* Made Google Analytics configurable.
  • Loading branch information
ColeDeanShepherd authored and austinpray committed Oct 4, 2016
1 parent fb656ee commit 08463c1
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 10 deletions.
2 changes: 1 addition & 1 deletion config/default.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// default config
export default {
module.exports = {
apiEntry: "http://localhost:4060",
GitHubRepo: "https://github.com/UTD-CRSS/app.exploreapollo.org",
TravisBaseURL: "https://travis-ci.org/UTD-CRSS/app.exploreapollo.org"
Expand Down
2 changes: 1 addition & 1 deletion config/development.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// development config
export default {};
module.exports = {};
6 changes: 3 additions & 3 deletions config/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import defaultConfig from "./default";
var defaultConfig = require("./default");

// TODO: more robust config management
const specificConfig = require(`./${process.env.APP_ENV}.js`).default;
const specificConfig = require(`./${process.env.APP_ENV || "development"}.js`);

export default Object.assign(
module.exports = Object.assign(
{},
defaultConfig,
specificConfig
Expand Down
5 changes: 3 additions & 2 deletions config/production.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// production config
export default {
apiEntry: "https://explore-apollo-api.herokuapp.com"
module.exports = {
apiEntry: "https://explore-apollo-api.herokuapp.com",
GoogleAnalyticsCode: "UA-83921870-1"
};
5 changes: 3 additions & 2 deletions config/staging.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// staging config
export default {
apiEntry: "https://exploreapollo-api-staging.herokuapp.com"
module.exports = {
apiEntry: "https://exploreapollo-api-staging.herokuapp.com",
GoogleAnalyticsCode: "UA-83921870-1"
};
15 changes: 15 additions & 0 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,21 @@
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title><%= htmlWebpackPlugin.options.title %></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>

<% if (htmlWebpackPlugin.options.GoogleAnalyticsCode) { %>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

ga('create', <%= "'" + htmlWebpackPlugin.options.GoogleAnalyticsCode + "'" %>, 'auto');
</script>
<% } else { %>
<script>
var ga = function () {};
</script>
<% } %>
</head>
<body>
<div id="houston"></div>
Expand Down
47 changes: 47 additions & 0 deletions src/middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { RECEIVE_AUDIO } from "./actions";
import {throttle, isFunction} from "lodash";
import ga from "ga";

// Tracks page-views and audio play times.
export function googleAnalytics(store) {
// This constant isn't exported from redux-router so I'm having to redefine it.
// It's a bit of a hack and makes the Google Analytics code dependent on redux-router's internal implementation.
// The better way to do this is to subscribe to the react router using browserHistory,
// but redux and redux-router make it difficult to access browswerHistory in a middleware function..
const ROUTER_DID_CHANGE = "@@reduxReactRouter/routerDidChange";

const gaMomentEventCategory = "Moment";
const gaPlayTimeEventAction = "playTime";
const gaPlayTimeEventIntervalInMilliseconds = 5000;

// Some helper functions.
const sendPlayTimeEvent = throttle(function(playTimeInMilliseconds) {
if (isFunction(ga)) {
ga("send", "event", gaMomentEventCategory, gaPlayTimeEventAction, store.getState().audio.momentId, playTimeInMilliseconds);
}
}, gaPlayTimeEventIntervalInMilliseconds);

// Return a function handling actions.
return next => action => {
switch (action.type) {
case ROUTER_DID_CHANGE:
// Send a page-view.
if (isFunction(ga)) {
ga("set", "page", action.payload.location.pathname + action.payload.location.search);
ga("send", "pageview");
}

break;
case RECEIVE_AUDIO:
const isPlaying = !!store.getState().audio.playing || !!action.playing;
if (isPlaying && action.time) {
// Audio has started playing, so start sending play time events.
sendPlayTimeEvent(action.time);
}

break;
}

return next(action);
};
}
2 changes: 2 additions & 0 deletions src/store/configureStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createStore, applyMiddleware, compose } from "redux";
import { reduxReactRouter } from "redux-router";
import routes from "../routes";
import thunk from "redux-thunk";
import { googleAnalytics } from "../middleware";
import createLogger from "redux-logger";
import rootReducer from "../reducers";
import createHistory from "history/lib/createBrowserHistory";
Expand All @@ -12,6 +13,7 @@ const isProduction = process.env.NODE_ENV === "production";
const middleware = compact([
applyMiddleware(thunk),
reduxReactRouter({ routes, createHistory }),
applyMiddleware(googleAnalytics),
!isProduction && applyMiddleware(createLogger())
]);

Expand Down
8 changes: 7 additions & 1 deletion webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
var path = require("path");
var HtmlWebpackPlugin = require("html-webpack-plugin");
var webpack = require("webpack");
var config = require("./config");

var isProduction = process.env.NODE_ENV === "production";

Expand Down Expand Up @@ -39,7 +40,8 @@ module.exports = {
title: "Explore Apollo",
template: "index.html", // Load a custom template
inject: "body", //scripts are injected to here
favicon: "./favicon.ico"
favicon: "./favicon.ico",
GoogleAnalyticsCode: config.GoogleAnalyticsCode
}),
new webpack.ProvidePlugin({
fetch: "imports?this=>global!exports?global.fetch!whatwg-fetch"
Expand Down Expand Up @@ -85,5 +87,9 @@ module.exports = {
{ test: /\.eot$/, loader: "file-loader" },
{ test: /\.svg$/, loader: "file-loader" }
]
},

externals: {
"ga": "ga"
}
};

0 comments on commit 08463c1

Please sign in to comment.