Tracking Rage Clicks Using Google Tag Manager and Google Analytics
By Silver Ringvee · Sep 17, 2019 · 5 min read
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

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.

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.

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.

Click on the “Rage Click” event category and choose Event Action to see the elements on which the rage clicks happened.
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.

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.
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
micka
May 24, 2023
Could you do the same for implementation with GA4 et tag manger ?
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.
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”
Beatrisa
Nov 23, 2020
will amazon spin off aws
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 ?
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.
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”
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 🙂
jul
Jul 10, 2020
Perfect, thank you 😉
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?
Silver Ringvee
Feb 21, 2020
Did you put your JS code between < script > < / script > tags?
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({
Silver Ringvee
Feb 25, 2020
Could you post a screenshot of your setup? This is how it should look like: https://i.imgur.com/h4edtde.png
Béate Vervaecke
Feb 25, 2020
It works, tnx!
Sarah
Nov 26, 2019
Best tutorial I’ve seen in a while. Currently testing with different thresholds for rage click duration and radius. Thanks!
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 🙂
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?
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]
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
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
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
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.
JT
Sep 18, 2019
Not here.
Only snippet i see, is that on the picture?
Silver Ringvee
Sep 18, 2019
Oh, seems you are right. There’s something wrong with showing code snippets for non-logged-in users.
Added the gist link for now: https://gist.github.com/silversillu/52ad72eaee5450ace862f39e52f6b953
Thanks for poiting this out!
JT
Sep 18, 2019
Could you share the script so we can try it?
Silver Ringvee
Sep 18, 2019
I’m not sure what you mean by that. The full snippet is in the post.