Add analytics middleware and pluggable handlers

This commit is contained in:
Kimmo Puputti 2017-10-25 17:03:11 +03:00
parent e82a775049
commit ceb87c2bb0
4 changed files with 59 additions and 3 deletions

View file

@ -0,0 +1,18 @@
import { LOCATION_CHANGED } from '../ducks/Routing.duck';
// Create a Redux middleware from the given analytics handlers. Each
// handler should have the following methods:
//
// - trackPageView(url): called when the URL is changed
export const createMiddleware = handlers => () => next => action => {
const { type, payload } = action;
if (type === LOCATION_CHANGED) {
const { canonicalUrl } = payload;
handlers.forEach(handler => {
handler.trackPageView(canonicalUrl);
});
}
next(action);
};

19
src/analytics/handlers.js Normal file
View file

@ -0,0 +1,19 @@
export class LoggingAnalyticsHandler {
trackPageView(url) {
console.log('Analytics page view:', url);
}
}
export class GoogleAnalyticsHandler {
constructor(ga) {
if (typeof ga !== 'function') {
throw new Error('Variable `ga` missing for Google Analytics');
}
this.ga = ga;
}
trackPageView(url) {
// https://developers.google.com/analytics/devguides/collection/analyticsjs/single-page-applications#tracking_virtual_pageviews
this.ga('set', 'page', url);
this.ga('send', 'pageview');
}
}

View file

@ -24,6 +24,7 @@ import { authInfo } from './ducks/Auth.duck';
import { fetchCurrentUser } from './ducks/user.duck';
import routeConfiguration from './routeConfiguration';
import * as log from './util/log';
import { LoggingAnalyticsHandler, GoogleAnalyticsHandler } from './analytics/handlers';
import './marketplaceIndex.css';
@ -53,6 +54,22 @@ const setupStripe = () => {
window.Stripe.setPublishableKey(config.stripe.publishableKey);
};
const setupAnalyticsHandlers = () => {
let handlers = [];
// Log analytics page views and events in dev mode
if (config.dev) {
handlers.push(new LoggingAnalyticsHandler());
}
// Add Google Analytics handler if tracker ID is found
if (process.env.REACT_APP_GOOGLE_ANALYTICS_ID) {
handlers.push(new GoogleAnalyticsHandler(window.ga));
}
return handlers;
};
// If we're in a browser already, render the client application.
if (typeof window !== 'undefined') {
// set up logger with Sentry DSN client key and environment
@ -74,7 +91,8 @@ if (typeof window !== 'undefined') {
},
],
});
const store = configureStore(sdk, initialState);
const analyticsHandlers = setupAnalyticsHandlers();
const store = configureStore(initialState, sdk, analyticsHandlers);
setupStripe();
render(store);

View file

@ -2,13 +2,14 @@
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import createReducer from './reducers';
import * as analytics from './analytics/analytics';
/**
* Create a new store with the given initial state. Adds Redux
* middleware and enhancers.
*/
export default function configureStore(sdk, initialState = {}) {
const middlewares = [thunk.withExtraArgument(sdk)];
export default function configureStore(initialState = {}, sdk = null, analyticsHandlers = []) {
const middlewares = [thunk.withExtraArgument(sdk), analytics.createMiddleware(analyticsHandlers)];
// Enable Redux Devtools in client side dev mode.
const composeEnhancers =