Drupal‑Friendly Google Tag Manager Configuration with the dataLayer Module
So, you’ve been tasked with implementing Google Tag Manager in order to collect analytics data related to your Drupal site. Perhaps in the past, you’ve seen this process consist of enabling the Google Tag Manager module (or alternatively the Google Analytics Module) and calling it a day. And maybe you’ve been left with the sneaking suspicion that you could be doing more and collecting richer data as a result.
As part of the recent launch of Bounteous.com, we had the opportunity to reevaluate our approach to implementing Google Tag Manager and its related data layer in Drupal 8. Our requirements included:
- Adding common content metadata to the data layer including author, content type, and tags.
- Adding and removing values from the data layer based on the type of content being viewed.
- A clearly defined process for making future adjustments.
We were excited to take another look at the options available to achieve this in Drupal 8 and hopeful we could find a reliable and easily-maintainable solution for our new site.
What’s Google Tag Manager?
Google Tag Manager (GTM) is a tag management system that allows you to easily configure and manage all of your tracking pixels or tags across your website or app. Rather than having to add individual snippets of code for various platforms on certain pages, you can just deploy (or update, or delete) them right from within the GTM interface.
In addition to deploying tags, you can also use a data layer with GTM, which allows you to store values from various sources and configure GTM to send them into different platforms. For example, Google Analytics, Google Ads, or Facebook. This provides a ton of flexibility and customization!
Adding Google Tag Manager to Your Drupal Site
First up is adding the necessary GTM scripts to your site. As with many of the decisions we’ll cover in this post, a big part of the choice comes down to choosing to implement this manually or with help from a contributed module.
While this absolutely could be a custom implementation, the popular GTM module offers a number of benefits. In addition to allowing you to specify your Container ID so that the appropriate GTM scripts will be loaded, it also easily allows you to include the necessary snippets as a file rather than inlining the scripts. This approach more closely follows Drupal JavaScript best practices and also can be compatible with a site’s Content Security Policy. The module also offers a number of options allowing you to include or exclude the snippet based on page path, user role, or response status which can be very handy.
We chose the community-vetted and highly-configurable GTM Module and this continues to be our general recommendation.
Passing Data From Drupal to the Data Layer
Now that we’ve loaded the GTM scripts, the next step is to provide relevant data to the data layer when the page loads. Once again, this could be implemented manually with a custom module, but compared to a custom implementation of the GTM script would require substantially more effort.
Alternatively, the community contributed dataLayer Module can add much of this metadata to the data layer by default. It also offers a wide array of configuration options, along with a number of hooks that make it easy to alter the data that is passed to the data layer.
For example, after enabling the module with the default configuration options, the following data would be provided to the data layer for one of the Insights posts on our site:
{
drupalLanguage: 'en',
drupalCountry: '',
siteName: 'Bounteous',
entityCreated: '1372134476',
entityLangcode: 'und',
entityStatus: '1',
entityUid: '1',
entityUuid: '443e42a3-221a-4a29-8048-xxxxxxxxxxxx',
entityVid: '#####',
entityName: 'example',
entityType: 'node',
entityBundle: 'insights',
entityId: '61112',
entityTitle: 'TOOL: The Regexinator, A Google Analytics RegEx Include Filter Compiler',
entityTaxonomy: {
insights_taxonomy: {
1061: 'Analytics',
1068: 'Google',
1091: 'Google Analytics'
},
insights_miscellaneous_taxonomy: {1122: 'JavaScript'}
},
userUid: '1',
gtm: {start: 1543512968634, uniqueEventId: 0},
event: 'gtm.js'
}
All of this is without any custom code or additional configuration, which by itself would make the dataLayer module a very compelling solution. That’s not all though - let’s take a look at some of dataLayer’s customization options.
Customizing The Data Layer
While the default data is useful, it is also very likely that you would want to provide data from a custom field. dataLayer once again makes this easy. The global settings for the dataLayer module provide an option to “include enabled field values.” Enabling this setting exposes a checkbox on all field settings forms, allowing you to add data for that field to the data layer, and specify the label that should be used in data layer output.
For example, for the office locations displayed on our site, we could add the office nickname to the data layer with the following setting:
For adjustments that can’t be configured in the admin UI, dataLayer offers a number of hooks allowing you to modify the data layer in code. We already had some data handling in place for taxonomy terms on our Insights posts that expected a single-pipe, delimited blogCategories field. Our new Insights posts instead used a taxonomy field called Insights Taxonomy, and the default output for taxonomy terms from the dataLayer module was a series of key-value pairs.
In order to massage this data, we created a custom module that included the following datalayer_alter hook:
/**
* Implements hook_datalayer_alter()
*/
function bounteous_data_layer_datalayer_alter(&$data_layer) {
// Modify data layer for Insights
if (isset($data_layer["entityTaxonomy"]["insights_taxonomy"])) {
$data_layer['blogCategories'] = implode("|", $data_layer["entityTaxonomy"]["insights_taxonomy"]);
}
}
With that module enabled, our taxonomy terms were now passed to the data layer as:
blogCategories: ‘Google Analytics|Analytics|Google’
Pushing Data After The Initial Page Load
You may also need to interact with the data layer as part of events that occur after the initial page load. This can be done with the standard Google Tag Manager push API. You can record events using:
dataLayer.push({'event': 'event_name'});
Or add or replace variables in the data layer using:
dataLayer.push({'variable_name': 'variable_value'});
These interactions can be included in any of the JavaScript libraries used on your Drupal site. Handling these within Drupal.behaviors is encouraged, as it will ensure that these push events occur after the DOM has loaded and the data layer has been instantiated, and also allows these events to be triggered by Drupal AJAX methods when necessary.
For cases where you need to access properties from the data layer on the client side, the dataLayer module also includes the Data Layer Helper Library as a dependency. After adding the script to your Drupal libraries and enabling the option in the admin settings for the dataLayer module, you’ll be able to access the data layer in your scripts like so:
var myHelper = new DataLayerHelper(dataLayer);
var bundle = myHelper.get('entityBundle');
var taxonomy = myHelper.get('entityTaxonomy.my_vocab');
A Flexible End-Result
Part of the motivation behind selecting the dataLayer module is how easily it can adapt to our changing data-collection needs. A large majority of future needs are likely to be able to be addressed through configuration rather than custom code. And when custom code is necessary, the process can be streamlined thanks to the module’s add method or data layer hooks. And this is all in addition to the standard options available on the client side via the Google Tag Manager API, or even within the configuration of GTM itself.
For bounteous.com, we’ve been happy with the combination of the GTM and dataLayer modules thus far, and this is likely to be our recommendation going forward for many Drupal 8 projects.
Drupal + GTM = Awesome
Ultimately, in order to determine what values need to be stored in the data layer, there should be a strategy, which would normally be provided by different teams and stakeholders within your organization. At Bounteous, we knew that our marketing team needed to have values in the data layer that would allow us to measure the performance of our content in Google Analytics, especially our blog posts.
Since values like author, blog categories, and publish date are not default values available in Google Analytics, we could configure the dataLayer module to surface those in the data layer on the insight pages, then configure GTM to send those values to custom fields (Custom Dimensions) that we set up in Google Analytics.
The immediate outcome is that our marketing team can perform deeper analysis on content performance and engagement by author, categories, or publish date. Not only does this insight inform on historic performance, but it also helps drive future content strategies. More relevant, valuable data for analysis? It’s a win for everyone!
Laying the Groundwork
A proper Drupal/GTM setup has immediate uses for tailored reporting about content on your website with Google Analytics. It’s also Step 0 in building a foundation for additional capabilities like remarketing, personalization, and journey orchestration.
By having data from Drupal accessible in GTM’s data layer, we can feed values not only into reporting and analytics tools like Google Analytics, but also collect data and trigger customized experiences -- personalized content on-site, using tools like Google Optimize or Acquia Lift, and orchestrating off-site experience with remarketing through Google Ads or Display & Video 360, or across multiple channels and interaction points with Acquia Journey.
The accessibility of detailed data about the site and users’ interactions with it through GTM enables these and many other approaches for really using data to drive valuable conversions and target audiences effectively.