February 15, 2019
Track element visibility based on text with Google Tag Manager
Element Visibility trigger in Google Tag Manager enables you to track elements when they appear on a screen, which is really cool. Even though I still feel a teeny tiny grudge (about the situation when I published a blog post with a custom visibility listener and then Google released their much superior solution several weeks later), I’m happy that it exists because this trigger opened a whole new horizon of tracking opportunities. Of course, if used properly.
Usually, this trigger is used to target elements based on their IDs or CSS selectors. But what about tracking based on the element’s text? – I hear questions here and there. Well, you technically *can* do that too.
In today’s blog post, I’ll show a tip you should not implement due to its fragility.
Yup, you read it right. Today I’m going to waste your and my time 🙂
In general, tracking element interactions based on their text is a very lousy method (most likely doomed to fail). What if someone changes that text? Your trigger will fail. What if a visitor turns on the page translation on your website? Once again, a trigger will fail. A/B test running? If it changes the element text, the trigger will also fail.
Anyway, I’m not here to judge you or your decisions today. This time, I want to show you what you *can* do with GTM even though you *shouldn’t*. Let’s roll
CSS Selector in Element Visibility trigger
So the “tip” is quite simple. First of all, you will still need to choose the selection method, either it’s ID or CSS Selector.
If the element does not have an ID (which, admittedly, happens quite often), you’ll need to go with the CSS selector (which is quite a difficult topic for GTM beginners). However, if you plan to up your Tag Manager skills, CSS Selectors should definitely be added to your to-learn list. With them, you will be able to create more complex rules on how to target particular website elements.
But how can you decide what is a proper selector? Unfortunately, it’s impossible for me to write a universal CSS Selector quick tip if you don’t know them at all because they depend on how a website’s HTML was coded. That’s why I really recommend you read this Simo Ahava’s blog post where he shares useful and most common use cases in GTM.
From this point (after reading Simo’s guide), I hope that you already have at least a very basic understanding of what CSS Selectors are and where you can use them in Google Tag Manager.
In the homepage of my website (as of 2019), there are several identically looking blue buttons (with the same CSS classes btn-bt align-left with_icon) and I want to track only one of them, containing the text LEARN MORE ABOUT THIS COURSE.
Even though I could just simply target it with a more precise CSS Selector, in this blog post, we’ll see how the text can be used instead.
First of all, let’s choose the CSS selector. I’ll do the right-click on a button and then Inspect Element. Next, let’s take a look at what we have.
The text of that button is in a <span> element that is a direct descendant of a link (<a> tag) and that link uses the btn-bt align-left with_icon classes. This is important: you need to target an HTML element that contains the actual text.
Since we’ll be targeting the text of a button, we need to enter the CSS selector that picks that very exact text. In this case, it can be a.btn-bt.align-left > span
With it, we’re selecting all elements that are <span> and are children of links (<a> tag) with CSS classes btn-bt and align-left.
Let’s verify whether this selector doesn’t pick up too many unwanted elements. In your browser, open the Developer’s Console (if you’re on Chrome and Windows, press F12 and choose Console.
Enter the following command (remember, this one applies only to my homepage (in 2019, as long as it using the current design). If you chose another CSS Selector, replace everything that is between the quotation marks.
document.querySelectorAll("a.btn-bt.align-left > span")
It will return a list of two elements that match the a.btn-bt.align-left > span CSS selector. If you’re trying this method on your website, the results will vary.
If you expand both of them, you’ll see that one contains a text LEARN MORE ABOUT THIS COURSE:
So how can we set the trigger to fire only when the page element (that appears on a screen) matches CSS selector a.btn-bt.align-left and contains the text LEARN MORE ABOUT THIS COURSE?
You have to add an additional condition to the Element Visibility trigger:
- Click Text contains (or equals) LEARN MORE ABOUT THIS COURSE
Remember that this is case sensitive, that’s why Learn more about this course would not work will not work.
Click variable in Element Visibility trigger?
Why the hell did I choose the Click Text even though we’re tracking an impression, not a click?
It’s because Element Visibility listener has some similarities with Click or Form listeners. When it spots the correct element, the visibility listener pushes some element-related data to the Data Layer that follows the exact structure as it would have been with Click or Form triggers.
In the Data Layer, that information will contain the following keys: gtm.element, gtm.elementTarget, gtm.elementClasses, etc.
See? Looks similar to what click and form listener is pushing.
OK, but where is the gtm.elementText? How will we get the text of the click element if it’s not in the Data Layer?
In GTM, such thing as gtm.elementText does not exist. At all. Take a look at the dataLayer.push when you click a website element. You won’t see gtm.elementText there either because Click Text (or Form Text) variables are not Data Layer variables. They are Auto-Event Variables.
Auto-event variables return values of elements that a visitor interact with, e.g. click it, submit it (form), view it (thanks to Element Visibility trigger). With them, you can get any element attribute or the actual text (also known as the innerText).
So tu sum up, even though Element Visibility trigger has nothing to do with the Click or Form submission, all of them work with the same data of the element (regardless of whether it is in the Data Layer or in the Element itself).
Simo Ahava has explained this in greater detail here. So when the Element appears on the screen, its info can be fetched with the Form and Click variables.
In the end, this is what a trigger should look like.
<script> alert("Today is Friday"); </script>
Assign this tag to the Element Visibility trigger we’ve previously created.
Test the trigger
Refresh the Preview and Debug mode, refresh the page that you’re working on (in this case, it’s my homepage) and start scrolling down. Even before you start scrolling, you’ll see one gtm.elementVisibility event in the debug console. That’s because there’s already an element in the viewport that matches the CSS selector a.btn-bt.align-left > span. It’s the main call-to-action offering to download my Google Tag Manager e-book bundle.
However, if you click that gtm.elementVisibility event, there will be no fired tags? Why? Because our trigger condition Click Text matches LEARN MORE ABOUT THIS COURSE was not met. The same principles applies to, say, gtm.linkClick or gtm.click events. Even though you see them in the debug console, it doesn’t mean that your tags will be fired.
Scroll down until the 2nd button appears. Voilà!
One more gtm.elementVisibility event was pushed to the Data Layer but this time the tag has fired (because the Click Text variable actually contains the text we’re interested in).
Here’s the proof that we used the correct variable to fetch the button’s text. Choose the gtm.elementVisibility trigger and go to the Variables tab.
So what are better options for tracking when important elements appear on the screen?
So if you didn’t skim this blog post through but actually read it, you should remember me saying that this tracking method (Element Visibility based on text) is not reliable. If somebody (or something) changes the text (e.g. page translation, A/B test, a coworker, etc.), this method will fail.
So what are better options? In no particular order:
#1. Ask a developer to add IDs to the important website elements and use them in your Visibility Trigger.
#2. Ask a developer to add some custom data-* attributes to important elements. You could use them then not only in the Element Visibility trigger but also more efficient click tracking (read this guide to learn more)
#3. Trying to use just CSS selectors (without checking the element text). This option is not as good as the 1st of the 2nd one (because if your CSS selector is relying on too many elements and their connections, it has a higher risk to fail), but it is still better than relying on a the text of an element.
Tracking element visibility based on text: Final words
So here’s the summary: even though you can track element’s appearance on the screen based on element’s text, you shouldn’t. Why? Because (from my experience) element text has the highest chance of being changed on a page (due to various factors, like colleague’s/developer’s input, page translation, etc.).
You should consider tracking element visibility based on text ONLY as the last resort if no other options are possible AND:
- There are no other people who can change it (maybe the website is one of those that was created once and never properly updated since)
- There are no A/B tests running on a page
- And you accept the chance of people using the Translate option in their browser (in fact, you can check your GA reports to see how often this happens: keep looking to the pageviews coming from translate.google.com hostname).
And even then I’d prefer using more precise CSS Selectors. But in order to that you need to actually learn at least their basics (and I really recommend you do that).
So why did I bother writing this blog post and wasting mine/your time? Well, my Friday mood told me to do that.
If you want my honest opinion, I say that you should go and start learning CSS selectors and use them in your GTM stack asap. If you don’t have the access to developers (to add IDs or data-* attributes), you will be able to find some workarounds with selectors by yourself.