Tracking repeat customer performance in Google Analytics

UPDATE: To make your Shopify event tagging in Google Analytics even more robust and seamless, I highly recommend the Elevar service. They have a free plan to get you started on your Shopify eventing journey. Learn more >

You can’t unlock your super powers in Google Analytics until you are able to segment your site traffic in ways that will provide meaningful insights for your business. Having spent the past seven years in the startup scene for DTC brands, one of the most insightful segments I’ve applied to my GA reporting is a segment for existing customers. If you’ve been using the returning visitors segment in GA as a proxy for your existing customer behavior, I would implore you to use a better proxy! This guide should fit the bill nicely.

What follows is a step-by-step guide to how I’ve implemented this segment in GA. The intention here is not to capture and report on every existing customer that visits your site. The goal is to track a solid majority of them so that you are able to look at existing customer behavior in aggregate on your site. This is a fairly involved tutorial as we’ll be covering in depth how to use the tools that we need to make this tracking possible. In particular, if you are new to the world of Google Tag Manager, I hope this tutorial will serve as a great first introduction that will have you well on your way to leveraging its full power.

Our Tools:

  • Shopify (will also work with any ecom platform with source code access)
  • Google Tag Manager (GTM)
  • Google Analytics (GA)
  • js-cookie


First things first, let’s be sure we have a solid GA and GTM set up for Shopify. In GA, navigate to Admin > Property > Tracking Info > Tracking Code and copy the Global Site Tag (gtag.js). Now jump into Shopify and paste the code into the Google Analytics section under Preferences in the Shopify admin (Online Store > Preferences). After saving the code, you will see a link in this section to add custom javascript. Click the link and paste the following into the Additional Google Analytics JavaScript input:

new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],

Be sure to replace ‘GTM-XXXXXXX’ with your Google Tag Manager Container ID.


Now, let’s install the cookie library we’ll be using, js-cookie. You can download the library here. Click on the Raw button and then save the page from the browser as cookie.js. Upload this file to the Assets folder in Shopify and include the following code towards the bottom of the theme.liquid file (before the closing </body> tag).

{{ 'cookie.js' | asset_url | script_tag }}

That will insure our cookie library is available for us to call on every page except checkout and the thank you page after ordering. We’ll now go ahead and make sure this library is available for us to use on the thank you page. Since we do not have access to the source code for the thank you page in Shopify, we’ll need to use GTM to inject our cookie library code into the thank you page when it loads.

At a minimum, there are two components required to fire a tag in GTM: The tag itself and a trigger that fires the tag. In this case, those are the only two components needed to get our cookie library to load on the thank you page. To start with, we’ll create the tag. Under the Tag section, click New and name your tag (let’s call it cookie.js). Click into the Tag Configuration area and select the Custom HTML tag type. 

You are going to copy and paste the contents of your local version of cookie.js into the HTML field, but first you need to put an opening and closing tag into the HTML field and then paste your code. Here’s what your screen will look like with the tags added:

Now go ahead and paste the contents of your cookies.js file in between the tags. Your screen should now look like the following:

All that’s missing now is a trigger to fire this tag. Click the area on the tag called Triggering and click the + sign to create a new trigger. Let’s name the trigger Thank You Page Trigger. Select the Page View trigger type, click on Some Page Views and select Page URL for the event type and enter /checkouts/ and then thank_you in an additional Page URL event type field. We need two event types to describe the thank you page because the structure of the URL looks like:

Your configuration should like the following:

Now save your changes and you’re done. If this is your first GTM tag, congrats! You now have a tag that will fire on the thank you page after checkout.


There will be three cookies to set for our tracking purposes:

RETURNING_CUSTOMER : This cookie will be set when an existing customer returns to the site.

COMPLETED_CHECKOUT : This cookie will be set after a customer places a first order.

FIRST_TRACKED_ORDER : This is a temporary cookie that will also be set after a customer places a first order. It will help us avoid including first time customers as existing customers in our analytics. More on this later.

Now, we’re ready to begin cookie-ing our customers. the first place we’ll do so is right after they place a first order. Let’s create a new tag called Thank You Page – Set Cookies in GTM. We will use the Custom HTML tag type again and include the following code:

   (function() {
       // check if user is first time thru checkout
       if (!Cookies.get('RETURNING_CUSTOMER')) {
          Cookies.set('FIRST_TRACKED_ORDER', '1', {expires: 1});
          Cookies.set('COMPLETED_CHECKOUT', '1');

Our trigger is the same as before, when a customer lands on the thank you page, so assign this tag the Thank You Page Trigger. This code first looks to see if there is already a cookie that has been set for an existing customer. If not, then the code sets two cookies: FIRST_TRACKED_ORDER, which is set to expire in 1 day, and COMPLETED_CHECKOUT. The reason why we include the first cookie and have it expire in a day will become apparent in the next step.

We will now create a snippet that we can include in our theme.liquid file in Shopify. This snippet will contain the logic for identifying returning customers. This snippet should be included towards the bottom of your file inside the closing body tag:

   // not 'FIRST_TRACKED_ORDER'   

   if (!Cookies.get('RETURNING_CUSTOMER')) {    	
      if (!Cookies.get('FIRST_TRACKED_ORDER') &&
      Cookies.get('COMPLETED_CHECKOUT')) {
         Cookies.set('RETURNING_CUSTOMER', '1');     	

Here we can see that we will not set the RETURNING_CUSTOMER cookie if the FIRST_TRACKED_ORDER cookie is present. This prevents us from including these first time customers as existing customers if they continue to browse the site right after they place their first order. Depending on the type of good you sell and the typical delivery time, you may want to adjust the 1 day value to the number of days the customer waits before receiving a first purchase.


Our next step is to create the code that will inform GA that an existing customer is visiting the site. We will do this by pushing a variable into the GTM data layer that can be read by a GTM trigger that we’ll create. This trigger will then fire a GA Tag that we’ll set in GTM. Understanding the data layer can be a bit tricky but it is essentially just a javascript array initiated with code on your site. We then populate this container with variables to be read by GTM when certain events happen on your site. These variables in GTM can then be used to create triggers to fire tags for various services (in this case, we’ll be creating a GA tag to fire). If this isn’t entirely clear, following along with the example should help clarify the concepts involved. I have also posted some articles at the end of this post that have helped me better understand GTM.

We will begin populating the data layer by amending the snippet we just added to the theme.liquid file. Add the following code into the snippet just before the closing tag.

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

// if RETURNING_CUSTOMER cookie present, update data layer
if (Cookies.get('RETURNING_CUSTOMER')) {
window.dataLayer.push({'DL_RETURNING_CUSTOMER': 1});

This code first initializes the data layer and then checks to see whether there is a cookie called RETURNING_CUSTOMER. If there is, we push a variable into the data layer called DL_RETURNING_CUSTOMER and give it a value of 1. This code takes care of every page except for the thank you page. Let’s tackle that next!

Once again we’ll use our GTM implementation to create a tag that contains the code we want to execute on the thank you Page. The process starts off the same way as before with us creating a Custom HTML tag. Let’s name this new tag Thank You Page – Data Layer. The code is exactly the same as the code we used above to populate the data layer. We don’t need to worry about setting a cookie on the thank you page, so the whole script will just be:

<script type="text/javascript">
  (function() {
	  window.dataLayer = window.dataLayer || [];

      // if RETURNING_CUSTOMER cookie present, update data layer
      if (Cookies.get('RETURNING_CUSTOMER')) {    
         window.dataLayer.push({'DL_RETURNING_CUSTOMER': 1});  

The tag just needs a trigger now. If your inclination is to use the existing Thank You Page Trigger we created before, you are on the right track! We just need to make two adjustments. 

First, the thank you page on Shopify after submitting an order can be accessed by the customer at any time. Our code needs to fire once and once only to mark a conversion from an existing customer. If this customer reloads/revisits this page in a future session, we would accidentally count that page load as a new conversion, thereby inflating our existing customer conversion rate. We need a mechanism to ensure that our tag to populate the data layer on the thank you page fires once only. Fortunately, Shopify has our backs here.

If you’ve ever included conversion tags in the Additional Scripts area of the checkout settings in Shopify (Settings > Checkout), you might have noticed the following liquid code:

{% if first_time_accessed %} 


{% endif %}

This code ensures that whatever is executed inside will only be executed once. Here’s the code we will insert into the Additional Scripts area:

{% if first_time_accessed %} 

<p id="GTM-PURCHASE-TRIGGER" style="color:white">GTM</p>

{% endif %}

This code will insert an invisible paragraph block on the thank you page with an id=”GTM-PURCHASE-TRIGGER”. It’s this id that our Page View – DOM Ready trigger will use as a condition to fire. All that is left is to create a GTM variable to detect the presence of this id on the page and we’ll be ready to create the trigger for our new tag.

Navigate to the Variables section in GTM and click New under the User-Defined Variables area. Let’s name the variable GTM-PURCHASE-TRIGGER. In the menu, under the Page Elements section, select DOM Element. Choose ID as the Selection Method and paste in our ID (GTM-PURCHASE-TRIGGER) in the Element ID input. Your variable should look as follows:

Second, when we fire our code to populate the data layer, we need to be sure that the thank you page loads first before the new tag is loaded. We need to do this to ensure that our new tag can detect the presence of the ID found on the thank you page. We’ll do this by using a different trigger type with a slight delay. Let’s use the Page View – DOM Ready trigger type, which will fire once the DOM loads (which occurs after the initial page view).

Let’s go ahead and add the trigger. Select Page View – DOM Ready and name the trigger DOM Ready – Thank You Page. The conditions are the same as our previous thank you page trigger except we are adding the condition that the GTM-PURCHASE-TRIGGER variable cannot be null. You will see the variable listed as a choice in the dropdown when you add a new event condition. Then type null after selecting does not equal.


So now that we are populating the data layer with a variable to signify an existing customer visiting the site, what’s left? We have to let GA know about it! Here’s what we need to create to make that happen:

  • A GTM variable that will look for presence of the DL_RETURNING_CUSTOMER variable in the data layer
  • A custom dimension in GA to represent an existing customer 
  • A Google Analytics tag in GTM which we’ll use to assign data to our new custom dimension in GA
  • A trigger in GTM to fire the tag

When creating the new GTM variable, select Data Layer Variable as the Variable Type. For the section under Data Layer Variable Name, input DL_RETURNING_CUSTOMER. Your GTM Variable should look as follows:

Now we’ll take a quick jump over to GA and create the custom dimension. In the admin section of GA, look under the Properties section for Custom Definitions. Click to expand it and then you’ll see Custom Dimensions. Create a new custom dimension using the User Scope.

After you save your new custom dimension, be sure to note its Index position. Here you can see that the index position is 6 for the User Has Previously Ordered custom dimension.

Now back to GTM where we will create the GA tag using the Google Analytics – Universal Analytics tag type. For Track Type, select Event. The Category, Action and Label fields define the event taxonomy that you’ll see in GA for this event. The taxonomy I have chosen here is User / Activity / Has Previously Ordered, but you can classify the taxonomy however you wish. Two important steps to take are to make sure the Non-Interaction Hit value is set to True and to make sure the Enable overriding settings in the tag checkbox is checked. After checking that box, you will input your Google Analytics Tracking ID. You can either store this in a GTM Variable as I have below {{GA-ID}} or input the actual tracking ID. Finally, under More Settings, expand Custom Dimensions and input the index position for your GA custom dimension (in my example, the value is 6) and enter a value of 1 for the Dimension Value. We will be able to isolate this value when creating a segment in GA for existing customers.

All that’s left here is to create the trigger to fire this GA tag. For the trigger type, select Page View – Window Loaded and have the trigger fire on Some Window Loaded Events. For the trigger event condition, select the Data Layer – Returning Customer GTM Variable you created above and have it equal a value of 1.


Alright! The hard stuff is all done. You’ve made it this far, so I think you’ll want to take this one extra step. Currently, our tracking is configured to cookie customers when they checkout so that when they return, we’ll be able to read the cookie and identify them as existing customers. Cookies don’t stick around forever though and we haven’t done anything to solve for the multiple device problem. What we need is a way to identify additional returning customers when they visit the site. We’ll do this by reading the UTM params from referring URLs and see if any are set to signify that a returning customer is visiting. If any are, we’ll go ahead and set a new RETURNING_CUSTOMER cookie if one is not already set on the user’s browser.

The code that follows can be amended to check for additional marketing channels, but the one that we will focus on here is our email marketing channel. For this code to work, you will need to tag the links in your emails to existing customers with a specific UTM_CAMPAIGN. By way of example, we will assume that the UTM_CAMPAIGN param assigned to the links in your existing customer emails is Email-Customers. Go ahead and insert the following code at the very beginning of the snippet that was inserted into your theme.liquid file (right after the opening <script> tag):

    if (isNewSession()) {

      window.UTM_SOURCE = 'UTM_SOURCE';
      window.UTM_MEDIUM = 'UTM_MEDIUM';
      window.UTM_CONTENT = 'UTM_CONTENT';
      window.UTM_TERM = 'UTM_TERM';

      // Set UTM Keys


    // Determine if this page load is the first of this session.
    function isNewSession() {
      var tuckerUrlRegex = /^https?:\/\/(w{3}.)?;
      return !(document.referrer.match(tuckerUrlRegex));

    // Store a url parameter to sessionStorage.
    function setFromUrlParam(key) {

      var value = window.getParameterByName(key);

      if (key == "utm_source") {
        Cookies.set(UTM_SOURCE, value);

      if (key == "utm_medium") {
        Cookies.set(UTM_MEDIUM, value);

      if (key == "utm_campaign") {
        Cookies.set(UTM_CAMPAIGN, value);

      if (key == "utm_content") {
        Cookies.set(UTM_CONTENT, value);

      if (key == "utm_term") {
        Cookies.set(UTM_TERM, value);


    if (Cookies.get('UTM_CAMPAIGN')) {

    	var str_medium = Cookies.get('UTM_CAMPAIGN');
      	var CustomerEmail = str_medium.includes("Email-Customers");

      	if (CustomerEmail) {
           if (!Cookies.get('RETURNING_CUSTOMER')) {
      	      Cookies.set('RETURNING_CUSTOMER', '1');

And there you have it. Your existing customers that are visiting from email are now also being added to the existing customer cookie pool if they are not already in it. You can easily amend this code to add in additional marketing channels like retargeting to make the cookie pool even larger. The more data, the better!


YOU MADE IT! Congrats on getting your tracking installed. I know that this was a lengthy guide, but we now have a great tracking code base that we’ll continue to build upon in (shorter) future posts. Ahem….

The only thing left to do is test our installation and create a segment in GA to use in our reporting. If you want to live dangerously, I won’t stop you. Just publish your GTM container and you will be live, but I would encourage you to use the Preview feature in GTM before publishing to test your tags. The Preview feature is very powerful and will certainly come in handy for testing your future GTM container additions.

There will be two specific use cases you want to test: 1) ensuring that we are correctly cookie-ing first time customers on the thank you page and 2) ensuring that we are recognizing our existing customers when they visit from our email channel and correctly cookie-ing them. You can use a dummy landing page url with the correct UTM_CAMPAIGN included to test this. Just be sure that you delete the RETURNING_CUSTOMERS cookie first if it’s present in your browser before testing this step.

For case 1, you will need to place a test order (after clicking the Preview button in GTM of course). On the thank you page, you should see three tags that are fired and one that is not:

Now, check to make sure that the COMPLETED_CHECKOUT and FIRST_TRACKED_ORDER cookies were installed correctly on the browser. In Chrome Developer Tools, navigate to the Application tab and scroll down and expand the Cookies section under Storage. You should see:

Now visit your home page and go ahead and delete the FIRST_TRACKED_ORDER cookie. This is the temporary cookie that expires after 1 day and prevents our GA – Returning Customer tag from firing. Reload the page and voila, there it is.

Assuming that all goes well, you can publish your container to go live!

To remove the preview feature on your browser, just click the Leave Preview Mode link

In Google Analytics, creating the segment for existing customers is a breeze:

You can now apply this segment to your traffic, conversion and product reports in GA for some super-charged analysis!


Simo Ahava’s blog was essential reading for me when learning about GTM. These two articles have additional information on what we reviewed here:

Thank you Simo!

I also highly recommend the book Google Analytics Breakthrough for anyone looking to learn to become a power user of the tool.

2 thoughts on “Tracking repeat customer performance in Google Analytics

  1. SO HELPFUL. Thank you!

    I run a consumables (skin care) brand, and a huge pain point has been trying to break out (no pun intended, I promise) first time customers vs repeat customers to really gauge our customer churn rate, measure our efforts on retention and test our LTV theories.

    I’ll reach back out if I don’t start tracking Repeat Purchases for any reason.

    Thanks again!


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.