#shadow-root
De manera related, debido a que el contenido del DOM de sombra está oculto a la estructura principal, coincide con el selector CSS No se puede usar el predicado para ver qué hay dentro del elemento en el que se hizo clic.
¡Podemos solucionar este problema! No podemos usar los activadores integrados de GTM porque no nos permiten acceder a los occasion
objeto en sí. Pero podemos utilizar un detector de eventos personalizado.
Para obtener más detalles sobre cómo funciona el manejo de eventos dentro del shadow DOM, eche un vistazo a Este excelente artículo sobre el tema..
X
El boletín informativo de Simmer
Suscríbete a la Boletín informativo de Simmer ¡Para recibir las últimas noticias y contenidos de Simo Ahava en tu bandeja de entrada de correo electrónico!
Cómo funciona el manejo de eventos con el shadow DOM
Los detectores de eventos dentro del shadow DOM funcionan igual que los detectores de eventos en las estructuras DOM normales. Se registra un evento y llena una ruta a través de las capas del sitio durante el seize
y bubble
etapas.
Algunos eventos suben hacia la parte superior del árbol DOM, otros permanecen en el nodo donde se registró el evento.
La principal diferencia con el shadow DOM es que los eventos que comienzan a ascender solo cruzan el límite del shadow DOM si tienen la propiedad composed
ajustado a true
.
La mayoría de los eventos tienen composed
ajustado a true
Por lo basic, las excepciones son eventos que no se basan en interacciones de la interfaz de usuario, como estos:
Para eventos que tengan composed
ajustado a true
podemos adjuntar un detector de eventos personalizado en el doc
nodo, por ejemplo, y los eventos que tienen lugar dentro del DOM de sombra se propagarán a nuestro oyente (asumiendo que también burbujao el oyente ha sido configurado para detectar el captura fase en su lugar).
Sin embargo, todavía nos enfrentamos al problema presentado al principio de este artículo. Todos los eventos que tienen lugar en el shadow DOM se delegan automáticamente al padre del #shadow-root
Esto no es muy útil. El DOM de sombra podría ser algo enorme y extenso, por lo que necesitamos precisión.
Por suerte, podemos utilizar el Occasion.composedPath()
método para obtener una matriz que representa el camino El evento se produjo a medida que surgía. El primer miembro de la matriz es el elemento que se de hecho hecho clic (a menos que el DOM de sombra estuviera closed
pero volveremos a eso en un minuto).
Podemos utilizar esta información para construir nuestro oyente.
El oyente
En Google Tag Supervisor, crea un Etiqueta HTML personalizaday escriba o copie y pegue el siguiente código.
<script>
(perform() {
// Set to the occasion you need to monitor
var eventName = 'click on',
// Set to false should you do not need to use seize section
useCapture = true,
// Set to false if you wish to monitor all occasions and never simply these in shadow DOM
trackOnlyShadowDom = true;
var callback = perform(occasion) {
if ('composed' in occasion && typeof occasion.composedPath === 'perform') {
// Get the trail of components the occasion climbed via, e.g.
// (span, div, div, part, physique)
var path = occasion.composedPath();
// Fetch reference to the aspect that was really clicked
var targetElement = path(0);
// Verify if the aspect is WITHIN the shadow DOM (ignoring the basis)
var shadowFound = path.size ? path.filter(perform(i) {
return !targetElement.shadowRoot && !!i.shadowRoot;
}).size > 0 : false;
// If solely shadow DOM occasions ought to be tracked and the aspect just isn't inside one, return
if (trackOnlyShadowDom && !shadowFound) return;
// Push to dataLayer
window.dataLayer.push({
occasion: 'custom_event_' + occasion.kind,
custom_event: '',
elementUrl: targetElement.href
});
}
};
doc.addEventListener(eventName, callback, useCapture);
})();
script>
Puedes adjuntar un Vista de pagina Activador de esta etiqueta. Después de eso, cada clic en las páginas donde el detector está activo se enviará a dataLayer
con un contenido de objeto que se parece a esto:
En este caso, el clic recayó en un
isShadowDom
es true
).
Luego puede crear un disparador de evento personalizado para custom_event_click
:
También puedes crear variables de capa de datos para los elementos individuales en el objeto enviado de esta manera:
Al cambiar eventName
decir, submit
en su lugar, puedes escuchar los envíos de formularios.
Si desea evitar que el script envíe un mensaje con cada instancia de evento particular personpuedes agregar controles dentro de la devolución de llamada que verifiquen que el objetivo del evento period un tipo específico de elemento. Por ejemplo, para enviar a dataLayer solo si el clic aterrizó en un enlace, puedes hacer algo como esto:
var callback = perform(occasion) {
...
var targetElement = path(0);
if (targetElement.matches('a, a *')) {
// Run the dataLayer.push() right here
}
...
...
¡Nota! Aunque se trata solo de un ejemplo, debes tener en cuenta que
.matches()
No funcionará en IE y necesitarás usar.msMatchesSelector()
.
¿Qué pasa con los eventos no compuestos?
¿Qué sucede si desea realizar un seguimiento de eventos que no tienen el composed
bandera puesta a true
? Si recuerdas, esos eventos no se propagarán más allá de los límites del shadow DOM. De manera related, si usas el script anterior, también tendrán el inShadowDom
bandera puesta a false
ya que prácticamente no se dan cuenta del hecho de que están en un DOM sombra (estilo Matrix).
Por lo tanto, deberás realizar el manejo de eventos sin el poder de la delegación. En otras palabras, deberás agregar los oyentes directamente a los elementos.
Por ejemplo, si quisieras rastrear un load
evento para un Dentro del DOM de sombra, el script se vería así:
<script>
(perform() {
// Set to the occasion you need to monitor
var eventName = 'load';
// useCapture is irrelevant as we'll be monitoring the aspect itself
// useCapture = true,
// trackOnlyShadowDom is irrelevant as we'll be solely monitoring a component within the shadow DOM
// trackOnlyShadowDom = true;
var callback = perform(occasion) {
if ('composed' in occasion && typeof occasion.composedPath === 'perform') {
// Irrelevant on this answer, as we're monitoring the aspect itself
// var path = occasion.composedPath();
// Irrelevant.
// var targetElement = path(0);
var targetElement = occasion.goal;
// Irrelevant.
// var shadowFound = path.size ? path.filter(perform(i) {
// return !targetElement.shadowRoot && !!i.shadowRoot;
// }).size > 0 : false;
// Irrelevant
// if (trackOnlyShadowDom && !shadowFound) return;
// Push to dataLayer
window.dataLayer.push({
occasion: 'custom_event_' + occasion.kind,
custom_event: '',
elementTarget: targetElement.goal
});
}
};
// That is the place the script units the listener on the precise aspect within the shadow root
// The script checks if the container exists in the usual DOM, then it checks if the container
// is the shadow root, and eventually it checks if the shadow DOM has the script aspect.
var shadowContainer = doc.querySelector('.shadowDomContainer');
if (!!shadowContainer && !!shadowContainer.shadowRoot) {
var scriptTarget = shadowContainer.shadowRoot.querySelector('script#someId');
if (!!scriptTarget) scriptTarget.addEventListener(eventName, callback);
}
})();
script>
Aquí el addEventListener
La llamada al last es bastante más compleja que la genérica que usamos antes. Primero debes encontrar el nodo en el que está incrustado el shadow DOM (el raíz de sombra). Luego, accediendo a su shadowRoot
propiedad, se le permite consultar elementos dentro del DOM sombra (asumiendo que el DOM sombra es open
).
Después de las comprobaciones habituales para verificar si el elemento existe, puedes agregar tu oyente directamente al elemento, y este invocará la devolución de llamada tan pronto como registre el evento.
¿Qué pasa con un DOM de sombra cerrado?
Si el DOM de sombra se crea en closed
modo, básicamente no puedes hacer nada con el shadowRoot
Si intenta acceder a él con métodos DOM, el shadowRoot
La propiedad simplemente regresará null
y de manera related el composedPath()
devuelve una matriz de elementos que se detiene en el nodo raíz de la sombra.
Por lo tanto, a un nivel superficial, realmente no hay nada que puedas hacer para rastrear las interacciones precisas dentro del DOM de sombra.
Sin embargo, hay una solución.
Cuando se crea el DOM sombra, si los desarrolladores almacenan una referencia a él en una variable world, pueden interactuar con él y pueden agregar oyentes a los elementos en el fragmento del documento si lo desean.
// Create a shadow DOM
var container = doc.querySelector('.someContainer');
window._shadowRoot = container.attachShadow({mode: 'closed'});
En el ejemplo anterior, la variable world _shadowRoot
mantiene una referencia al DOM de sombra, y por lo tanto puede usar métodos como window._shadowRoot.addEventListener(...)
para manipular e interactuar con elementos dentro del DOM de sombra.
Requiere cierta cooperación con los desarrolladores, y también deberás justificar por qué el modo está configurado así. closed
en primer lugar, si los desarrolladores añaden una apertura mediante una variable world.
Resumen
Espero que este artículo haya sido instructivo. Tengo la sensación de que el shadow DOM es un misterio para muchos desarrolladores de análisis net, simplemente porque no es la forma más común de agregar elementos a la página net.
Sin embargo, ofrece herramientas poderosas para la encapsulación y separación de preocupaciones, y especialmente en lugar de incómodas incrustaciones de iframe, podría tener mucho sentido desde el punto de vista del desarrollo net.
Los consejos de este artículo deberían brindarle las herramientas para identificar otro problema potencial con los oyentes integrados de Google Tag Supervisor y deberían ayudarlo a abordarlo con el poder de algunas secuencias de comandos personalizadas.