taking Google Analytics to the next level with Drupal

In this post I'll be taking you through how to go from tracking ambiguous page views and user interactions to more fine-grained, useful and powerful data about how users are really using your site. Since we produce web solutions with Drupal at miggle this post will be focused around improving your analytics data with a Drupal site.

standard analytics

Using Google Analytics you can capture events, page views and searches and create reports based on many different factors. Some of these factors included the source of traffic, types of devices being used, and user location. Using the Google Analytics module created by budda allows direct integration to enable tracking of user activity.

Using events you can capture all sorts of user interactions such as download clicks, outbound link clicks, form submissions and many other types of interactions. To use events you would have write some code on the Drupal side to trigger the GA events accordingly.

Using Analytics in this way will give an overall insight to how your site is being used but might not provide that kind of accuracy that allows you to make informed, critical business decision. 

welcome google tag manager

Google Tag Manager (GTM) provides an extra layer of control to capture events from your site and forward them to tracking services such as Google Analytics, LinkedIn Insights, Adwords Conversion Tracking and many others. This means you don't have to manage all the different tags (snippets of tracking code) on your site individually but can instead manage it all from GTM.

The other significant thing about GTM which links back to the need for producing events on the Drupal side is that Tag Manager has a concept of triggers. There are a range of built in triggers including form submissions, clicks, timers, JavaScript errors, window load and others. You can also provide custom event triggers which can be determined by values of variables.

Variables in GTM allow you to provide constant values, custom JavaScript functions which return a value, lookup table variables based on the current environment. There are built-in variables such as Environment name which can be used in determining the value of other variables or whether a custom event is triggered or not. Variables are very powerful and flexible in GTM and play a large part in allowing you to capture more advanced user interactions.

For each container you can setup different environments to map your site's environments to test GTM events before pushing them live like you would when adding new features to the site itself.

To integrate tag manager with Drupal all you need is this little module created by solotandemhttps://www.drupal.org/project/google_tag

All you need to provide is the Container ID for the site to get tag manager working.

is GTM enough?

Now I'll tell you about a scenario we faced at here at miggle. We had a form submission trigger setup to trigger a tag which would then forward an event to Google Analytics using the universal analytics id. With the form submission trigger you can determine whether you want to exclude submissions that haven't been validated.

You might think that's great but if your site does all it's validation on the server-side then it will not take effect. Even if a part of your site was validated on the client-side (in the browser) there might be further validation on the server-side based on more advanced business rules. With a Drupal site form submission this option doesn't take effect because of the reasons mentioned.

In the form submission view displayed within the analytics reports simply listed all form submission events on a specified form and didn't provide any information on whether those submissions were successful or not.

There are also things like whether a user subscribed to a newsletter or not as a part of the submission which would also be useful to capture for a user registration form.

the state tracker

To tackle this we embarked on a journey of determining the best way to provide such enlightening information and then implementing it. The method chosen was one based on a concept of state bundles. The idea is for an event such as a form submission there are an extensible set of states which Drupal can then inform a service such as GTM through one of many means we will go into later.

This is a rough overview of how the state bundle idea would work for a form submission:

Form submission states diagram

The state tracker module was developed on this idea providing hooks to enable other modules to define state bundles and set states accordingly when the bundle event occurs.

An example instance of this would be if you were to capture state information based on the the value of fields set in a form submission a module developer would first define their form state:


 * Implements hook_state_tracker_state_bundles().
function my_module_state_tracker_state_bundles() {
  $bundles = [
    'my_form' => [
      'label' => t('My form'),
      'type' => 'form',
      'form_id' => 'my_form_id',
      'states' => [
        'subnl1' => t('Subscribed to newsletter 1'),
        'subnl2' => t('Subscribed to newsletter 2'),
  return $bundles;

You would then attach a submit callback to my_form and ensure it is added at the very end. You would then write something like this in the submit callback to set states accordingly:


 * Submit callback to deal with setting states based on the values
 * in the form state.
function my_module_my_form_state_tracker_submit($form, &$form_state) {
  if ($form_state['values']['newsletter_1']) {
    state_tracker_set_state($form['#state_tracker_bundle'], 'subnl1');
  if ($form_state['values']['newsletter_2']) {
    state_tracker_set_state($form['#state_tracker_bundle'], 'subnl2');

This module will then create empty elements in the page which have an ID of a key set in the module's settings form for the specified state for the given bundle. This form should look something like the following:

State Tracker Settings Form

From GTM you could then create a custom JavaScript variable containing a function which checks if the element with the ID newsletter-1-key exists and if it doesn't then return a label like SubNewsletter1. This can then be used in a tag which forwards an event to analytics labelled with the state of the submission.

populating the data layer

Another key piece of functionality that Analytics does provide out of the box is the ability to determine between authenticated and unauthenticated users with it's User-ID feature. When you use GTM to forward events to Google Analytics you need a way of providing data to the dataLayer object which is used to hold data about events. In order to pass a user ID value on to GA to determine whether a user is authenticated or not you need to provide the user ID to the data layer before the GTM snippet in the page.

Initially we implemented a module which solely exposed the user ID to the dataLayer so tag manager could then consume it and send it off to GA. It was easy enough to extend this functionality to allow for a user on the Drupal site (with access to administration pages) to add variables in a settings form and use global tokens for values. Global tokens include things like the current user's ID. These variables are then used to produce the dataLayer JavaScript object in the page.

wrapping things up

To conclude this post we have covered how to utilise Google Tag Manager (GTM) and Drupal to increase the accuracy of Google Analytics reporting to apply states to give context such as whether a form submission was successful or not. We also touched on how we made use of the Google Analytics  User-ID feature in passing data to the GTM dataLayer which GTM can then forward on to with a custom module providing variables. The purpose of this post was to identify ways in which we could produce more accurate analytics reports which would then be more of a solid foundation for making informed business decisions.

If you want to take back control of your web sites and applications then get in touch with miggle to see how we can deliver operational freedom for you in Drupal.