The death of Google Optimize is upon us. And wowee, aren’t you a little bit heartbroken. Gone are the days where you’ll be able to switch a button on your website from red to green and run a mindless A/B test. Now you have to pay $60,000 annually for that. But wait! What if I told you that you can continue to run A/B testing FOR FREE, leveraging tools that are probably already on your website. Would you pay me $60,000? How about $2? I’ll take it…

Now don’t get me wrong, you should absolutely invest in an A/B testing platform. They have a butt-ton—(can I say butt-ton?…no? Ok how about boatload)—a boatload of features that go beyond what I am about to show you. Also, A/B testing in general should have a dedicated process, with a well-thought-out testing matrix, strategists, developers, designers and analysts. If you’re going to have all of that, you should probably have a dedicated tool,right? If you just want to be a little whimsical about it though, I will show you how to do testing without anything fancy. Just a little grease on your Google Tag Manager wheels and any analytics platform.

Basic Steps Below:

How to A/B Test for Free with Google Tag Manager, and any marketing analytics tool.

  • Create a New Cookie in GTM
  • Create a GTM Experiment Tag
  • Build a Variable to Capture the 1st Party Cookie
  • Build a Variable to Generate a Random Number Between 0-99
  • Create a RegEx table Variable for the Cookie
  • Update Cookie Tag with RegEx Table Variable
  • Create a Custom HTML Tag with Your Changes
  • Trigger Your Test on the Variation Trigger.
  • Build Out the Analytics Portion
  • Build Your Conversions
  • Set Up the Conversion in Your Marketing Analytics Tool
  • Set Up Your Custom Dimension in your Marketing Analytics Tool
  • Finally, Let’s Build our Audiences!
  • Integrate with Heatmap Let’s get started. First, this post assumes that you have a basic understanding of Google Tag Manager, triggers, variables, & tags. If you don’t, then please leave and go to MeasureSchool’s YouTube to learn all about the tool. If you are still reading then I’ll assume we’re good to go.

Create a New Cookie in GTM

First lets build a Cookie in GTM by importing the template “Cookie Creator” from the Community Gallery. Review the permissions (which allow cookies to be written if you specify them in the template) of this Tag Template and select “Add to Workspace.”

Google Tag Manager Import Tag Template window searching “cookie creator”, with the Cookie Creator template shown

You can also just build a cookie using custom HTML, but why work harder than you have to? Once you have imported it into your templates and accepted permissions, you can start building multiple cookies with ease.

Before we start building our experiment, we need to allow this cookie creator to build the cookie we tell it to. To do this, open the Cookie Creator template and navigate to “Permissions”.

Tag Templates list in Google Tag Manager showing the Cookie Creator template, last edited 6 hours ago

Next add an allowed cookie for _gtm_exp or whatever identifier you’d like to build for your GTM experimentation.

Template Editor Permissions tab with the Sets a cookie permission and an allowed cookie named _gtm_exp

Create a GTM Experiment Tag

In the Tags tab, create a new tag using the Cookie Creator tag template you’ve just saved.

  • Set Cookie Name to “_gtm_exp”
  • Set Cookie Value to “abc”
  • We’ll be updating this value later to dynamically populate based on random allocation. Since we can’t save the tag with a blank value, let’s add “abc” to the cookie value for now.
  • Set Expiration Mode to “By month”
  • Set Expiration by Months to “6m”
  • “Even if your experiment duration is shorter than 6 months, having a longer expiration date ensures that users will continue to see the same experiment on return visits until this cookie is removed”

Cookie Creator tag named GTM Experiment with cookie name _gtm_exp, value abc and an expiration of 6 months

You may want to set additional cookie options- like SameSite if you have subdomains, etc. -but we’re going to leave it blank for now. Feel free to use this FireFox pageas a resource for all the different configurations you can do with cookies.

You can save the tag without a trigger for now. We’ll come back to it!

Build a Variable to Capture the 1st Party Cookie

Let’s now go into our variables section and build a 1st Party Cookie to capture the new cookie value that we created:

  1. Navigate to the Variables tab
  2. Click to create a new User-Defined Variable
  3. Select “1st Party Cookie” as the Variable Type
  4. Update the Cookie Name to “_gtm_exp”
  5. Give your variable a name and save

Variable configuration for a 1st Party Cookie variable named GTM-EXP Cookie with cookie name _gtm_exp

Awesome. That was easy. We’ll come back to using this later.

Build a Variable to Generate a Random Number Between 0-99

Now, we want to create the functionality to generate a number from 0-99. This will become the basis of our test functionality.

  1. Click to create another User-Defined Variable
  2. Select “Custom JavaScript” as the Variable Type
  3. Add a function to generate a random number. Here is some code so you don’t have to look around on the web for it. You are welcome.

function() {

var math = Math.floor(Math.random() * 100);

return math

}

  1. Marvel in wonder at the highly advanced, complex bit of JavaScript you’ve just written
  2. Name your variable “Random Number (0-99)”

Create a RegEx table Variable for the Cookie

We now want to use our random number to set a cookie value based on whether a user is assigned to the control group or the test group. You could also create multiple variations by adjusting this logic with the amount of numbers that represent a version. In this version we are looking for 0-49 & 50-99 to set different variations, but you could easily adjust to 0-33, 34-66, 67-99 for an A/B/C test (etc.)

RegEx Table variable using the Random Number 0 to 99 variable as input, with patterns mapped to the outputs cta_button_test_control and cta_button_test_var1

  1. Create a new RegEx Table variable
  2. Set the Input Variable to the random number variable you’ve just created
  3. Use this RegEx to target the split-test numbers:
  • Control Group: 0 – 49
  • RegEx Pattern: ([0-9]|[1-4][0-9])
  • Test Group: 50-99
  • RegEx Pattern: ([5-9][0-9])
  1. The Output values will be based on the type of test you are running. For this example, we’ll be doing a simple CTA button text change.

Update Cookie Tag with RegEx Table Variable

Now that we have our RegEx table, we can use it to build the functionality of our split test. We’ll be using the 0-49 randomized number to set the control & 50-99 to set the variant.

To do this we want to go back into our cookie creator tag and set the Cookie Value to our RegEx table.

Cookie Creator tag with the cookie value field set to a CTA Button Text variable and an expiration of 4 months

For the trigger we want it to fire on all pageview events where the cookie does not yet have a value that includes our test.

Page View trigger named “CTA Button Test Cookie Does Not Exist Yet” that fires on some page views when GTM-EXP Cookie does not contain cta_button_test

Now that we have the cookie in place, we can build our actual test.

Create a Custom HTML Tag with Your Changes

Now is probably the most challenging part. You are going to need to know a bit of JavaScript but if you don’t, ChatGPT is a great resource. Just ask it to help you target and change the element you want to change. Unfortunately, GTM is not equipped with a visual editor like Google Optimize to help you change. If you wish you can use a chrome extension such as “visual css editor” which has a lot of the same functionality as a CRO visual editor and even helps you export code. Overall, you will probably hit a snag at some point and need some help from either AI or a JavaScript developer. Regardless, I used ChatGPT for this change and if it’s good enough for me, it’s good enough for you!

For this example, we’ll be updating the text of the hero tagline by using a Custom HTML tag.

Step 1: Create a new Custom HTML tag. This will contain any necessary scripts to modify website content for your Test Group.

Step 2: In the HTML section, add your script. This example will be using the script below to update the text of the hero tagline:

<script>

var tagline = document.querySelector('.hero-tagline');

if (tagline) {

tagline.innerHTML = 'Build Sustainable Growth <i class="far fa-arrow-right" aria-hidden="true"></i>';

}

</script>

  1. Give your new tag a name. In this case, we’ll name it “Update Hero CTA for Test Group”

Custom HTML tag named “Update Hero CTA for Test Group” with a script that changes the hero tagline text

Now that we have our code, let’s trigger it on 50% of the traffic.

Trigger Your Test on the Variation Trigger.

Now that the cookie is placed, we just need to look for the value we want the test to trigger on and add our trigger condition to our Custom HTML tag.

DOM Ready trigger named “CTA Button Var” that fires when GTM-EXP Cookie contains cta_button_test_var1

You will likely want to test at this point. Testing is pretty simple. Just go to your preview mode, and open the page you want to test on. You’ll get your randomly generated value and it will set a cookie since it’s your first time there. You can then navigate to the Chrome debugger and edit the cookie value between your control and variant by finding the cookie value in Applications and looking for our _gtm_exp cookie.

Browser developer tools showing the _gtm_exp cookie set to cta_button_test_control below a website hero headline

Website hero with a Build Sustainable Growth call to action and an arrow pointing to the _gtm_exp cookie value in developer tools

Great, now that we have the test setup portion done, let’s get that baby into our analytics system.

Build Out the Analytics Portion

This next part can be applied to ANY analytics tool. I will be focusing this blog on GA4 and Microsoft Clarity but the same process can be applied to Piwik Pro & HotJar, Matomo & ContentSquare. Whatever you want. We’re going to apply it to both a marketing analytics tool and a heatmap software just for fun but it can be used with just one tool if that’s your preference.

Add to your Analytics Tag

First, just like with CRO tools, we need to make sure our cookies load before information gets sent to our analytics tools. So if you are firing your marketing analytics tool on Pageview as well, we’re going to need to add an analytics event that fires when the cookie is set.

Let’s create the event. This event fires the actual event but also sets the cta_button_audience to the control or the variant in our GA4 and ties it to the user. This will be the basis of our audience parameters.

GA4 Event tag named CTA Button Test Triggered with the event name cta_button_test_triggered and a cta_button_audience user property set to the GTM-EXP Cookie variable

Now let’s make it a cleanup tag for our cookie placement.

Cookie Creator tag advanced settings with tag sequencing set to fire the CTA Button Test Triggered tag after the cookie tag

Awesome. One last thing. We also want to add to our main configuration tag. This ensures that as people come back to the website and the variant is there, it also communicates the value to the user-level custom dimension. It should remain with that user but this is a secondary level of protection from GA clear cache etc. It becomes a little more secure than just relying on the event itself as the event only fires the initial time that the user gets bucketed. The cookie will remain as a value as long as it’s stored in the person’s browser. After the initial placement, the cookie should be there on page load so you can capture it with your main configuration on pageview.

Google tag named FTF - GA4 Configuration with a cta_button_audience user property set to the GTM-EXP Cookie variable, firing on All Pages

Note: You can also just move GA4 config to Dom Ready instead of doing the above (with the same configuration tag changes) but some people are violently against changing where GA loads, so that’s why we did the above approach.

Another Note: you can actually set the variable to an event level parameter instead of a user-based one since we will be building it as an audience who saw the particular event anyway, but I think User Properties are a bit cleaner. If you are running low on User-level custom dimensions, event custom dimensions are fine.

Build Your Conversions

If you already have a conversion that you want to use with this setup you can skip this section. Otherwise, if you want to set up a secondary conversion or you have no conversion you can follow along with the below to set up one.

Usually, our main conversion would be a form submit or purchase, but we are going to use cta clicks for this example.

Go into preview & debug mode and perform the action that you want to track.

Website hero headline with an arrow labelled “Click” pointing at the Build Sustainable Growth button

Make sure you have any relevant built-in variables (click id, click class) and triggers (all elements/link clinks) enabled in your GTM.

Navigate to the click action that you did and find the relevant variable that you want to track.

Tag Manager preview Variables tab for a click event with the Click Classes value “hero-tagline” circled

Build your trigger and event/conversion.

GA4 Event tag named CTA Button Click with the event name cta_button_click and a click_text parameter, fired by the Hero tagline trigger

Click - All Elements trigger named Hero tagline that fires when Click Classes contains hero-tagline

Great! We’ve just set up the action we want to use in GA4 as one of our conversions. The nice thing about building an audience or segment with our variations is that you can use those in conjunction with other conversions or events that are already in place (thank you pages, etc.)

Set Up the Conversion in Your Marketing Analytics Tool

In GA4, there are a few steps we need to take to get this to work. First, we need to set up our conversions. Some may already be set up, but the one we just built above we need to set as a conversion. You can either wait for the event to show up in GA4 and then check the little blue toggle next to the event, or we can navigate to conversions and input the name of the event manually. Let’s do that one.

GA4 Create conversion event dialog with the event name cta_button_click

Set Up Your Custom Dimension in your Marketing Analytics Tool

Now that we have our conversion, let’s navigate to custom dimensions. Let’s create both a User based custom dimension for our cta_button_audience which is handling our cookie value.

GA4 Edit custom dimension screen: CTA Button Experiment Audience, scope User, user property cta_button_audience

Note: If you don’t have click_text set up as a value in GA4 already, you’ll want to do that now for the cta_button_click event that we built. Every custom dimension needs to be defined in GA4 for the data to show up in the interface.

Finally, Let’s Build our Audiences!

You’ll want a unique audience per variant (including control).

GA4 audience named CTA Button Test Control that includes users whose audience property contains cta_button_test_control

GA4 audience named CTA Button Test Variation that includes users whose audience property contains cta_button_test_var1

You’ll want to confirm that the amount of users in both the variant and the control are relatively equal. This will be an extra-level of comfort that our triggers and tags are working.

Now all we have to do is do an audience comparison with our conversions and we are swimming in A/B test sauce.

You can build an audience report by creating a custom report in the library and using the audience as a dimension.

GA4 audience report for the CTA Button Test Control and Variation audiences with users, sessions and cta_button_click conversions

Alternatively, you could use our user-level custom dimension

Table of the two audiences: cta_button_test_var1 with 19 users and 1 conversion, cta_button_test_control with 15 users and none

I find it’s a bit cleaner to use an audience because you can archive audiences when you are done with the test and you can choose to use the gtm_exp cookie to build alternative tests in the future and audiences help provide a general cleanliness around the reporting.

To run statistical significance tracking you can use any A/B test calculator but my preferred is CXL’s AB Test Calculator. Just dump your data in and it will calculate the lift for you!

Great job! You made it and can stop here. Or we can bring both variations into Microsoft Clarity. You want to continue??? I APPLAUD your tenacity.

Integrate with Heatmap

For this part of the lesson, we will assume you have Microsoft Clarity up and running. I like Microsoft Clarity a lot. It’s free and has a TON of features that are really valuable. For this particular task, we are going to be using the custom tag filter feature.

Navigate back into Google Tag Manager and find the Microsoft Clarity community template by Luratic. If you have Microsoft Clarity hard-coded, I suggest you migrate it to the template so that you can use their built-in custom tag feature, which we’ll be utilizing for this experiment. You can also do this with code instead of the template if you are a masochist.

Add in a key: cta_button_audience with the value of our GTM_Exp. Now you’ll be able to filter all pages by your cookie variation!

Microsoft Clarity tag named CTA Button Test - Clarity with a custom tag cta_button_audience set to the GTM-EXP Cookie variable

You can go one step further by also building custom events for your CTA clicks & conversions, which will make finding specific recordings much easier.

Microsoft Clarity tag named CTA Click with a custom tag key_action set to cta_click, fired by the Hero tagline trigger

Now we have our new Custom Tags. Navigate back to Microsoft Clarity and find the custom filters.

Microsoft Clarity dashboard with an arrow pointing to the Filters button

Clarity Custom filters panel with the custom tags list showing key_action and cta_button_audience

Clarity Custom filters with cta_button_audience selected and the values cta_button_test_control, cta_button_test_var1 and deleted listed

Now we can filter by both our key action that we want to see and also the different variations. This gives us ultimate clarity (pun intended) into how the different pages are performing with our variations! Give it a few days and you’ll get your changes in two different heatmaps!

Clarity click heatmap of the homepage filtered to the cta_button_test_var1 audience, with the hero button showing 2.63%

Clarity click heatmap of the homepage filtered to the cta_button_test_control audience, with the hero button showing 1.00%

BONUS: if you integrate GA4 with Microsoft Clarity you can also pull in your GA4 segments (audiences), making this a breeze to analyze! I still like having the filters but it can help streamline the process.

PHEW! We’ve Reached the End

You did it! You made it! You created a fully functioning A/B test machine in GTM with FREEEEE tools. But yeah that was a lot of work. You may want to pay for something to avoid the long and drawn out (but cool) process above. But if you don’t and you end up using this solution…maybe you can pay me instead 🙂