One of the strongest (and there are plenty!) variable types in Google Tag Manager is the RegEx Lookup Table (technically “RegEx Table”). It allows you to look up an output value based on a regex search in an input variable, and makes structuring unstructured data much easier.
If you have never worked with RegEx Table variables, I urge you to start thinking it into your way of working. Yes, they are that good.
But one of the flaws (or maybe limitations is a more fair definition) is the lack of ability to create a multicolumn matrix-sort of variable. Which comes especially much in handy when the setup you are building involves lots of values in different variables. Having all that information collected in one table, and look up a specific value in a specific cell, based on an x and a y coordinate, can make complex datasets easy(-ier) to navigate and maintain.
Let us do an example case and try to build it out, rather than going down the theroretical road.
Example case for using a multi-column regex lookup table
So, let’s pretend you are working on a B2B website, with multiple different forms implemented. Some are Lead forms (request for quote, product demos, meeting booking etc), some are signup forms (newsletters and stuff), and some a genericmore forms (contact forms, press, HR, login and the like). You also use a plethora of different marketing and tracking tools (like Facebook, Linkedin, Google Analytics – you know them all).
Your case is that depending on what form was submitted, it is more or less unique what event you want to send to the different tools. The different events are maybe unique to each each tool due to technical requirements: Facebook uses strings (“Lead
” or “Contact
“) but Linkedin uses integers (123456
or 987654
).
The Real-World Challenge of Multiplication
And herein lies the challenge: If you have just 5 different forms and use just GA4, Facebook, Linkedin, Google Ads and Bing Ads, that is already 25 different tags that you need to maintain (5 forms ✖️ 5 tracking tools = 25 tags). And if you then later add a new form or a new tool, you’re looking at 6✖️5 = 30 tags. Now try adding an additional form and two new tools, and you’re looking into maintaing 7✖️7 = 49 tags. Good luck with not introducing human error into that equation. Oh, and we also need an adequate number of triggers, to fire each tags. So 7✖️7+7 = 56 maintainable (and error-prone) elements. Just for form tracking.
Now, there are many different ways this could be solved; some better than other. Because if you look at a generic table of this, it’s actually quite maintainable, and the lookup option is quite obvious:
Explanation: Look for {{Variable Match}} in Column 1, and return the value of {{Relevant Column #}} for the matched row. Example:
- Look for a row matching (RegEx) “
-ab0f-
“. (Row 6 above) - Return the value of the Facebook column of that row (“
Contact
“)
We can then use that variable in the “Custom Event” field in a Facebook tag:
Let us discuss the simple(st?) approach
The simplest approach could be to create the matrix in a Google Sheet or Microsoft 365 Excel sheet as they are both avilable online. Google Sheet would be the most obvious solution as it is already fairly well integrated into Google Tag Manager.
Having your matrix in a Google Sheets is the epithomy of maintenance: You can update your sheet whenever possible, and the values will automagically autoupdate into your tracking setup immediately, and maintenance is swift and clean.
The problem with that solution is that if you do this on a high-traffic website, that it has the potential of sending a lot of requests to Googles server, and given that we are currently in Client Side GTM Country, it’s not the best option. The risk of losing data due to timeouts is just too big here, and so I personally would not go that way. (Note: Working with this in a Server Side GTM environment is a different story and could be done – but that is for a different article).
So back on track.
The Better Solution: Generic tags and Lookup Variables
We could create a multi-variable, multi-generic-tag setup, where we use Lookup or RegEx Table variables for each tracking tool. Form identifiers in Column 1, and the output value for each in Column 2, limited to a specific tool. Our setup would then look more like this:
- 7 generic tags, one for each tool
- 7 lookup tables, one for each tool
- 7 triggers, on for each form (or maybe even just one trigger covering all forms!)
That gives us a setup of just 21 tags to maintain (compare that to the 56 tags in the original calculation). That’s not too bad. And after all, we also need to make a living by filling our work day with meaningful tasks, amiright?
The general idea is that the generic tags are fired whenever a form is submitted. Then, based on the form identifier of your choice (could be {{Form ID}}
or {{Form Classes}}
, or maybe {{Page Path}}
– you decide based on your setup), the variable will then return the event value needed for the specific tag, and is inserted in the tag/script. It could look like this:
And yes, this actually works. And it works quite well, especially on sites that do not change too often. But on sites where we often change/update forms (new ones are added, old ones are removed, and/or forms are repurposed often (e.g. when using forms for campaign-based landing pages), upkeep suddenly becomes high. Mainly because forms suddenly change their purpose (or maybe identifiers). And as soon as someone has changed/added a form, you need to update all the relevant variables, adding and changing values – and this introduces the problem, because as your site grows, it is easier than not to miss a single line somewhere, or wrongly map a form identifier with the wanted output value.
Guilty as charged 🙈
The Multi-Column RegEx Table Variable
Nerd Alert!
Let’s get technical now. The above setup we will build by using built-in GTM elements: Tag, Lookup (or RegEx, depending on needs) and Trigger. But in order to move on we need to move into the strongest, most flexible (but also the most error-prone) variable type in Google Tag Manager: The “Custom Javascript” variable:
⚠️ Attention: This is advanced stuff and if you are not used to working with vanilla javascript, you should consult someone who does, as this feature have the power to break your website if used haphazardly.
What we a going to do is build a Javascript variable that contains our data matrix, and use standard Javascript functions to look up the values we are interested in.
We will do it this way:
- Create a Dataset variable, which contains all the data. We will create this only once (to keep the data set in one place only = only need to update the matrix in one place).
- Create a variable type which we instruct to return the value from a specific column, based on out input variable.
Creating The Data set / Matrix Variable
The dataset is basically a Javascript object, where we use standard JSON to populate it. It is as simple as this:
function() {
return [
{
"lookup": "form1rules",
"facebook": "data1-1",
"linkedin": "data1-2",
"google_ads": "data1-3"
},
{
"lookup": "hereisform2",
"facebook": "data2-1",
"linkedin": "data2-1",
"google_ads": "data2-3"
},
{
"lookup": "thisisform3yeah",
"facebook": "data3-1",
"linkedin": "data3-2",
"google_ads": "data3-3"
},
];
}
Code language: JavaScript (javascript)
⚠️ Attention: You can choose to maintain this variable by hand but my recommendation would be to maintain it in a spreadsheet (Google or Excel). Whenever you then make an update, use a function to transform the table contents to a JSON object, and use simple copy/paste in your variable. This way you avoid a Code 18.
Save the variable with a saying name, like “Dataset - Custom Events Overview
“.
Create the Custom Javascript Lookup Variable
Next up is creating the variable we will use to look up values in the dataset matrix. It’s fairly simple – it is basically a Javascript function which take the dataset matrix variable, the form identifier variable and a column (“index”) number as input, roam around the dataset matrix, and return the value.
function() {
var formClasses = {{Query - lookup}}; // Replace with your input variable
var columnNumber = 2; // Replace with column number variable you want to search in - here it is Column 2 "Linkedin" bacause column #1 is technically column #0)
var dataset = {{Dataset - Custom Events Overview}}; // Reference the dataset variable
// Define column names. This needs to be aligned with your dataset
var columnNames = ["lookup", "facebook", "linkedin", "google_ads"];
// Compile the regex pattern
var pattern = new RegExp(formClasses);
// Find the row where formClasses matches the lookup value using regex
var row = dataset.find(function(row) {
return pattern.test(row.lookup);
});
// If row is found and the column number is valid, return the value
if (row && columnNumber > 0 && columnNumber < columnNames.length) {
return row[columnNames[columnNumber]];
}
// If no match or invalid column number, return null
return null;
}
Code language: JavaScript (javascript)
Note the changes you need to make in the code, to align with your dataset.
You can test the above by giving it one of the following lookup inputs: form1
(returns data1.2
), form2
(returns data2.2
) or form3
(returns data3.2
).
You then use the above code for any variable you would need. In our case example here, you would make the following variables:
JS - Get Table Cell Value - Facebook
JS - Get Table Cell Value - Linkedin
JS - Get Table Cell Value - Google Ads
You can now insert the relevant variable in a generic form submit tag:
Easy-peasy-lemon-squeezy 😊
A word of caution
As mentioned, the above solution – while being fairly simple – requires a certain understanding of how Javascript and Google Tag Manager works. We see some risks involved whenever you work with Custom Javascript, in Google Tag Manager specifically, but in any setup in general So if you feel this is outside your comfort zone, talk to someone with a technical background.
But also don’t be afraid. It is immensely powerful to be able to build your own variables, tags and triggers, so I urge you to try it out, if it makes sense for you.
And if you have any ideas for improving the setup (or solve the problem in different ways,) let me know in the comment!
⌨️ Happy tagging!
Leave a Reply