diff --git a/config/default.js b/config/default.js
index a09b6ed..4bc4cff 100644
--- a/config/default.js
+++ b/config/default.js
@@ -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"
diff --git a/config/development.js b/config/development.js
index dfd3b80..8cd5107 100644
--- a/config/development.js
+++ b/config/development.js
@@ -1,2 +1,2 @@
// development config
-export default {};
+module.exports = {};
diff --git a/config/index.js b/config/index.js
index 9a9746f..8bf1ba2 100644
--- a/config/index.js
+++ b/config/index.js
@@ -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
diff --git a/config/production.js b/config/production.js
index 975ecc2..43ce426 100644
--- a/config/production.js
+++ b/config/production.js
@@ -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"
};
diff --git a/config/staging.js b/config/staging.js
index 4ac3e27..d60bd06 100644
--- a/config/staging.js
+++ b/config/staging.js
@@ -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"
};
diff --git a/src/index.html b/src/index.html
index 70d7592..40423fb 100644
--- a/src/index.html
+++ b/src/index.html
@@ -4,6 +4,21 @@
<%= htmlWebpackPlugin.options.title %>
+
+ <% if (htmlWebpackPlugin.options.GoogleAnalyticsCode) { %>
+
+ <% } else { %>
+
+ <% } %>
diff --git a/src/middleware.js b/src/middleware.js
new file mode 100644
index 0000000..ab1f71e
--- /dev/null
+++ b/src/middleware.js
@@ -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);
+ };
+}
diff --git a/src/store/configureStore.js b/src/store/configureStore.js
index 3cf19af..03ed16d 100644
--- a/src/store/configureStore.js
+++ b/src/store/configureStore.js
@@ -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";
@@ -12,6 +13,7 @@ const isProduction = process.env.NODE_ENV === "production";
const middleware = compact([
applyMiddleware(thunk),
reduxReactRouter({ routes, createHistory }),
+ applyMiddleware(googleAnalytics),
!isProduction && applyMiddleware(createLogger())
]);
diff --git a/webpack.config.js b/webpack.config.js
index 3758718..85c762d 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -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";
@@ -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"
@@ -85,5 +87,9 @@ module.exports = {
{ test: /\.eot$/, loader: "file-loader" },
{ test: /\.svg$/, loader: "file-loader" }
]
+ },
+
+ externals: {
+ "ga": "ga"
}
};