Google Tag Manager Data Layer for WordPress

[UPDATE] Google Tag Manager Data Layer for WordPress is now available on GitHub

[UPDATE] You guys are too lazy and prefer Duracell Tomi’s plugin 🙂

This year again, I was invited to talk at Superweek, the premier Analytics/PPC conference in Eastern Europe.
I talked about tag management best practices and mentioned my Google Tag Manager data layer for WordPress implementation. In this post, I am sharing my setup with you.

Ready? Let’s modify your theme!

Setting up the data layer for WordPress themes

Note that the code below should go in your WordPress header, ideally in a child theme and before you insert your Google Tag Manager container snippet.

<!-- Google Tag Manager Data Layer -->

<script type="text/javascript">
// URL toolbox - helps grabbing elements in the URL
var _d = document;
var _dl = _d.location;
var _dlp = _dl.pathname;
var _dls = _dl.search;
var _dr = _d.referrer;

// Initialize your data layer and start pushing variables from custom WordPress PHP data layer
dataLayer = [];
dataLayer.push({
// add your Google Analytics property ID here if you haven't defined it as a constant macro in GTM
'GTM_WP_UA': 'UA-1234567-1',
<?php 
	if (is_404()){ // 404 pages, handled with a /404/ prefix as well as the referrer 
?>
'GTM_WP_404': '<?php print is_404(); ?>',
'GTM_WP_404_URL': '/404' + _dlp + '/'+ _dr,
<?php } ?>
<?php 
	if(is_home()){ // Home page is tagged manually here but can be done directly in GTM 
?>
'GTM_WP_post_type': 'home',
'GTM_WP_Category': 'Home',
<?php } ?>

<?php 
	if (is_single()||is_page()){ 
	/* Content pages: either a post or a page 
	*  Query the WP API to retrieve post/page type, author, number of comments, tag, or even custom variables */ 
	$gtm_cat = get_the_category(); // post/page tags being passed as one big string separated by spaces 
	$posttags = get_the_tags(); 
	if ($posttags) { 
		foreach($posttags as $tag){	$gtm_tags .= $tag->name . ' ';}
	}

// Now we populate the Javascript data layer with our PHP variables
?>
'GTM_WP_authorname': '<?php the_author(); ?>',
'GTM_WP_post_type': '<?php print get_post_type(); ?>',
'GTM_WP_Number_Comments': '<?php print get_comments_number(); ?>',
'GTM_WP_Category': '<?php print $gtm_cat[0]->cat_name; ?>',
'GTM_WP_Tags': '<?php print trim($gtm_tags); ?>',
<?php } // Done with WordPress page type/conditions, you can add more default dataLayer variables below 
?>
'GTM_WP_dummy': ''
});
// Don't forget to terminate your data layer correctly!
</script>

Fairly basic PHP and Javascript code all in all.

But my theme layout changes a lot, won’t I break my data layer?

That’s a great point. We’ve already mentioned we want to set up the data layer for WordPress in a child theme to minimize the risk of breaking things. This is especially true when a developer or designer handles your site and is not necessarily aware of your tracking requirements.

In this case, let’s mitigate risk by placing the code in your child theme’s functions.php script.

Create a PHP function that will generate the data layer for WordPress, with similar code from the above example:

function dataLayerForWordpress(){
    $gtmBuffer='';
	$gtmBuffer.="\n
<!-- Google Tag Manager Data Layer -->
<script type='text/javascript'>
  // URL toolbox
  var _d = document;
  var _dl = _d.location;
  var _dlp = _dl.pathname;
  var _dls = _dl.search;
  var _dr = _d.referrer;
  var dataLayer = [{
    'language': 'en',";				
$gtmBuffer.= "\n\t'isLoggedIn': '" . (is_user_logged_in()==true ?  'Yes' : 'No')."',"; 
// Is this a 404 page? (boolean)		
if (is_404()){
$gtmBuffer.="\n
    'is404': '".is_404()."',
    'url404': '/404' + _dlp + '|' + (_dr ? _dr : 'direct'),
";}

if(is_home()){
$gtmBuffer.="\n\t'postType': 'home', // '".get_post_type()."'
";}

if (is_single()||is_page()){
  $gtm_cat = get_the_category();
  $gtm_catname = count($gtm_cat)>-1 ? $gtm_cat[0]->cat_name : '';
   
  $gtm_tags ='';
  for ($cati=0;$cati<count($gtm_cat);$cati++){
	  $gtm_cats[]= $gtm_cat[$cati]->cat_name;
  }
  $posttags = get_the_tags();
  if ($posttags) {
	
    foreach($posttags as $tag) {$gtm_tags .= $tag->name . ' ';}
  }
  if ($gtm_cats){$gtm_catconcat=join(",",$gtm_cats);}else{$gtm_catconcat="";}
  $gtmBuffer.="\n
    'author': '".get_the_author()."',
    'postType': '".get_post_type()."',
    'postCategory': '".$gtm_catname."',
    'postCategories': '". $gtm_catconcat."',
    'postTags': \"".addslashes(trim($gtm_tags))."\",	
  ";
}
$gtmBuffer.="\n			
    'terminator': 'I\'ll be back'
  }];
	";
	// You migh as well insert your GTM snippet here
	$gtmBuffer.="\n
		</script>
		<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-ABC1234');</script>
<!-- End Google Tag Manager -->
	";
	print $gtmBuffer; // Outputs the data layer to your theme
};
add_action('wp_head', 'dataLayerForWordpress');

Notice that the add_action call with trigger the function and insert its contents (the data layer for WordPress as well as the Google Tag Manager container snippet) within the HEAD tag, as recommended.

Setting up GTM to use the data layer for WordPress

Once that code is in place, you need to create macros in GTM to handle the datalayer variables we defined.

gtm for wordpress macros

Now I need to update my GTM page tracking call, in this case with Universal Analytics, in which I’ve already defined custom variables.

gtm for wordpress tag

And of course, these are custom dimensions I’ve already defined in Google Universal Analytics:

gtm for wordpress custom vars

What will my reports look like?

Great, now how do I get the data out? Build a custom report, like so:

gtm for wordpress custom report google universal analytics

Which turns into the following drill-down report:

gtm for wordpress custom report step 1

Then click on “post” to get author names.

gtm for wordpress custom report step 2

Great, just me. Then again, I had it coming 🙂
Let’s click on:

gtm for wordpress custom report step 3

And now we’re down to content categories. Our next click is going to take us to the page level (URL or title depending on your custom report setup.

gtm for wordpress custom report step 4

OK that was way too much coding for me. Got anything simpler?

Not all of us are technically minded, but then again, maybe we should be if we work in digital marketing. If you don’t want to modify your WordPress blog because you’re not confident in your technical abilities, that’s fine too.

In that case, look no further and install my esteemed collegue Tomas Geiger’s (he goes by Duracell Tomi) Google Tag Manager for WordPress plugin. The wizard-like setup will guide through most of the steps I showed you in the above sections.

In closing

And there you have it, folks! With this, you can install your data layer for WordPress and get powerful hierarchical reports in Google Analytics.

Enjoyed this post? Let me know in the comments and don’t hesitate to share your results!

Author: Julien Coquet

Julien Coquet is a veteran of digital analytics, with 20+ years of experience in al things data, web and app. He is currently Senior Director of Data, EMEA @ Monks.

3 thoughts on “Google Tag Manager Data Layer for WordPress”

  1. Julien,

    I tried your script and it worked for the most part, but I was not able to get “php the_author” to work. I also added “php the_date” as a variable but I wasn’t able to get that to work either. Any ideas?

  2. Julien,

    I found that “php the_author” has to be called inside of the loop. The same goes for “php the_date.” I know it’s less than ideal, so I moved your code to the end of the single.php page and then loaded GTM in the footer. It seems to be working fine now.

    Isn’t there a rule that will delay the loading of a tag until after the data layer has loaded? I seem to remember reading that on someone’s site once.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.