Google Tag Manager activities – let me briefly pause here and discuss how we can handle a specific scenario using Google Analytics.
In this article, I’ll walk through a scenario involving WordPress – specifically, category and page type checks, triggering a custom event upon image clicks via Google Analytics, and visualizing image clicks using a column chart in Looker Studio. Naturally, while the main flow will follow this structure, I’ll also provide some additional details along the way.
The operations discussed in this article are part of the Looker Studio User Interaction Report.
Capturing Image Clicks with JavaScript
It’s quite straightforward to capture image interactions (such as hover, click, or move) when visitors view images on a page using JavaScript. To achieve this, we can use document.querySelectorAll() and document.getElementsByTagName() to target all img elements within the page.
document.querySelectorAll('img')
document.getElementsByTagName('img')
However, this would include all images on the page, regardless of relevance. Therefore, it’s better to narrow the scope slightly.
WordPress NextGEN Gallery Plugin
Let’s further narrow the focus and incorporate the NextGEN plugin – one of the most widely used gallery plugins for WordPress websites1.
In the gallery shown above, each image can be accessed via the selector .ngg-gallery-thumbnail-box a img. This allows us to focus our actions specifically on this element.
document.querySelectorAll('.ngg-gallery-thumbnail-box a img');
// or
// jQuery('.ngg-gallery-thumbnail-box a img').click(function() { ... });
Now that we’re focusing exclusively on the images within the gallery, we can begin monitoring click events.
const nGGallery = document.querySelectorAll('.ngg-gallery-thumbnail-box a img');
Array
.from(nGGallery)
.forEach(el => el.addEventListener('click', () => console.log(el.getAttribute('src')))
// or ...forEach(el => el.addEventListener('click', (e) => console.log(e.target.src))
);
Now, when an image is clicked, we can view the src value of the clicked image directly in the console. For example: http://138.197.191.84/wp-content/gallery/demo-gallery/thumbs/thumbs_Screen-Shot-2020-09-28-at-21.01.55.png. However, what’s more important to us is the image itself, rather than its full path. That is, the part we’re interested in is thumbs_Screen-Shot-2020-09-28-at-21.01.55.png.
const nGGallery = document.querySelectorAll('.ngg-gallery-thumbnail-box a img');
Array
.from(nGGallery)
.forEach(el => el.addEventListener('click', () => {
const image = el.getAttribute('src');
const imageSplit = image.split('/');
const imageSlashCount = imageSplit.length;
console.log(imageSplit[imageSlashCount-1]);
})
);
This process can be accomplished more efficiently using Google Tag Manager.
We’ve completed our JavaScript steps. Finally, let’s add the event definition to GTAG and proceed to the next step.
const nGGallery = document.querySelectorAll('.ngg-gallery-thumbnail-box a img');
Array
.from(nGGallery)
.forEach(el => el.addEventListener('click', () => {
const image = el.getAttribute('src'); // or event.target.src
const imageSplit = image.split('/');
const imageSlashCount = imageSplit.length;
gtag('event', 'click', {
'event_category': 'image click: ' + getCategoryName,
'event_label': imageSplit[imageSlashCount-1],
'value': 1
});
})
);
You can currently ignore the getCategoryName variable. I’ll discuss the value it holds shortly.
WordPress Conditional Tag Usage
Under the heading WordPress NextGEN Gallery Plugin, we’ll extract the JavaScript snippet and associate it with our theme by placing it in a separate file, so it runs on every page.
For this, we’ll use the functions.php file. Open the relevant PHP file and add the following code to the end:
add_action('wp_footer', 'nextGENGallery_enqueue_custom_js');
function nextGEN_Gallery_enqueue_custom_js() {
if((is_single() && !is_page() && !is_home() && !is_sticky()) || !is_tag() || is_category()) {
foreach((get_the_category()) as $category){
// https://developer.wordpress.org/reference/functions/get_the_category/
if($category->term_id == 3) { // $category->name == 'x' or $category->slug == 'tattoo-designs'
echo '<script>var getCategoryName = "'. $category->name .'"</script>';
wp_enqueue_script('custom', get_stylesheet_directory_uri().'/assets/js/custom.js', 0);
}
}
}
}
The above PHP code snippet ensures that the JavaScript content we previously created and saved to /assets/js/custom.js is only added to the footer when the page is viewed or when a category or subcategory with the ID value 3 is listed. In other words, our code runs and is used only when necessary. We do not evaluate the presence of the NextGEN Gallery plugin on any page that does not meet these conditions.
For more detailed information about the above process, see the articles titled WordPress Hooks and Conditional Tags.
Again, if you look at the relevant code, you’ll see a global variable named getCategoryName is being created. This variable retrieves the name of the displayed category and passes it through gtag. Of course, instead of using a global variable, we could also process the relevant PHP code by exposing it to JavaScript.
if($category->term_id == 3) {
echo "
<script>
const nGGallery = document.querySelectorAll('.ngg-gallery-thumbnail-box a img');
Array
.from(nGGallery)
.forEach(el => el.addEventListener('click', () => {
const image = el.getAttribute('src'); // or event.target.src
const imageSplit = image.split('/');
const imageSlashCount = imageSplit.length;
console.log(imageSplit[imageSlashCount-1]);
gtag('event', 'click', {
'event_category': 'image Click: ' + getCategoryName,
'event_label': imageSplit[imageSlashCount-1],
'value': 1
});
})
);
</script>";
}
So, what should we do if we want to preserve these additions and manage them independently of themes? For example, we might want to repeat this process across all our sites using WordPress MU.
For such situations, we can turn our modifications into a plugin. Since our code is designed to work appropriately in this context, we’ll only need to add a single header.
add_action('wp_footer', 'nextGENGallery_enqueue_custom_js');
function nextGENGallery_enqueue_custom_ js() {
if((is_single() && !is_page() && !is_home() && !is_sticky()) || is_tag() || is_category()) {
foreach((get_the_category()) as $category){
// https://developer.wordpress.org/reference/functions/get_the_category/
if($category->slug == 'tattoo-designs') { // $category->name == x or $category->term_id == 3
echo '<script>let getCategoryName = "'. $category->name .'"</script>';
wp_enqueue_script('custom', get_stylesheet_directory_uri().'/assets/js/custom.js', 0);
}
}
}
}
Just save this code under any name and place it into the /wp-content/plugins directory. Then you’ll be able to see the plugin listed under its extensions.
We’ve completed the setup for our web page. Now we can proceed to the next steps with Google Analytics and Looker Studio.
Monitoring Visual Clicks with Google Analytics and Looker Studio
Within our JavaScript code, we can use the Global Site Tag function gtag to send our event data to our Google Analytics account.
gtag('event', 'click', {
'event_category': <image category>,
'event_label': <image name>,
'value': 1
});
When viewing the event flow in our Google Analytics account in real time, we’ll see an event flow similar to the one illustrated in the image below.
You can review the gist I prepared explaining how the logic can be implemented using the is_page() condition instead of is_single(), and traversing through parent and child relationships.
Now that we have a data flow, we can access these data through Looker Studio. One of the charts that best illustrates the click density between images is the Bar Chart. Additionally, creating a Table for category, total engagement count, and similar information will also be beneficial.
Of course, we will need to filter the relevant activities by category, action, and tag; for example, Activity Category > Contains > image. Based on the information we specified in gtag, we should adjust the filter accordingly. Afterward, we can use this filter across all other fields.
If there’s a specific image name or category that we’d like to evaluate separately, we can create a new dimension for it and manage those values using REGEXP_MATCH.
CASE
WHEN REGEXP_MATCH(Activity Category, "((?i).*click:).*") THEN 'YES'
ELSE 'NO'
END
In addition, if we wish to parse a value from the image name or category field, we can use REGEXP_EXTRACT to perform the operation.
REGEXP_EXTRACT(Activity Category, 'image Click:(.*)')
After performing all these operations, the resulting visualization will resemble the following image content.
There are certainly many ways to interpret various fields in the above example scenario. Generally, I recommend using GTM for such cases. However, in some situations, it may be necessary to approach the process at a more fundamental level.