The new Google Analytics 4 is event-driven, so the data you see in reports comes from events that are triggered by interactions a user has with your web/app. GA4 has built-in events that you should take advantage of before going to custom events, mainly because you don’t have to code anything to use most of these events and they will have better integration and support for reporting and data analysis. However, if you can’t use any of the automatic, enhanced, and/or recommended events you can implement your own custom event. Here I will show an implementation of GTM custom event sending data to GA4 for the KnowYourPixel blog.
Important: GA4 has collection and configuration limits. So if you are mapping all events in your web/app, make sure that you are within your quota.
Use-case: reactions to GA4 reports
At the end of each post, we have a reaction box where users click on an Emoji, and the counter of the clicked reaction changes. I would like to track these clicks as events to measure interactions with posts.

Javascript: dataLayer configuration
For this use-case, I’ve decided to code the dataLayer inside the WordPress theme‘s javascript function that controls the interaction with the reaction boxes. If you are already using GTM you know it uses dataLayer to retrieve and save data and we can use it to leverage our custom events.
Here, whenever a user clicks on the reaction box, my function pushes an event called ‘reaction’ to dataLayer and sets the attribute dtL_reaction with the reaction type, status, and name. These values are set in the javascript code above this dataLayer implementation.
// Above this is the reaction js function of my WP Theme.
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'event': 'reaction',
'dtL_reaction': {
'type': reactionType,
'status': reactionStatus,
'name': reactionName
}
});
Variables: send dataLayer attributes to GTM
Now I need to tell GTM to catch these attributes when my code pushes them to dataLayer. GTM does that with variables. On GTM you can do that by going to Variables at the left side menu and click on the New button in the User-Defined Variables section.

After you click the New button, GTM will show you a list of variable types where you can choose from. For our use-case we gonna need Data Layer Variable.

Now we configure GTM to fetch the nested attribute ‘type’ from ‘dtL_reaction’ and assign to the variable dtL_reactionType. As a result, this variable can be used elsewhere in GTM with {{dtL_reactionType}}.

After create all three variables (dtL_reactionType, dtL_reactionName and dtL_reactionStatus) we need to configure the trigger that will activate our GTM tag.
Triggers: GTM custom event
Triggers are listeners that will fire a tag when a specific event happens on your website/app. So in this next step, we will create a trigger that will listen to a custom event ‘reaction’ and fire an event tag on our GA4 sending data from our previous variables. On GTM you can do that by going to Triggers at the left side menu and click on the New button in the Triggers section.

There is a variety of trigger types to choose from, but for our use-case, we will go with Custom Event. GTM has a list of standard methods to track events (e.g. form submission, video play), and everything that is not handled by these should be tracked by using the Custom Event trigger.

In the next screen, we will configure our trigger. For this use-case, only the Event’s name is necessary. Since we are pushing an event to Data Layer called ‘reaction’, we need to tell GTM that this is the name it should look for. In addition, it is possible to filter out custom events and trigger them only when certain conditions are met. However, in our’s example scope there is no need. After that, set the Trigger’s name and save it.

Tag: GA4 Event
Finally, the last step in the configuration is the firing Tag. This is the pixel (tracking code) that GTM fires after the trigger is activated. GTM has a bunch of pre-built tags on their portfolio and even more types on their community template gallery. On GTM you can add one by going to Tags at the left side menu and click on the New button in the Tags section.

In the tag configuration screen, you can set the name, the type, and which triggers fires the tag. For this use-case, I’ve selected the GA4 Event. After choosing this option, GTM will show the fields where you configure your GA4 Event Tag. Alongside the ‘Event name’, I will send parameters to differentiate the events in the GA4 reports. The values for the parameters will be the variables we set before in GTM from the Data Layer.

All set, now it is time to debug to check if everythin went ok and is good to go live.
Debug: test, test, test
Google Tag Manager has a preview feature where you can debug your tags and configurations. It’s a good practice to check things before go-live and understand what’s happening under the hood. Just click the Preview button on the top right and add the URL you want to check.

GTM will open a new tab and shows which tags are firing while you interact with the website. After the URL loaded I’ve clicked on a reaction box to see if my configuration is correct.

As you can see in the previous image, you will find on the left side the list of events that are happening while your site loads and/or there is interaction. Additionally, you can see if some API call was made to the Data Layer and which tags were, or not, fired in the process. In this example, the Data Layer pushed an event called ‘reaction’ and some attributes to be consumed by GTM Variables after I’ve clicked on the reaction box. GTM Custom Event Trigger has listened to this push event and fired the GA4 Event Tag. You can check the details of this tag by clicking on it.
Publish: go-live!
After testing it, your GTM configuration is ready for publication. Just hit the Submit button on the top right. Fill in your submission configuration and click on the Publish button.

All set! You can check if your GTM custom event is being sent to GA4 reports by going to the real-time feature on Google Analytics. Enjoy 🙂