Skip to content

Tracking Google Analytics 4 Events using Data Attributes

David Vallejo

I must admit it, I like to use data-attributes for user clicks interactions rather than delegating that work on the IT team or relying on the class/id attributes. ( Data Attributes Tracking ) .

For Universal Analytics, this was some kind of easy work, since we had some fixed data attributes names (category, action, label, value when talking about events, or pagepath if we wanted to use a virtual pageview ). With the new event based tracking model on Gooogle Analytics 4 ( GA4 , formerly APP+WEB ), this has change, and we have a single hit type which is going to be an “event” all the time, but them we have an unlimited possiblities of parameter names.

On this post I’ll showing my approach to automate the events tracking on Google Analytics 4 using data attributes. Let’s go for it.

First we’ll need a data-attribute named “data-ga4-event” , this one will allow us on the next steps to setup a CSS Selector to trigger our tags.

Then for the events parameters we’ll use the following format: data-ga4-param-{{PARAM_NAME}} .
Note that data attributes use kebab-case, so we’ll using is as “clicked-link-url”

data-ga4-event{{event name}}
data-ga4-param-{{PARAM_NAME}}one per each needed parameter
Data Attributes Definition

Let’s now see some examples. A simple event without parameters will look like this:

<button id="cta"
data-ga4-event="cta click"

and if we need to pass some paraemters it will look like:

<a href=""
>Follow me on Twitter</button>

You may now be thinking, that would need a separate JS snippet for each event, but we’ll be using some JS magic to automatically convert this data attribute tagging on dataLayer pushes automatically.

(function() {
    // Grab all tagged elements
    var events = document.querySelectorAll('[data-ga4-event]');
    var unCamelCase = function(str, separator) {
        separator = typeof separator === 'undefined' ? '_' : separator;
        return str.replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2').replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2').toLowerCase();
    for (var i = 0; i < events.length; i++) {
        events[i].addEventListener('click', function(event) { 
            var target = event.currentTarget;
                var dl = {} 
                dl['event'] = target.dataset['ga4Event'];
                Object.entries(target.dataset).forEach(function(e) {
                    var key = e[0];
                    var value = e[1]
                    var m = key.match('ga4Param(.+)');
                    if (m && m[1]) {
                        dl[unCamelCase(m[1],'_')] = value;

The snippet above will take care of building a dataLayer push each time a click is performed on a element that has a data-ga4-event attribute, and will take also care of converting all data-param-X attributes in snake_case parameters within our event push.

As example our previous example:

<a href=""
>Follow me on Twitter</button>

Will turn being the following dataLayer push:

    "event": "social_link_click",
    "social_network_name": "twitter",
    "social_network_user": "thyng"

Of course you could add some more feature to this snippet, for example for automatically sanitizing the values before the push is sent, or you could build some black list to prevent any non-predefined event to go into your reports.