Google Tag Manager (GTM) has a built in Click trigger that allows you to trigger GTM tags when the user clicks on stuff.
I believe it does this by adding a 'click' listener on document and then pushing a special 'gtm.click' event into the dataLayer when clicks are made.
In the 'gtm.click' object that is pushed into dataLayer GTM includes certain data pulled from the event.target property, including attributes of the target element such as id/class/href.
Issue is...
If you're using shadow-dom in your html the target/data will be wrong. This is due to the fact that when events bubble up through shadow-dom boundaries they "are re-targeted to look like they've come from the component rather than the internal elements within your shadow DOM".
This can be problematic if you're creating tags/triggers/variables in GTM based on the event target data and you're expecting that target to be the element which the user is actually clicking on (which seems normal).
Is there a solution for this that already exists?
Ideally GTM would fix this internally; until then, here is the solution I've come up with...
Create a document level click listener (just like GTM would) and fire custom click events but with data pulled from the original event target (rather than the re-targeted one).
So, listen for 'click' on the document and then get the original target using event.composedPath()[0]
or one of the fallbacks for the browsers that don't support composedPath. I just cobbled this together looking at different documentation and trying things in different browsers, so not sure if it's perfect.
function getOriginalTarget(ev) {
if ('composedPath' in ev) return ev.composedPath()[0]; // Standard
else if ('path' in ev) return ev.path[0]; // Old Chrome
else if ('originalTarget' in ev) return ev.originalTarget; // Firefox
else if ('srcElement' in ev) return ev.srcElement; // Old IE & Safari
else return ev.target; // Fallback to normal target.
};
document.addEventListener('click', function (ev) {
var target = getOriginalTarget(ev);
dataLayer.push({
'event': 'MyClick', // some custom event
'targetId: target.id || '' // some custom data (from original target)
// etc...
});
}, false);
I initially thought about simulating the GTM built-in click event using 'event': 'gtm.click'
but I've since concluded that it is probably not the best idea.. hacky, would cause duplicate events that need filtering, and would be confusing to someone who didn't know what was going on. Though I think one could use built-in GTM variables, like 'gtm.elementClasses': target.className || ''
, 'gtm.elementId': target.id || ''
, 'gtm.elementTarget': target.target || ''
, 'gtm.elementUrl': target.href || target.action || ''
, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With