Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issues with Google Tag Manager's built in Click trigger and shadow-dom

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?

like image 924
devlop Avatar asked Oct 03 '17 16:10

devlop


1 Answers

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.

like image 110
devlop Avatar answered Sep 21 '22 08:09

devlop