Google Tag Manager and React/Redux

Jul 30, 2017

The Google Tag Manager dataLayer is one of the nicest thing when it comes to analytics for the developers. But there’s one major issue when you start having
custom dimensions: you need to reset the dataLayer between your pages or you will be sending the same data for a specific propery over and over again.

And now your user goes to the next page that is not a product of type food anymore:

dataLayer.push({userType='customer',productType='drink'});

If your page hasn’t been reloaded between the 2 push(), the following data will be sent to Google Tag Manager:

{userType='customer',productType='drink',foodName='burger'};

This will not be an issue if your website isn’t a single page app (each page reload
will flush the dataLayer since it gets recreated) but it can be a huge problem if
you build your website using react and redux which are commonly used for single page applications.

I’ll show you how to create and use a middleware that solves this issue using a hidden method of the GTM library.

First we have to find a way to reset the dataLayer. The Google documentation
is not helpful here…so I reached out to Simo Ahava on Twitter to get the answer:

Now that we have a way to reset the dataLayer and our reducer we can move on to our next step: creating a middleware.

import{Types,getDataLayer}from'app/redux/analytics';//assuming this is the path to the reducer we just created// the name of the container for GTM, usually 'dataLayer'constDATA_LAYER_CONTAINER='dataLayer';const_dataLayer=window[DATA_LAYER_CONTAINER]||[];const_gtm=window.google_tag_manager['GTM-XXXX'];//replace with your container Idexportdefault({getState})=>{return(next)=>(action)=>{constreturnValue=next(action);if(action.type===Types.PUSH_TO_DATALAYER){_dataLayer.push(getDataLayer(getState()));}elseif(action.type===Types.RESET_DATALAYER){_gtm[DATA_LAYER_CONTAINER].reset();}returnreturnValue;};};

The last step will be to plug in the middelware:

//somewhere in the file that creates your storeconststore=applyMiddleware(analyticsMiddleware/*, thunk, routerMiddleware...*/)(createStore)(myReducer);

This is not a complete solution and using an undocumented feature from Google Tag Manager can be risky but it does work.
Also note that you can simplify the reducer even more if you only use action creators and types (skipping the state).
I’m also not including the interaction with React but it should be pretty straight forward following the doc: http://redux.js.org/docs/basics/UsageWithReact.html