Google Analytics 4 Tip: Direct Dual Deployments via the gtag.js Tagging Framework

by Rob English

Event Configuration for gtag.js Direct Dual Deployments

With the release and updates made to GA4 tracking over the course of 2020, there’s been a lot of new content surrounding reporting on and properly implementing GA4, particularly for a dual deployment scenario.  On the implementation side, the focus of a lot of new content has been on implementing GA4 via GTM, which is really the best way to deploy any analytics tagging you do.

For users who don’t have a tag manager though, and won’t have one for the foreseeable future, this means you’re going to be deploying your GA4 tracking via the gtag.js JS tagging framework, directly.  And, while gtag.js is the framework that drives GA4 tracking, it’s completely usable with Universal Analytics deployments too.  Meaning it’s entirely possible that if you’ve direct deployed Universal Analytics tracking, you may already be familiar with the gtag.js library.

For more info on the gtag.js library check out Google’s documentation.

While I was reading through some of Google’s documentation on event handling via the gtag.js scripts, I couldn’t help but notice some differences in how they treat examples depending on the set of document pages you’re visiting. These differences I feel could cause some confusion when attempting to implement a dual tracking scenario.  As well, there’s also a key parameter that is missing from these examples, and general mention on the document pages that I feel is a cornerstone to dual deploying properly, and I wish would’ve been called out more in the document pages.  For that reason I wanted to write a quick article on how I would recommend deploying events via the gtag.js direct deployment scripts.

Working with a basic gtag.js deployment

Before I jump into the event portion of this article, let’s just quickly review the (very) basics of a gtag.js deployment via your site code.

Config Script

The first thing you’ll need to do is include your configuration script in the <head> of your page, and preferably as high in the head as you can.  The script below will set up the connection for your eventing to the Universal Analytics property UA-11111111-2.  By default, implementing the config script will enable page view tracking at page load.  This is a setting that if you’d rather control manually you can specify in the config script as well, but for the sake of simplicity, lets just fire it off automatically in our examples:

<script async src=”″></script>


  window.dataLayer = window.dataLayer || [];

  function gtag(){dataLayer.push(arguments);}

  gtag(‘js’, new Date());

  gtag(‘config’, ‘UA-11111111-2’);


Modify the config script for GA4 dual deployment

The only addition you’ll need to make to the config script, to start tracking to a GA4 property is, the addition of a second gtag(‘config’) method, referencing the GA4 property to report to.

<script async src=”″></script>


  window.dataLayer = window.dataLayer || [];

  function gtag(){dataLayer.push(arguments);}

  gtag(‘js’, new Date());

  gtag(‘config’, ‘UA-11111111-2’);

  gtag(‘config’, ‘G-ABCDE12345’);


If we were to add this to a live site, we’d now be seeing page view tracking to our GUA property, as well as Page view tracking to our GA4 property (and, if enabled any Enhanced measurement events).

Adding Custom Dimensions and Metrics

To collect custom dimensions and metrics, for your GUA tracking, you’ll need to tweak the config script slightly, to include a custom_map object.

<script async src=”″></script>


  window.dataLayer = window.dataLayer || [];

  function gtag(){dataLayer.push(arguments);}

  gtag(‘js’, new Date());

  gtag(‘config’, ‘UA-11111111-2’, {

    ‘custom_map’: {

      ‘dimension1’: ‘method’



  gtag(‘config’, ‘G-ABCDE12345’);


Notice that this is something we only need to set for our GUA configuration, not our GA4 configuration.

This is because, with GA4 tracking, dimension and metric indexing is no longer needed.  I don’t need to tell my GA4 tracking to “collect a method parameter on the cd1 index”.  So, when we include the custom dimension in our eventing, like this:

    gtag(‘event’, ‘<action>’, {

      ‘event_category’ : ‘<category>’,

      ‘event_label’ : ‘<label>’,

      ‘method’: ‘<dimension1 value>’


While our GUA tagging will see ‘method’ and use the custom_map object to associate this key/value pairing to custom dimension 1, GA4 simply sends the <dimension1 value> to an event parameter named ‘method’. 

With all of that, we’re now ready to jump in to the primary topic of this article which is:

How to properly implement events for Dual Deployment

First let me reference two examples from different Google Documentation pages, surrounding gtag.js event tracking, and address some of – what I feel – are limitations in the examples provided if being used for dual deployment.

Example 1

gtag(‘event’, <action>, {

  ‘event_category’: <category>,

  ‘event_label’: <label>,

  ‘value’: <value>



If deploying for either GUA OR GA4, this is a perfectly fine method to use, as is.

In the case of this script, rather than define a unique key/value pair for event action, as we see for category and label, the <action> parameter on the gtag function will be treated as the event action, meaning if we were to send this event to GUA:

The resulting collect hit sent out to GUA, would be:

Perfectly fine!  

But, once we add our GA4 property to our configuration file, we’ll also be sending an event to GA4 that looks like this:

The breakdown occurs on the event name.

Google recommends that for login events, the event name (for GA4) = ‘login’.

While you don’t HAVE to track your login events this way, there are REQUIRED event names for some of our events, the first ones that pop into mind being for ecommerce events.  We cannot name them differently than Google has specified.  In the case of recommended events (like login), you could absolutely track it differently from the recommendations as Login Success, but you may miss out on some reporting capabilities if you do so.

At the very least, even if Google doesn’t have required or recommended events for what you’re trying to track, the event name for our event of ‘Login Success’ doesn’t meet the general event name structure laid out by our recommended and required event names for GA4 – these mostly follow an all lowercase, snake case format: something_like_this

For more information on recommended events, visit Google’s documentation.

Example 1 conclusion:

The limitation to implementing this single event script for both our GUA and GA4 event is that they may not always be able to share that <action> value for how each tracking type uses it. We shouldn’t always assume that our GUA event action will equal our GA4 event name.

Example 2

From Google’s documentation:

“Imagine that you send the following custom event in analytics.js:

ga(‘send’, ‘event’, ‘myCustomEvent’, ‘myEventAction1’, ‘myEventLabel1’);

or, using a slightly different syntax:

ga(‘send’, {

 hitType: ‘event’,

 eventCategory: ‘myCustomEvent’,

 eventAction: ‘myEventAction1’,

 eventLabel: ‘myEventLabel1’


Since myCustomEvent does not correspond to an automatic, Enhanced Measurement, or recommended event, you would trigger it as follows in gtag.js:

gtag(‘event’, ‘myCustomEvent’, {

  “TheEventAction”: “myEventAction1”,

  “TheEventLabel” : “myEventLabel1”



With this example, there are a couple of limitations that I can see to utilizing this for a dual deployment (or even just a GA4 only deployment).

To start, this seems to suggest for this event that we should map our event category as the <action> value on the GA4 event.  Right away, some differences in how we should/could treat mapping the equivalent GUA event to a GA4 event between Example 1 and Example 2.

Second, though I know it’s just an example… “TheEventAction” and “TheEventLabel” are just badly named event parameters to send to GA4, and are not parameters that will automatically be associated with event action or event label if we’re trying to use a single script to deploy to both reporting types.  GUA won’t know what to do with these.  If we recall back to example one, event_category, and event_label were shown in the event snippet, and these are automatically picked up by GUA tagging (and alludes to where I’m going with my recommended event method).

To highlight, let’s use this example to fire our login event:

The resulting GUA hit looks like this:

Because we’ve mapped ‘event category’ to <action>, and don’t define the recognized event_category key, gtag.js, doesn’t know what to populate in ‘ec’, and thus falls back to the auto defined value of ‘general’.  As well, because it doesn’t know that ‘TheEventLabel’ should be mapped to el, no el parameter is assigned to the collect hit to pass ‘Google’.

And then for GA4:

While we’re able to pass an event name (based on category) and ‘TheEventAction’ and ‘TheEventLabel’, we can see that en (event_name) isn’t using the recommended event name for ‘login’, nor is what’s being used close to identifying it as a login event, because category contained a more generalized category value.  Further, while Action and Label are passed, again, not on the greatest event parameter names.


The real limitation here lies in that the event parameters that have been named in our GA4 event aren’t something that will map automatically to our GUA tagging if trying to configure a single event to work with both solutions.  For GA4 they’re just badly named, for GUA, it won’t know what to do with them.

Further, if the goal of the example is simply to show how a GUA event would map in a GA4 property, keep in mind that if you’re deploying to GA4 only (at this point you shouldn’t be, but just in case), event parameters like category and action aren’t requirements anymore, so you could just exclude entirely from your eventing.  It really depends on the approach you’ll take to event tracking with this new tracking method.

As well, I certainly feel, referencing category as the <action> here is confusing, particularly if you do have GUA and GA4 deployed via gtag.js… as you’re going to see your category value, showing up in your action value in your event if you use this approach.

Finally this brings me to my recommendation.

How to script out your GUA and GA4 events via gtag.js in a single script

Some of you may have already known where I was going with this based on event_category, and event_label being captured on my GUA tagging automatically.

The simple solution: add an event_action key to your events, like this:

While it’s not referenced in the examples themselves, or on the gtag.js page where the example from Example 1 is shown, it is referenced here as part of the gtag.js fields, for reference.

Like event_category, and event_label, it is automatically mapped to your eventing in GUA, and doesn’t interfere with the <action> (event name), in your GA4 tagging.  This means, for the login script shown above, my GUA collect hit would look like this:

Where event_action (Login Success) will override the event <action> (login).

And my GA4 event would look like this:

Where, the event name (en) parameter captures the <action> value of ‘login’.

We now have a single script that can be used to meet each tracking model’s needs without sacrificing one way or the other.


While the examples I’ve provided in this document are both completely usable in tracking to GUA and/or GA4, using them as is, to implement tracking across both solutions, means that you might be sacrificing data quality as it pertains to that particular reporting type in one of the two solutions.

There are certainly other ways out there to define these gtag event methods to ONLY send to either GA4 or GUA (see the send_to parameter), allowing you to uniquely define the event calls to each in separate scripts.  As well, if you’re looking at updating your direct deployment for GUA using the analytics.js library, you may be opting to just leave those scripts as is, and deploy gtag.js solely for your GA4 tracking.

In either of these cases, it does mean you’re maintaining separate sets of code to do the same thing for each reporting type, which can lead to inconsistencies, and code bloat on your site.  As dual deploying GA4 with GUA is still very much recommended, being able to do so in a manner that ensures you can use a single script to control eventing to both solutions will ensure closer alignment between the events – reducing the risk of them falling out of sync, as well as keep your onsite code as light as possible.

From advice on when is the right time for GA4 for your business, to help in determining what changes need to be made to your current measurement setup, to deploying the GA4 property, and everything in between and beyond, Napkyn can assist with every step of your GA4 journey. Contact us to speak to an expert.

Rob English

Analytics Implementation Specialist

Analytics Implementation Specialist proficient in the use of Javascript and tag management platforms such as Google Tag Manager and TealiumIQ to build out custom tagging/tracking solutions. Google Analytics certified. Experienced in front end design and development.

See more posts from Rob