Global Site Tag (gtag.js) Event Tracking

Manage multiple GA/GA4 properties with gtag.js. Learn config, groups, send_to, and event parameter differences.

Ceyhun Enki Aksan
Ceyhun Enki Aksan Entrepreneur, Maker

TL;DR

gtag.js lets you manage multiple GA/GA4 properties in a single snippet. Use config for property setup, groups for grouping, and send_to for targeting.

FunctionUsageExample
configProperty setupgtag('config', 'GA_ID')
groupsProperty groupinggroups: 'access'
send_toEvent targetingsend_to: ['default', 'group_1']
eventSend eventsgtag('event', 'login', {...})

Critical: GA and GA4 event parameters differ. Use parameters from both versions to support both.


Considering there will be more structural changes on the GTM side going forward, I recommend migrating your existing analytics.js1 and ecommerce.js2 configurations directly into GTM. Given that some stacks still rely on ga.js3 and ec.js4, moving to a more flexible, maintainable setup is a better long-term strategy than constantly patching and rebuilding.

tip

You can request Google Analytics support via this support link.

Of course, things are not always this straightforward. For example, a few of the e-commerce products I advise use off-the-shelf platforms (especially local solutions) that lag behind, so you often need to work within the constraints they provide.

In this post on Global Site Tag (gtag.js) Event Tracking, I’ll outline what changed for event and e-commerce setups with gtag.js and what to consider when migrating from analytics.js and ecommerce.js.

warning

As of July 2023, Universal Analytics (UA) has been replaced by Google Analytics 4 (GA4). From this date forward, UA properties no longer process new data.

Global Site Tag (gtag.js) Event Tracking

In the post on the Global Site Tag (gtag.js), I mentioned that both Google Ads and Google Analytics can be initialized via the config parameter (global snippet). For details, refer to that post. Event handling in Global Site Tag (gtag.js) follows the same approach. This makes it easy to define multiple sites (not necessarily subdomains) and multiple Analytics and Ads properties in a single snippet with separate cookie namespaces.

gtag('config', 'GA_TRACKING_ID', {
  'send_page_view': false
});
gtag('config', 'GA_TRACKING_ID_2');
gtag('config', 'GA_TRACKING_ID_3');

For example, the code above disables page_view tracking for the property GA_TRACKING_ID, while the other properties GA_TRACKING_ID_2 and GA_TRACKING_ID_3 continue to receive pageview hits normally. This capability also brings grouping into play5. When migrating from a Google Analytics property to a Google Analytics 4 (GA4) property, you simply provide the GA4 GA_TRACKING_ID in the config call.

By default, the snippet processes properties under the built-in group named default. To set the group explicitly:

gtag('config', 'GA_TRACKING_ID_1', {
  groups: 'default'
});
gtag('config', 'GA_TRACKING_ID_2', {
  groups: 'default'
});

If you assign a custom group name via the groups parameter:

gtag('config', 'GA_TRACKING_ID_1', {
  groups: 'access'
});
gtag('config', 'GA_TRACKING_ID_2', {
  groups: 'access'
});

These property IDs are now under the access group. Grouping lets you direct event data to specific groups and the property IDs assigned to them.

Google Analytics Events
Google Analytics Events

Sending Events

Google Analytics surfaces the events we send (event objects) in the Events reports as Category, Action, Label, and Value. We structure our payloads accordingly. E-commerce events and goal definitions follow the same logic. However, some events require a specific trigger (view, click, submit, etc.) to fire. We use the event_name to associate event names with these triggers. Therefore, I recommend following a consistent naming pattern and purpose.

gtag('event', 'event_name', {
  send_to: 'access',
  parameter_1: 'value_1',
  parameter_2: 'value_2',
  // ...
});

GA4 now includes automatically-collected events6:

  • language
  • page_location
  • page_referrer
  • page_title
  • screen_resolution

This allows frequently performed user actions to flow directly into the Events report. However, GA4 handles events somewhat differently. I’ll share the details below.

Google Analytics 4 Events
Google Analytics 4 Events

For example, this event will interact with the access group. If send_to is not specified with a custom group, events will be sent to the default group. For events targeting multiple groups:

// Code structure
gtag('event', 'event_name', {
  send_to: ['group_name_1', 'group_name_2', ... ],
  parameter_1: 'value_1',
  parameter_2: 'value_2',
  // ...
});

// GA4
gtag('event', 'myCustomEvent', {
  TheEventAction: "myEventAction1",
  TheEventLabel : "myEventLabel1"
});

As you can see, GA and GA4 events have different parameters and scopes. Therefore, if you’re defining events for both versions, you need to use both parameter sets together. Otherwise, events from one version won’t appear in the other’s reports.

// GA - Sending page view separately
gtag('config', 'GA_MEASUREMENT_ID', {
  'page_title' : 'homepage',
  'page_path': '/home'
});

// GA - Disabling automatic page view
gtag('config', 'GA_MEASUREMENT_ID', {
  send_page_view: false
});

// GA - Sending page view as an event
gtag('event', 'page_view', {
  page_title: '<Page Title>',
  page_location: '<Page Location>',
  page_path: '<Page Path>',
  send_to: '<GA_MEASUREMENT_ID>'
});

Event anatomy parameters for GA:

NameParameterStatus
Categoryevent_categoryRequired
Actionevent_actionRequired
Labelevent_labelRecommended
ValuevalueOptional

Event anatomy parameters for GA4:

NameParameterStatus
ActionTheEventActionRequired
LabelTheEventLabelRequired

With gtag.js events, you can use predefined categories (ecommerce, engagement), events, and parameters following the event anatomy. For example, the “login” event operates under the engagement category with the method event label.

gtag('event', 'login');

Looking directly at event structures:

// GA
gtag('event', 'login', {
  event_category: 'engagement',
  event_label: 'Google'
});

// GA4
gtag('event', 'login', {
  TheEventAction: "engagement",
  TheEventLabel : "Google"
});

For custom structures where you don’t want to use recommended parameters7:

// GA
gtag('event', 'event_name', {
  // event parameters
  parameter_1: 'value_1',
  parameter_2: 'value_2',
  // ...
});

// GA4
gtag('event', 'myCustomEvent', {
  TheEventAction: "myEventAction1",
  TheEventLabel: "myEventLabel1"
});

To send the login event to multiple groups:

gtag('event', 'login', {
  send_to: ['default', 'group_1', 'group_2'],
  method: 'Google'
});

Grouping, global snippet, property-scoped event handling, and recommended events are just a few features of gtag.js.

Property and Event Flow Separation

Even when everything looks correct in the code, you might still experience issues with data flow. There are several possible reasons for this.

Automatic Property Migration

When Universal Analytics was replaced by Google Analytics 4, you likely saw a notification on your page. If property migration wasn’t completed by the specified date, the migration was automatically performed as planned. However, this process caused configuration issues in some properties. While G- and GT- are the most common measurement ID prefixes for GA4 property config, in some cases we’ve also seen MC- and AW- appear based on the UA property’s relationships with other properties.

This creates a separation between config and event targeting. While config fundamentally covers the tracking library and configuration, event targeting may require a different property definition handled via send_to. This situation resembles the Misconfiguration issue described below.

Misconfiguration

You can create a Google Analytics 4 property through various applications and connections. Merchant Center and Google Ads are the most common examples. In this linked structure, sometimes the Google Analytics 4 configuration is set up as the target property to receive data from another property. That is, while the actual data source is Google Ads, Google Analytics 4 is added as the destination and data is acquired through Google Ads. In such cases, config handles Google Ads while data (external event data, etc.) needs to be sent separately via send_to. This is because event data sent to Google Ads may differ from data sent to Google Analytics 4.

If you frequently see page views and other automatically-collected events in your Google Analytics 4 event reports but ecommerce and other custom event data aren’t appearing, the likely cause is the inter-property data transfer issue described in this section.

Sandbox Limitations

If you’re using Shopify Pixel, you might encounter several situations simultaneously. First, you may have experienced issues during the Universal Analytics to GA4 transition; see: Automatic Property Migration. Second, if you created Google Ads through the Google & Youtube app and performed property operations automatically, properties may have been linked to each other as targets; see: Misconfiguration. Finally, pixels by design operate in sandbox mode. At the loading stage and afterward, initial data is obtained via page_viewed (at minimum). If the setup script isn’t loading in page flows and/or if config is delayed (due to various checks, etc.), event data won’t know where to go. In such cases, using send_to for each event will prevent flow problems that might otherwise occur.


Frequently Asked Questions (FAQ)

How to manage multiple GA properties with gtag.js?

Make separate config calls for each property:

gtag('config', 'GA_TRACKING_ID_1', { groups: 'access' });
gtag('config', 'GA_TRACKING_ID_2', { groups: 'access' });

Use send_to to direct events to specific groups.

What’s the difference between GA and GA4 event parameters?

VersionParameters
GA (UA)event_category, event_action, event_label, value
GA4TheEventAction, TheEventLabel

Use parameters from both versions to support both.

What does the send_to parameter do?

Used to direct event data to specific properties or groups:

gtag('event', 'purchase', {
  send_to: ['default', 'group_ads'],
  value: 150
});

If not specified, events are sent to the default group.

Does automatic GA4 migration cause data loss?

Mismatches between config and event targets can occur during automatic property migration. Different measurement ID prefixes like G-, GT-, MC-, AW- may get mixed up. Using send_to for each event prevents this issue.

What to consider when using gtag.js with Shopify Pixel?

  1. Sandbox limitations: Pixels operate in sandbox mode by design
  2. Automatic property migration: Config issues may occur during UA → GA4 transition
  3. Misconfiguration: Google Ads and GA4 property associations may conflict

Explicitly specify send_to for each event.


Summary: Key Takeaways

  1. config for property setup, groups for grouping, send_to for targeting
  2. GA parameters: event_category, event_action, event_label, value
  3. GA4 parameters: TheEventAction, TheEventLabel
  4. Use parameters from both versions together
  5. Use explicit send_to targeting for data flow issues

Footnotes

  1. Add analytics.js to Your Site. Google Analytics
  2. Ecommerce Measurement. Google Analytics
  3. Introduction to ga.js (Legacy). Google Analytics
  4. Tag your property with the ec.js plugin. Analytics Help
  5. Send data to Google Analytics with gtag.js. Google Analytics
  6. Automatically collected events
  7. Measure Google Analytics Events. Google Analytics