Push custom events to Google Tag Manager and Analytics

Continuing the discussion from Setup Google Tag Manager for Analytics:

:warning: This guide is a wiki. I am far from an expert in using Google Tag Manager or Google Analytics. If you are an expert at using GTM, feel free to edit the topic, or reply to the topic with suggestions for improvements. If there are particular events that you are wanting to track, let us know and we’ll see what can be done to push them onto the Data Layer.

To configure your Discourse site to push page view events to Google Tag Manager and Google Analytics, follow the steps outlined here: Setup Google Tag Manager for Analytics - admins - Discourse Meta. After completing those steps, you should see data about the title and URL of Discourse page views on your analytics page.

In this topic I will outline how to add custom events to the data that is sent to GTM and Analytics. Note that this topic assumes you have entered your site setting and updated your site’s content security policy script src setting to allow the Google scripts to run on the site.

Adding Discourse events to the GTM Data Layer

Note: when you enable GTM on Discourse by adding your tag manager ID to your Discourse gtm container id setting, a dataLayer object will be created. You can push new events onto the data_layer to make them available on GTM. If you are just testing the script below without having set your gtm container id , you’ll need to initialize the data_layer object in your script.

Discourse fires numerous events when users perform an action on the site. Some of these events will be useful for analytics. The code below handles the following events:

  • page:bookmark-post-toggled
  • post:created
  • topic:created
  • page:like-toggled
<script type="text/discourse-plugin" version="0.11.0">
// This should only be required if the gtm_container_id hasn't been set, but it is probably 
// best to include it to prevent errors if the gtm container id is ever removed from that setting.
window.dataLayer = window.dataLayer || [];

api.onAppEvent("page:bookmark-post-toggled", post => {
    if (post && post.bookmarked) {
        window.dataLayer.push({
            'event': 'postBookmarked',
            'postId': post.id
        });
    } 
});

api.onAppEvent("post:created", post => {
    if (post) {
        window.dataLayer.push({
        'event': 'postCreated',
        'postId': post.id
        });
    }
});

api.onAppEvent("topic:created", (post, composerModel) => {
    if (post) {
        window.dataLayer.push({
            'event': 'topicCreated',
            'topicCategory': composerModel.get("category.name")
        });
    }
});

api.onAppEvent("page:like-toggled", (post, likeAction) => { 
    let topic = post.topic;
    if (post && topic && likeAction && likeAction.acted) {
        window.dataLayer.push({
            'event': 'postLiked',
            'postId': post.id
        });
  }
});
</script>

In all events except the topicCreated event, the ID of the post that has been acted on is being added to the dataLayer object. The topicCreated event is an example of how other types of data can be added to the dataLayer . If you have followed all steps in Setup Google Tag Manager for Analytics - admins - Discourse Meta, you will also have page.title and page.url variables configure on GTM that can be used to add data about the page’s title or URL to the custom event on GTM.

Configure GTM

For the examples below, I’ll be configuring the postBookmarked event that’s been added to the dataLayer in the code example above.

Create a Trigger

Go to https://tagmanager.google.com/. Select Triggers from the side menu and click the New button to create a new trigger. Give your trigger a name, select Custom Event as the Trigger type and postBookmarked as the Event name . Set the trigger to fire on “All Custom Events”:

Create a Data Layer Variable

Select Variables from the GTM side menu. On the page’s User Defined Variables section, click the New button. Give the variable a recognizable name (you’ll be using it in the next step.) For Variable Type select “Data Layer Variable.” Set the Data Layer Variable Name to postId . This allows GTM to read the value of the postId that you have pushed onto the dataLayer . Make sure the Data Laver Version is set to “Version 2”:

Create a Universal Analytics Event Tag

Select Tags from the GTM side menu and click the button to create a new tag. Give your tag a name. For the Tag Type select Google Analytics: Universal Analytics . For the Track Type select Event . Give your tag a Category. That category will be displayed on your Analytics page when the event fires. The value of the Action field is what will get passed along with the event from GTM to Analytics. To send the postId that was configured in the previous step to Analytics, add that variable’s title, surrounded by {{}} to the form’s Action section. You’ll see that you can select this variable from the field’s drop down menu.

You can now either configure a settings variable and add it to the Google Analytics Settings field, or select “Enable overriding settings in this tag” and enter your Analytics tracking ID into the form:

Submit your changes

Before the data will be available on Analytics, you need to click the GTM Submit button to publish your changes. You should now be able to browse your site and see your actions in the Analytics Events section:

Todo

  • find the best way to track signup events
8 Likes

@simon Thanks for posting this. I appreciate the outline and would like some guidance on how to implement the javascript snippet you have shown in your post.

I’ve setup the default tracking mentioned through GTM for the virtualPageView event as well as the Page Title and Page URL values. I’ve attempted to add the script snippet provided, via GTM custom tag, and I’m not seeing the events outlined firing. :confused:

How should I be adding the javascript “plugin”?

Thanks for the assistance.

The best way to add it is to create a new theme component from your site’s Admin / Customize / Themes section:

Copy and paste the full code snippet from my post into that component’s /head section:

After saving your changes, add the theme component to all active themes on your site:

If you want to confirm that the code is being loaded, you could add a console.log statement to some of the events to make sure that they are firing. Another good tool for debugging this is the GTM preview mode:

When preview mode is enabled, you can see all tags that are pushed from Discourse to GTM.

Get in touch with the Discourse team through our private support system if you have trouble getting this to work.

3 Likes

Thank you - Works great. I converted it for use with Tealium TiQ instead of GTM.

You mentioned numerous events; is there a complete list of events I can reference beyond the examples shown here?

1 Like

There isn’t one yet, but I’ll put together a list tomorrow. In the meantime, are there specific events that you want to be able to track?

2 Likes
  • Registration
  • Login
  • Thread > Subscribe
  • Thread > Share
  • Post Reply > Share
  • Forum Search
1 Like

Here is the list of events I’ve been able to find that can be targeted with the onAppEvent method:

  • page:changed
  • page:bookmark-post-toggled
  • post:created
  • topic:created
  • page:like-toggled
  • topic:flag-created
  • post:flag-created
  • page:topic-loaded
  • page:compose-reply

I am not finding a way to use this method to track the signup or registration events. I’ve asked about this before on Meta, so I am fairly sure there isn’t a user:created, or user:logged-on event that can be hooked into. It looks like the best approach for tracking signups may be to track visits to the /users/account-created page with something like this:

api.onPageChange((url, title) => {
    if (url === '/u/account-created') {
        window.dataLayer.push({
            'event': 'newUserCreated'
        });
    }
});

Unfortunately, that approach will only work for users that are created by submitting the Discourse login form. It also doesn’t give you any details about the user that was created, or tell you if the user activated their account by responding to the Discourse account activation email.

It is also possible to track Discourse click events to push information onto the data layer. This approach could be used with either the Sign Up or Log In buttons. The downside of this is that all it is telling you is that the buttons were clicked. It doesn’t tell you if the user went on to activate their account, or login to the site.

The click tracking approach can also be used to get details about shared topics and posts.

<script type="text/discourse-plugin" version="0.11.0">
window.dataLayer = window.dataLayer || [];

let main = document.getElementById("main");
if (!main) {
    return;
}
let currentUrl; // Setting this in the call to onPageChange, then using it in the clickHandler method.
    
api.onPageChange((url, title) => {
    currentUrl = url
    if (currentUrl === '/u/account-created') {
        window.dataLayer.push({
            'event': 'newUserCreated'
        });
    }
});

let clickHandler = function(e) {
let target = e.target;
if (target) {
    if (target.closest('.login-button')) {
        window.dataLayer.push({
            'event': 'userLoggedIn'
        });

    } else if (target.closest('.sign-up-button')) {
        window.dataLayer.push({
            'event': 'newUserCreated'
        });

    } else if (target.closest('#topic-footer-button-share-and-invite')) {
        window.dataLayer.push({
            'event': 'topicShared',
            'url': currentUrl
        });

    } else if (target.closest('.post-controls .share')) {
        let shareUrl = $(target).parent().data('share-url')
        window.dataLayer.push({
            'event': 'postShared',
            'post': shareUrl
        });
    }
}

return false;
};

main.addEventListener("click", clickHandler);
main.addEventListener("touchstart", clickHandler);
</script>

I’d still like to find a better way of passing the login and signup events to analytics. I’ll look into finding a way of tracking search events as well.

2 Likes