Google Analytics 4 Ecommerce Tracking Part 3: Checkout Tagging

by Rob English

How to deploy your GA4 tags, using your Universal Analytics dataLayer schema

It’s been a busy few months, and this post is looong overdue.  By now there are many resources on ecommerce implementation for GA4, but I wanted to finish up this series of posts regardless.  So, welcome to Part 3 of Tagging for Ecommerce eventing in GA4.  Just to quickly recap:

In part 1 – we focused on all of our pre checkout eventing

In part 2 – we focused on our purchase eventing

Now, in Part 3, we’re going to focus on our Checkout eventing.

Article Breakdown:

Why have I chosen to focus on Checkout tracking last?

To start, it probably seems a little strange that Checkout tracking is the one I focus on last, rather than going in a more “chronological” order of Pre-checkout > Checkout > Purchase, but the reason I’ve done this is really due to the difference in checkout tracking between Universal Analytics (GUA) and GA4.  Of all the ecommerce tracking, checkout is really where we start to see eventing handled differently between the two tools.

What’s different about the Checkout events?

When we think of Universal Analytics and checkout tracking we think of, a checkout event firing on each of our checkout steps, tracking that particular checkout step, and then we could also have checkout_option events that further enrich our checkout tracking, step by step, after the user has made certain selections (think shipping tiers, or payment methods).  See the below table for an example of how eventing differs between the two sets of tracking now (keep in mind the comparison is only using what we’d have available to us in our GUA dataLayer as we translate to GA4, not what’s available for use in GA4, as I’m addressing this with my dataLayer “as-is”).  The event breakdown in this table is also the flow of the checkout steps I’ll be working with to build out my new GA4 tracking.

Understanding Checkout Flow with GUA and GA4

** Where we identify unique checkout steps in GUA via the actionField.steps variable we now identify them by unique event_names in GA4

* Where we only pass the products array on checkout steps in GUA (and really only need to pass it on Step 1), and not on checkout _option events,we can pass this array on the add_shipping_info and add_payment_info steps equivalent steps in GA4

Building out our Checkout tracking elements in GTM

So, with all of that said, how do we go about actually tweaking our existing GTM implementation for GUA, to dual deploy our checkout in GA4?

We’ll break this down into two sections:

  • Capturing Checkout Step 1 – begin_checkout event
  • Capturing checkout_options for add_payment_info and add_shipping_info 

Capture Checkout Step 1 – begin_checkout

First, let’s create the variables we’re going to need to map to our new begin_checkout event tag.

Go to Variables > New > Data Layer Variable

Let’s go ahead and name the variable Data Layer – ecommerce.checkout.actionField.step

Then, in the Data Layer Variable Name enter:

ecommerce.checkout.actionField.step

Click Save

Let’s quickly check on-page to make sure this is capturing the expected value.

Enable GTM Preview, then move over to our site, and trigger Checkout Step 1 in the dataLayer.

In my GTM Preview tab, select the ‘checkout’ event for checkout step 1 > Variables.  I can see it’s capturing ‘1’.  So far so good.

I’m going to trigger a couple more checkout events, to make sure it’s accurately capturing the differing step values.

When I trigger Step 2, I see the value change to ‘2’

And the same for step 3 – I get 3 – and for 4, I get 4 ( I won’t bore you with screen caps of every one of these steps).

This is capturing exactly what I want it to capture.

Now, let’s create a new checkout trigger for the begin_checkout event.

We’ll make a copy of the existing checkout trigger that I’m using for my GUA tagging, as the core of it will be exactly the same.

My GUA trigger looks like this:

I’ll copy it and name my copy Custom Event – ecommerce – checkout step 1

Then, I’m going to map my newly created Data Layer – ecommerce.checkout.actionField.step variable as an additional firing parameter, under ‘This tag fires on’

So that I now have a trigger that looks like:

Then, I’ll create a data layer variable to capture my ecommerce.checkout.products array from my checkout steps.

To do this, I’ll go to Variables > New > Data Layer variable

Let’s name this variable Data Layer – ecommerce.checkout.products

And then, in the Data Layer Variable Name field we’ll enter

ecommerce.checkout.products

Click Save.

Again, let’s Preview this before we move any further to make sure we’re getting the expected products array during our checkout events.

Hit the preview button to relaunch GTM Preview, and jump over to our site.

Trigger a checkout event, and under our GTM preview tab, navigate to our ‘checkout’ event >  Variables.  We can see that our Data Layer – ecommerce.checkout.products variable is capturing product data.  

Now, we have everything we need to go ahead and create our Checkout tag.

Building the begin_checkout event tag

Under Tags > New > Select the Google Analytics : GA4 Event tag template

I’m going to name this tag GA4 – Begin Checkout.

Under the Configuration Tag, select our GA4 configuration tag that’s being used across all of our other ecommerce event tags.

And then, Under Event Name enter:

begin_checkout

This is the Google defined event name for our first checkout step now, so this HAS to be this value.

Under Event parameters, add a new Parameter Name for: items

with a value that points to our newly created Data Layer – ecommerce.checkout.products variable

We’ll also map our Data Layer – ecommerce.currencyCode variable to a currency parameter.

If you’ve already read through my last post on dual deploying for purchase events, you’ll probably have already created this variable.  If you haven’t though, I’d recommend giving it a read.

And, finally let’s add our new Custom Event – ecommerce – checkout step 1 trigger to the Triggering section of this tag.

Our finished tag will look something like this:

Click Save

Again, let’s relaunch our Preview window, and jump back to our site to see what’s happening now

This time, we’ll also want to open up our Network tab (or another tag testing tool like WASP, GA/GTM Debugger), and enter collect in the search bar, so that we can see the GA collect hits being generated from our events.

I’ll trigger my checkout step 1 event

And in Network, I can now see that in addition to my GUA hit:

I’m also getting my GA4 hit

Just to highlight our triggering conditions I’ll also trigger checkout step 2, to show  that we get our GUA Step 2 hit, but nothing (as expected) for our GA4 tagging.

And as I navigate through the rest of the checkout, same thing.  No additional checkout events firing off of my GA4 tag.

Great!  So from the implementation side, all looks good for our begin_checkout event, let’s move on to capturing our checkout_option events.

Capturing checkout_options for add_payment_info and add_shipping_info

We’ll need to capture our checkout_option events as the GA4 events add_payment_info and add_shipping_info.  My checkout implementation already has the equivalent checkout_option events that we’ll be translating, but if you don’t have them, this is where you may lose out on some of your checkout tracking.  You’ll need to work with a developer to place these checkout_option events (if you want to enable them in GUA), or place the actual GA4 events for add_shipping_info, and add_payment_info to only capture in GA4, or build out some additional elements in GTM to capture.

With regards to my existing checkout pages/events I need to capture the checkout_option event for Step 2 – Shipping Info, and for Step 3 – Payment Info.

First we’ll create some of the variables and triggers that we’ll need to support our new tags.

Create a variable to capture the ecommerce.checkout_option.actionField.option field

This is going to capture the value that will get passed into our GA4 shipping_tier, and payment_type parameters on our add_shipping_info, and add_payment_info events.  This is the field that allows us to find out which option, on each of these steps the user selected (ie. Standard Shipping, Express Shipping, Visa, MasterCard, Debit, etc.)

In our variable, under the Data Layer Variable Name field, enter

ecommerce.checkout_option.actionField.option

Check the “Set Default Value” field, and then in the Default Value, I’ve mapped to my undefined value variable, which will consistently capture undefined (in non-string format), when no value is set.

Next I’ll create triggers for my Step 2 and 3 checkout_option events.

For my checkout option events, I already have a checkoutOption trigger that I could use, and I could absolutely create one tag to work with both of my add_shipping_info and add_payment_info events, but to better explain setting up my tagging for each individual instance, and, also to remove the risk of other checkoutOption events that I might have in my checkout getting captured in my GA4 eventing, I’m going to create two new custom triggers targeted to each of my GA4 checkout events.

For my Step 2 checkoutOption event trigger, I should have:

Trigger Type: Custom Event

Event name: checkoutOption

Additional conditions of:

Data Layer – ecommerce.checkout.actionField.step = 2

And for my Step 3 checkoutOption event trigger, I have:

Trigger Type: Custom Event

Event name: checkoutOption

Additional conditions of:

Data Layer – ecommerce.checkout.actionField.step = 3

Now I’m ready to set up my tags for these events.

add_shipping_info Tag

Make sure to map our GA4 – Config tag to the Configuration tag field, and then under Event Name, we’ll add add_shipping_info.  This event name has to match up exactly as this is a required event name for ecommerce tracking on the shipping info step.

Next, we’ll map our Event parameters. As we did with our begin_checkout event,  we can reuse the Data Layer – ecommerce.checkout.products variable we created earlier.

Same for the currency parameter – we can reuse the Data Layer – ecommerce.currencyCode variable we created earlier too.

For this event, we’ll create a ship

ping_tier parameter, and we’re going to map our newly created Data Layer variable that points to the checkout_option.actionField.option key in our dataLayer.

shipping_tier is one of Google’s GA4 recommended event parameters for this event, and it will capture the shipping selection that we’d normally send in our Universal Analytics option field.

And then, finally, we’ll add our newly created trigger  Custom Event – ecommerce – checkoutOption – Step 2 trigger to our Triggering section of the tag.

The final tag should look like this:

add_payment_info Tag

Because both this tag, and our add_shipping_info tag are so similar, I’m going to copy our GA4 – Add Shipping Info tag

Rename to GA4 – Add Payment Info

Modify the Event Name to add_payment_info

And then modify our shipping_tier Event Parameter Name to be payment_type.  We can leave the variable value as is, because payment_type will also pull from the same actionField.option key, that our shipping_tier value was coming from.

And then finally, lets change up the trigger on our tag to point to the Custom Event – ecommerce – checkoutOption – Step 3 trigger.

That’s it.

Now that we’ve got our new tags setup, let’s go back to our site, and have a look at what they’re sending.

As we saw previously when we work through our checkout flow, when I trigger checkout step 1 in Universal Analytics, I’m also triggering begin_checkout in GA4, complete with my items array, and currency code. (again, as we’ve highlighted this earlier, I won’t bore you with screen caps of those test cases again)

As I move through Step 2, I still only have my GUA step 2 hit.

And, now, on completion of Checkout Step 2, when my Checkout Option event fires for Step 2, I get the checkout_option event firing for Universal Analytics.  Note the value in our col parameter, of standard shipping.  This was my shipping tier selection on Checkout step 2.

And then I also see the add_shipping_info event for GA4, complete with our products array, currency code, and our shipping tier event parameter containing the shipping level I selected on my order (standard shipping).

For step 3, we only get our Universal Analytics hit, as expected.

And then, for Checkout Option on Step 3 (Payment info) we can see our checkout_option event getting sent to Universal Analytics.

Again note the col parameter contains the credit card type I selected.

And we also see the add_payment_info event getting sent to GA4, complete with our currency code, our products array, and an additional event parameter of payment_type that captures the value of our actionField.options key.

And then as we progress through the rest of the checkout, we get our GUA checkout events, and no additional checkout_option, or GA4 events.

Checking our Data

Now that I’ve got my eventing in place, and we’ve verified the data is getting sent out as we expect, let’s make sure it’s being collected in GA4 as we expect.

Prior to the screens I’ve included in this section, I ran two test runs through my checkout:

  1. I completed a transaction, so triggered all of my checkout and checkout option events
  2. I dropped out of the checkout at Checkout Step 3

The first thing I did was add a Checkouts column, under Values to my existing ‘product performance’ report that I created, and have been using throughout these posts.

We can see that for my chosen date range that there were two instances of Checkout for Item 2, and one purchase.  This lines up with the test cases I triggered, but it doesn’t really give me any insight into where in the checkout the customer may have dropped off.

For that, I decided to just quickly set up a custom Funnel Report for my Checkout, to try and mirror what the Checkout Behaviour Report in GUA looks like.

This is really a very basic Funnel setup to ensure my events are working as I would expect, so there’s nothing super fancy about it.

I’ve defined steps for my funnel as:

I want to see customer progression through my checkout steps to purchase.  I’ve chosen to set each as being ‘directly followed by’, but could’ve also selected ‘indirectly followed by’ for these test cases, as it’s a test page, and the events I triggered all happened one directly after the other.  

When I apply my funnel settings, I get something like this.

Which looks right to me when considering my test cases.

One user who completed the checkout in its entirety and made a purchase

One user who dropped off at Step 3 (After my Shipping Info event, but before my Payment Info event).

For comparison, here’s my Checkout Behaviour Analysis funnel in GUA for the same sessions / events.

Looks to line up exactly as I would’ve expected.  Two users landed on Checkout Steps 1-3, and one user dropped off before Step 4.  One purchase was made.

How will this impact tracking?

While it may look a bit concerning to see far fewer events being captured in our checkout, the more I think about it the more I feel like it’ll definitely have some benefits.

Speaking strictly from the implementation side, many times while working on implementation for checkouts, we’ve run into the scenario of users being taken off site for some of the checkout steps. This makes it difficult or impossible to place those checkout steps at all, on the actual page they’re relevant to.  With this new set of events, I feel like it’ll be far easier to capture the add_payment_info, or add_shipping_info step in these cases, as the user returns to the site to complete the checkout.  As well, I feel like it’s more flexible when considering websites with multiple, differing  checkout flows (ie. user signed in vs. signed out), as now we capture just the users entry into the checkout funnel, and some key actions that happen within it (and usually within any checkout).

In discussing the new approach to checkout tracking with other members of the implementation team here, one possibility that was raised was, you could add your own GA4 custom events to fill in the checkout steps beyond step 1 if you really wanted to, but be cautious doing this, as these won’t be considered ecommerce events as begin_checkout, add_shipping_info and add_payment_info will be.  You won’t be able to send product info, or track any of the ecommerce data on them, like with the recognized ecommerce events.

Conclusion

With these posts I really wanted to highlight how you can leverage the dataLayer object you may already have to enable Ecommerce tracking with GA4, and some of the pain points or gaps that may pop up along the way.  While these posts will help you to get up and running with ecommerce tracking in GA4 quickly, with no dataLayer rework, be mindful, that if used, this should really only be one step along the path to GA4 enablement for ecommerce.   

While this approaches a dual deployment utilizing GA4s backwards compatible use of the GUA ecommerce object, it will become recommended to also deploy the GA4 modelled ecommerce object in tandem (as much as I hate redundancies in data collection like this…) at some point.  Let’s face it, chances of both GUA and GA4 being maintained indefinitely is highly unlikely.  If GUA is slated for retirement at some point in the future, and in preparation for whenever that may be, making sure that you have the proper underlying architecture in place for it – and not just pulling from what may be an outdated schema – is highly recommended, in anticipation for that switch.

These posts also don’t allow you to take full advantage of what’s available in the GA4 ecommerce objects either, or what capabilities may become available, only what you may already have available in your GUA ecommerce object.  While this gets you your data “as-is” in a manner that is fairly quick to deploy with low onsite development required, familiarizing yourself with the full capabilities of what GA4 can track is definitely recommended, as is auditing your current tracking to see what you can get and where gaps may occur in GA4, and what tracking you may need to rethink.

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