When working with Google Tag Manager (GTM) implementation, we often bump into companies that have limited developer access and don’t have time to implement a Data Layer for a number of reasons – limited time to work on the website, third-party teams, etc., or they have a Data Layer, but it is not properly implemented.
I’m passionate about what I do. If you meet my manager or co-workers, they would say I’m a team player, engaged and always excited to learn something new. Like everyone else I have some flaws. However I’m not afraid to work around those to bring the best in myself and for the company.
February 1, 2023 - When working with Google Tag Manager (GTM) implementation, we often bump into companies that have limited developer access and don’t have time to implement a Data Layer for a number of reasons – limited time to work on the website, third-party teams, etc., or they have a Data Layer, but it is not properly implemented.
Whatever the reason, if you don’t have a data layer, or have one that’s not properly implemented, eventually you will have to rely on the page and site source code to get the information you want in order to provide the best reports to your clients, and the most common way to do this is by looking forElement ClassesandElements IDs.
But, what if the website I’m working on doesn’t have these or it’s a hit-and-miss when it comes to this information?
Well, as long as you can load GTM on the website, there’s a solution and we’re here to help.
NOTE:Before we jump into the actual code, it’s important to highlight this is not our first choice when it comes to collecting data. Most notably because in HTML, Classes and, sometimes IDs, can be modified by the developers for a number of reasons and therefore, the information you were using for triggers – for example in GTM – may not be available anymore, resulting in considerable data loss if it’s not fixed quickly enough.
That being said, let’s do the work!
What are you seeing?
If you preview yourGTM containerand haveClicksenabled, you should see something similar to this:
Now, what is actually happening here? Or should we say, what’s wrong with this image? That’s right, gtm.elementClasses and gtm.elementId are empty. More often than not, this is the information we look for when using gtm.linkClick or gtm.Click. We can’t really rely on the rest of the data because some of it changes every time this event fires. One example is Element URL, but sometimes that may not help a specific situation.
The formula to get this information is pretty simple and you can use it in theDevTools Console.
Here, all you have to do is replace theContainerIDwith the actual GTM container that’s loading on the page. Keep in mind that a click must happen BEFORE you type the formula, otherwise, you will getundefinedas a result.
To give more detail, what is happening here is that .datalayer.get helps you query GTM elements that are retrievable from the Data Layer and (“gtm.element”) specifies the node in the Data Layer you want to extract.
Add .parentElement to climb up the tree until you find what you’re looking for. This part can be tricky because you need to be in the actualparentelement to retrieve the actualsonelement.
Once you reach the element you want, add .querySelector(” “) to your command, with the parameter CSS selector inside the parentheses and double quotes.
Now, if you don’t know what you are looking for specifically, or what you can use/retrieve here, you can add .attributes to your code to see the full list of items available. This will return the NamedNodeMap and you can use any other values in there with your code to pull the data.
All you have to do is right-click on the item you want and select Copy Property Path (or you can hover over the item to see the path as well).
Once you have the Path you want, add it to the end of your code but this time without a dot.
The  means the first array available and .textContent means the name of the information available in that array.
For example, if I wanted the first item in the array (baseURI) my code would have attributes.baseURI at the end.
Once you have this setup, Preview the container and check to see if the variable is populated with the proper information.
Keep in mind this is related to a click element so the action needs to happen in order for the variable to be populated. If the element was clicked but you’re still seeing undefined, there’s most likely something wrong with the code, so you’ll have to revisit it.
But why stop here?
The objective here is to return “Home” when a user clicks on Home, “Blog” when Blog is clicked, etc. . There are a couple of ways to approach this, but I used a small IF statement:
What’s happening here is that I created a variable called menuClicked that would hold the textContent of the element that was clicked inside the <a> HTML tag.
On the third line there, I created a variable called menuList that would hold all the items in the menu. You can definitely get a different approach here in case you have a different menu or more items, but for this case, I used this approach.
Note that undefined is not configured in the code, but GTM automatically helps us here and returns undefined if nothing is found.
Although just a few lines of code, it can be very helpful to actually return the proper information that should be used within triggers, or even to push further Data Layer information based on it – but that’s a subject for another article. 🙂
Although this is a pretty interesting way to retrieve information from the HTML code, it’s possible to get carried away with it. You can end up creating multiple variables in GTM just to fix a couple of things and suddenly end up with and in the end, 10 variables retrieving individual information and passing it all to another custom JS and so on. CustomJS in GTM alongside HTML custom Tags are one of the main reasons most websites are heavy on loading, so use this wisely. In the end, the Data Layer should be your first option, but if a Data Layer isn’t possible, then you can think about exploiting this path.