Skip to content
~/reflective_data

blog / google analytics

Tracking Rage Clicks Using Google Tag Manager and Google Analytics

By Silver Ringvee · Sep 17, 2019 · 5 min read

Google AnalyticsGoogle Tag ManagerTechnicalTools

Visitors rage clicking on certain elements on your website is a good indicator of a UX error. For example, people may click on a blue text that is not a link or on an image that has no click functionality.

Detecting and fixing such usability issues is crucial, and luckily the detection part is doable using Google Tag Manager and Google Analytics.

Rage click is a situation where, in a short period of time, a website user clicks multiple times on a specific element. I.e. in two seconds, a visitor clicks three times on an image.

Without further ado, let’s see how tracking rage clicks works in Google Tag Manager.

Step 1 – Create a new Tag that detects rage clicks

Google Tag Manager - detect rage click
Google Tag Manager – detect rage click

This tag is responsible for detecting rage clicks and pushing a custom event rage_click into the data layer.

There are a few variables that you can play with to make it best fit your use case:

no_of_clicks – after how many clicks do we consider it a rage click. Default is 3.

time – in what time period should the clicks happen. Default is 2 seconds.

radius – in what radius should the clicks happen. Default is 100px.

The following variables are pushed into the data layer when a rage click is detected:

event – rage_click

rc_element – selector of the element on which the clicks happened

rc_count – the number of clicks

rc_max_distance – maximum distance between the clicks

rc_time_diff – period from first to last click

PS! You don’t have to send all of them to GA, pick the ones you think make the most sense.

Full code snippet. – Requires jQuery to be loaded on the page.

if ( typeof(jQuery) === 'function' ) {
    jQuery(document).ready(function($) {
        jQuery.fn.extend({
            getPath: function() {
                var path, node = this;
                while (node.length) {
                    var realNode = node[0],
                        name = realNode.localName;
                    if (!name) break;
                    name = name.toLowerCase();
                    var parent = node.parent();
                    var sameTagSiblings = parent.children(name);
                    if (sameTagSiblings.length > 1) {
                        var allSiblings = parent.children();
                        var index = allSiblings.index(realNode) + 1;
                        if (index > 1) {
                            name += ':nth-child(' + index + ')';
                        }
                    }
                    path = name + (path ? '>' + path : '');
                    node = parent;
                }
                return path;
            }
        });
        // Number of rage clicks
        var no_of_clicks = 3;
        //Time interval - 3 for 3 secs, 4 for secs and likewise
        var time = 2;
        var click_events = [];
        //internal variables
        var possible_click = 3;
        var radius = 100;
        function detectXClicks(count, interval) {
            var last = click_events.length - 1;
            var time_diff = (click_events[last].time.getTime() - click_events[last - count + 1].time.getTime()) / 1000;
            //returns false if it event period is longer than 5 sec
            if (time_diff > interval) return null;
            //check click distance
            var max_distance = 0;
            for (i = last - count + 1; i < last; i++) {
                for (j = i + 1; j <= last; j++) {
                    var distance = Math.round(Math.sqrt(Math.pow(click_events[i].event.clientX - click_events[j].event.clientX, 2) + Math.pow(click_events[i].event.clientY - click_events[j].event.clientY, 2)));
                    if (distance > max_distance) max_distance = distance;
                    if (distance > radius) return null;
                }
            }
            var result = {
                count: count,
                max_distance: max_distance,
                time_diff: time_diff
            }
            return result;
        }
        function removeUsedClickPoints(count) {
            click_events.splice(click_events.length - count, count);
        }
        $("body").click(function(event) {
            click_events.push({
                event: event,
                time: new Date()
            });
            //remain only required number of click events and remove left of them.
            if (click_events.length > possible_click) {
                click_events.splice(0, click_events.length - possible_click);
            }
            //detect 3 click in 5 sec
            if (click_events.length >= 3) {
                var result = detectXClicks(no_of_clicks, time);
                if (result != null) {
                    var path = $(event.target).getPath();
                    //console.log('Rage Click: ' + JSON.stringify(result));
                    dataLayer.push({
                        'event': 'rage_click',
                        'rc_element': path,
                        'rc_count': result.count,
                        'rc_max_distance': result.max_distance,
                        'rc_time_diff': result.time_diff
                    });
                    removeUsedClickPoints(3);
                }
            }
        });
    });
}

Step 2 – Create a new Trigger

The snippet from the previous step is pushing the rage_click event into the data layer every time a rage click is detected. Now we need to create a trigger that listens to that event.

Google Tag Manager - rage click trigger
Google Tag Manager – rage click trigger

Step 3 – Send an event to Google Analytics

Awesome, now let’s create a new tag that is responsible for sending the custom event to Google Analytics.

Send rage click to Google Analytics
Send rage click to Google Analytics

You can play around with the event parameters, especially with the event label to best match your needs but the recommended values are as seen in the screenshot above.

Before publishing your changes, don’t forget to enter the preview mode in Google Tag Manager and test the setup yourself. Go ahead and do a few rage clicks and see if an event is getting sent to Google Analytics. Also, check the event parameters and see if they match your expectations.

Step 4 – Using this data

Okay, so you have configured everything correctly, tested it and it works fine. Now, how do you put this data into use?

First, go into Google Analytics and find your rage click events. If you did as described in this post, you find them by clicking on Overview under Behavior –> Events, then find the “Rage Click” event category.

Rage click report in Google Analytics
Rage click report in Google Analytics

Click on the “Rage Click” event category and choose Event Action to see the elements on which the rage clicks happened.

Rage click event in Google Analytics

Since elements with the same selectors might be on different pages, it might be helpful to apply a secondary dimension “Page”.

Now, all you need to do is to pick one element, copy its selector and go to the page seen in the secondary dimension.

Next, open the Javascript console of your browser (press F12) and paste your selector in the following format:

jQuery('YOUR>SELECTOR>HERE');

Hover over the line that was returned in the console and it should highlight the element in the DOM.

Seeing the Rage Click element
Seeing the Rage Click element

If you prefer element class over the selector, you can change the event action in GTM from the rc_element to GTM’s built-in Click Class variable.


Great! That’s it, should you need any help with tracking rage clicks using Google Tag Manager and Google Analytics, post your questions in the comments below.

Should you need further help with your analytics setup, take a look at our services.

Cover photo by Emmanuel on Unsplash

newsletter.sh

Join 7,900+ people building with data and AI

Field notes from our experts on tracking, data pipelines, experimentation and what AI is changing in data work. One or two emails a month, no fluff.

// unsubscribe any time
author

written by

Silver Ringvee

Silver Ringvee is an expert in both traditional digital analytics and user behavior analysis. Besides analytics, Silver also has a strong experience in A/B testing and web development. Over the years, he has worked on over a hundred websites helping them become more profitable using various data-driven solutions.

We love AI, but this article was written by one of our experts.

discussion

26 comments

  1. micka

    May 24, 2023

    Could you do the same for implementation with GA4 et tag manger ?

    reply →

  2. KS

    Jul 21, 2022

    Hi – I’m trying to set this up and have no experience at all. I’ve got to the part where you set up a tag to send it to google analytics however in the google analytics settings tab it says “select settings variable” and when you click into that, its got a box for a tracking ID – what do I put here as nothing is working and I have no idea where to find the tracking ID.

    reply →

    1. Tom

      Aug 14, 2022

      the tracking ID = which GA account you are sending info to.
      You can find tracking ID at GA -> admin -> property -> tracking info -> tracking code
      A tracking ID looks like “UA-12345678-2”

      reply →

  3. Beatrisa

    Nov 23, 2020

    will amazon spin off aws

    reply →

  4. Roi

    Nov 19, 2020

    It doesnt works for me .. It says all the DLV ( rc_element, rc_time_diff…) are unknown.

    what can I do to solve it ?

    reply →

    1. Wasia Javed

      Nov 30, 2021

      From the VARIABLES tab, create a new data layer variable. Name the variable as DLV-rc_element and put “rc_element” (wihtout quotes) in the Data Layer Variable Name tab. Do the same for other unknown variables.

      reply →

  5. jul

    Jul 7, 2020

    Hi,
    Thanks for the details, it works well !
    We see the event action & page recorded in Google Analytics. However, we don’t understand your very last explanation, I mean how to identify the rage click element in the page with the console…
    From this for example : “html>body>div:nth-child(2)>div:nth-child(3)” or “html>body>div:nth-child(2)>div:nth-child(2)>div>div>div>div>div>div>div>ul>li>div:nth-child(2)>div>div>div>div>div>h1”

    reply →

    1. Silver Ringvee

      Jul 8, 2020

      Hi!
      If you’re using Google Chrome, open the developer tools, navigate to console tab and paste document.querySelector('YOUR SELECTOR'); in the input field and click enter. Then hover over the matched element to see which element it is.
      If you’re still having trouble figuring this out, I recommend asking your developer 🙂

      reply →

      1. jul

        Jul 10, 2020

        Perfect, thank you 😉

        reply →

  6. Béate Vervaecke

    Feb 14, 2020

    I don’t speak JS, so I haven’t got a clue what this means.
    I copied the JS from Github and when previewing GTM, I get following message: Error at line 1, character 3: Parse error. primary expression expected
    What am I doing wrong?

    reply →

    1. Silver Ringvee

      Feb 21, 2020

      Did you put your JS code between < script > < / script > tags?

      reply →

      1. Béate Vervaecke

        Feb 24, 2020

        Yes, still not working. There is jquery on the site.

        if ( typeof(jQuery) === ‘function’ ) {
        jQuery(document).ready(function($) {
        jQuery.fn.extend({

        reply →

        1. Béate Vervaecke

          Feb 25, 2020

          It works, tnx!

  7. Sarah

    Nov 26, 2019

    Best tutorial I’ve seen in a while. Currently testing with different thresholds for rage click duration and radius. Thanks!

    reply →

    1. Silver Ringvee

      Nov 26, 2019

      Hello Sarah!

      I’m glad you liked this post. Should figure out the best settings, feel free to share them here with others 🙂

      reply →

  8. Dawid

    Oct 4, 2019

    Hej
    Is this idea still working? I have tried it several times and still with no positive effect. I have an idea, could you record a video step-by-step how you configured your GTM?

    reply →

    1. Silver Ringvee

      Oct 7, 2019

      Hello Dawid,

      Yes, it is working. We have the exact same setup live on different sites. We might do a video tutorial in the future but it is planned in a few months.

      Could you provide some screenshots of your setup so we could take a look? Feel free to send them over via email [email protected]

      reply →

  9. Dino

    Sep 18, 2019

    Love the idea of this solution.

    The only issue I have with it is the element detail.
    When I have an element return of something like: ‘html>body>nav:nth-child(15)>div>div>div>div>span’
    It has no meaning in GA.

    I think it would be more beneficial to maybe utilise the Click Class variable within GTM, is this something that can be adapted in the code?

    Regards

    reply →

    1. Silver Ringvee

      Sep 18, 2019

      Hello Dino,

      Thank you for your feedback. It really depends, we actually like grabbing the selector and pasting it in the console like $(‘your-selector’) to immediately see the element.

      If you want the click class you can use GTM’s built-in variable as your event label.

      Silver

      reply →

      1. Dino

        Sep 18, 2019

        Thanks for the response Silver,

        That makes sense, I think I was thinking more around a GA users that isn’t so savvy using dev tools in Chrome.

        I guess rage clicks are something that require interpretation to the wider audience.

        I’ll have a play about to see what works best for us.

        Many thanks
        Dino

        reply →

        1. Silver Ringvee

          Sep 18, 2019

          Sure and thank you for pointing this out, I’m going to add a few more details about this in the post.

  10. JT

    Sep 18, 2019

    Not here.
    Only snippet i see, is that on the picture?

    reply →

  11. JT

    Sep 18, 2019

    Could you share the script so we can try it?

    reply →

    1. Silver Ringvee

      Sep 18, 2019

      I’m not sure what you mean by that. The full snippet is in the post.

      reply →

Leave a comment

Your email address will not be published.

put it into practice

Run it yourself, or have our experts do it

platform

the platform

Pipelines, dbt and exploration in one place

Reflective Data is our data platform: managed pipelines from hundreds of sources into your warehouse, hosted dbt with a semantic layer, and an AI data agent. Use all of it or just one part.

services

expert services

Senior specialists for your data stack

Analytics implementation, audits, A/B testing, BI and AI, delivered by the experts who write these articles. Vendor-neutral, for startups and enterprises.