Четыре года назад в GTM появилась возможность выбирать CSS-селекторы для GTM. Со временем эта возможность из любопытной фичи превратилась в мощное средство веб-аналитики.

Перевод и адаптация статьи Симо Ахавы — CSS Selector Guide For Google Tag Manager.

У каждого элемента сайта есть свое уникальное положение: например, параграфы следуют друг за другом, а картинки расположены в разрез текста. Иногда нужный элемент найти просто: у него прописал класс или идентификатор. Но бывает и так, что нужно найти «безымянные» элементы. Или группу разных элементов по какому-то конкретному признаку. В этом случае на помощь приходят CSS-селекторы в GTM: они позволяют нацелиться на любой элемент страницы сайта.

Иногда селектор короткий. Например, селектор

div#author

 находит все элементы вида

. Поскольку у этого элемента есть идентификатор, его проще найти, и нет необходимости подробно описывать селектор.

Но бывает и так, что элемент слишком общий, и селектор разрастается:

#main > article > div.post-content.markdown > div > p:nth-child(12) > a:nth-child(2)

Это допустимо, но рискованно: селектор не сработает, если один из элементов в цепочке изменит положение или не загрузится. Чем меньше элементов перечислено в селекторе, тем ниже риск сбоя.

Разберем, как обрабатывать элементы на сайте с помощью CSS-селекторов в GTM.

CSS-селекторы в JavaScript

В JavaScript CSS-селекторы встречаются в двух важных сценариях:

Получить значение элемента текущей страницы сайта. Html-элементы по сути объекты. Часто стоит задача получить не сам объект, а выцепить и обработать определенное свойство:

// Получаем первую внешнюю ссылку на странице
var firstOutbound = document.querySelector('a:not([href="mydomain.com"])');

// Передаем первую найденную ссылку на внешний домен в dataLayer
window.dataLayer.push({
firstOutboundLinkURL: firstOutbound.getAttribute('href')
});

Для этой задачи используются два метода:

  • document.querySelector(selector)

     — получает первый элемент, соответствующий селектору

  • document.querySelectorAll(selector)

     — получает все элементы, соответствующие селектору

Селектор передается строковым типом данных (string):

// Передается первый элемент на странице
var firstOutbound = document.querySelector('a:not([href="mydomain.com"])');

// Передаются все выделенные чекбоксы и радиокнопки на странице
var allChecked = document.querySelectorAll('input[type="checkbox"]:checked,input[type="radio"]:checked');

Важно помнить, что

document.querySelectorAll

 возвращает не массив, а

NodeList

, поэтому не получится использовать встроенные методы массивов JavaScript. Придется использовать обходное решение, например, собрать все элементы с помощью

map()

, чтобы на выходе получить трансформированный массив.

// Получаем все внешние ссылки на странице
var allOutbound = document.querySelectorAll('a:not([href="mydomain.com"])');

// Создаем массив со всеми ссылками
var allHrefValues = Array.prototype.map.call(allOutbound, function(link) { return link.href; });

// Удаляем дубликаты
var uniqueHrefValues = allHrefValues.filter(function(href, index) { return allHrefValues.indexOf(href) === index; });

В этом примере вызывается метод из прототипа

Array.prototype 

для того, чтобы запустить

map()

 по списку, возвращенному через

document.querySelectorAll

.

Проверить, чтобы выбранный элемент соответствовал нужному селектору. Для этого используется

element.matches()

:

// Проверяет, чтобы кликнутый элемент являлся внешней ссылкой
function checkIfClickedElementIsOutbound() {
  var element = {{Click Element}};
  if (element.matches('a:not([href="mydomain.com"])') {
    return true;
  } else {
    return false;
  }
}

Как и в случае с

querySelector

 и

querySelectorAll

, вы обрабатываете элемент с помощью метода 

matches()

 и передаете селектор строкой. Если есть совпадение, метод возвращает 

true

 (в остальных случаях — 

false

).

element.matches()

 не поддерживается старыми браузерами, для них придется добавлять поддержку через полифил.

CSS-селекторы в GTM

Работать с CSS-селекторами можно тремя способами.

Селектор можно выбрать  при настройке переменной с типом DOM Element variable, которая возвращает только первый элемент (это поведение напоминает

document.querySelector

): 

CSS-селектор позволяет нацелиться на определенный элемент, который может и не содержать ID-атрибут

 

Селектор можно выбрать в триггере «Доступность элемента», чтобы нацелиться на все совпадающие элементы: 

 

Третий, самый полезный сценарий, — прописывать селектор для переменной Click Element. Это встроенная переменная, которую сначала нужно активировать вручную один раз:

Настроить → Клики (Click Element)

Переменная возвращает элемент на странице, который был целью триггера auto-event. Проще говоря:

  • Переменная возвращает кликнутый элемент, используя триггеры «Клик — все элементы» и «Клик — только ссылки».
  • Возвращает отправленный элемент (например, заполненную пользователем форму), для которого используется триггер «Отправка формы».
  • Возвращает видимый элемент, для которого используется триггер «Доступность элемента».

Click Element можно использовать в пользовательских переменных html и JavaScript вместе с обычными методами, как

getAttribute

,

appendChild

 и

matches

.

В GTM переменная Click Element часто используется с «соответствует селектору CSS».

Вы можете использовать «соответствует селектору CSS» чтобы проверить, совпадает ли элемент с нужным селектором: триггер сработает тогда, когда пользователь кликнет на определенный элемент на странице. В селекторе можно перечислить ненужные элементы, чтобы он не срабатывал слишком часто. Пример настройки селектора:

Можно также выбрать триггер «Все клики»

Далее перечислены примеры того, как выглядит триггер «Клик — все элементы» с разными селекторами.

Справочник по CSS-селекторам для GTM

Можно комбинировать селекторы, чтобы нацелиться на разные свойства. Комбинируемые селекторы прописываются подряд, без пробела:

a.author#simo:not([href="mydomain.com"])

Этот селектор находит все внешние ссылки

 с классом

author

 и идентификатором

id="simo"

:

Порядок перечисления произвольный, но для лучшей читаемости псевдо-классы лучше прописывать в конце (:checked, :not).

Пробежимся по селекторам:

.class

Выбирает элементы, которые имеют заданный класс в своем атрибуте

class

.

Пример:


  Simo Ahava


Селектор:

.author

Триггер сработает после клика на ссылку. Клики на

 также сработают, поскольку триггер «Только ссылки» автоматически забирает ближайшую ссылку

 у любого кликнутого элемента.

#id

Выбирает элементы, которые имеют заданный идентификатор

id

Селектор:

#date

 

Триггер сработает после клика на

...

.

element

Выбирает элементы с заданным

element

 (например,

 для ссылок,

 для изображений).

  
Здесь и далее в качестве триггера выбран «Клик — все элементы»

Селектор:

img#simo

 

Триггер сработает после клика на

. Поскольку селектор сочетает

element

 и

id

 , выбранный элемент страницы должен быть картинкой с идентификатором

simo

.

element1,element2

Выбирает элементы, которые могут быть выбраны с любым из селекторов, перечисленных через запятую. Можно перечислять несколько селекторов.


  
  

Name: Simo Ahava

Селектор:

img#simo_img

,

p#simo_name

 

Триггер сработает после клика по любому элементу:

 или

...

element1 element2

Сработает на самом правом элементе

element2

, когда он вложен внутри левого элемента

element1

 (это необязательно родительский элемент — достаточно, чтобы

element2

 находился внутри него).

Hello world!

Селектор:

section#main h1

 

Триггер сработает после клика на

Hello world!

, поскольку он вложен внутри выбранного слева тега

section#main

.

Подстановочный знак * (wildcard)

Выбирает любой элемент. Удобен, если использовать вместе с триггером «Все элементы».

Селектор:

div#navi, div#navi *

Триггер сработает после клика на

 или любой другой из вложенных элементов

    ,

  • ,

    .

    Первый селектор отслеживает клики на

    . Второй — на любой другой элемент, который вложен внутри

    . Если второй селектор был бы

     *

    , он бы отслеживал клики только по

      , поскольку это прямой дочерний элемент селектора

      .

      element1>element2

      Сработает на самом правом элементе

      element2

      , когда он выступает родительским элементом по отношению к

      element1

      .

      Hello world!

      Селектор:

      div>h2

       

      Результат: Триггер сработает после клика на

      Goodbye world!

      , который является дочерним по отношению к

      . Он не сработает на

      Hello world!

      , поскольку это дочерний элемент

      .

      element1+element2

      Сработает на самом правом элементе

      element2

      , когда он идет сразу же после

      element1

      . У обоих элементов должен быть общий родительский элемент.

      Author name

      Селектор:

       

      Триггер сработает после клика на

      , поскольку он идет сразу после

      .

      element1~element2

      Сработает на самом правом элементе

      element2

      , когда ему предшествует

      element1

      . У обоих элементов должен быть общий родительский элемент. Этот селектор менее строгий, чем element1+element2, поскольку

      element1

      необязательно должен находиться рядом с

      element2

      .

      Селектор:

      img#author_image~a

       

      Триггер сработает после клика на

      , потому что ему предшествует

      .

      [attribute]

      Сработает, когда у элемента есть заданный атрибут.

      GTM examples

      Селектор:

      div[data-name]>span

      Триггер сработает, когда происходит клик по

      , потому у него прямой родительский элемент — 

       с атрибутом

      data-name

      .

      [attribute=value]

      Сработает, когда у элемента есть заданный атрибут с определенным значением.

      GTM example
      Another GTM example

      Селектор:

      div [data-name=”second_gtm_example”]>span

       

      Триггер сработает после клика на второй

      , поскольку только у него есть прямой родительский элемент с атрибутом

      data-name="second_gtm_example"

      .

      [attribute^=value]

      Сработает, когда у элемента значение атрибута начинается с заданного значения.

      Product 12345 Product 23456 Attachment 12345

      Селектор:

      span[id^=”product”]

      Триггер сработает после клика на одном из двух элементов

       с идентификатором, начинающегося на слово

      product

      . В третьем элементе триггер не сработает, потому что идентификатор начинается с другого слова.

      [attribute$=value]

      Сработает, когда значение атрибута элемента заканчивается на заданное значение.

      Product 12345 Product 23456 Attachment 12345

      Селектор:

      span[id$="_12345"]

      Триггер сработает после клика на первый или третий элемент

      , поскольку у обоих идентификатор заканчивается на

      _12345

      . На втором элементе триггер не сработает.

      [attribute*=value]

      Сработает, если элемент не соответствует значению в скобках.

      Simo's profile Benjamin's profile Derek's profile

      Селектор: div#author > span[id*="simo"]

      Триггер сработает после клика на одном из первых двух элементов, поскольку они содержат слово

      simo

      .

      :checked

      Сработает, когда заданный элемент выбран пользователем (поставлена галочка, выбран кружочек, выбран пункт меню).

      My name:
      I consent to everything

      Селектор:

      input[name=”consent”]:checked

       

      Триггер сработает после того, как пользователь поставит галочку в чекбоксе.

      :first-child и :last-child

      Триггер с

      :first-child

       сработает у первого дочернего элемента, с

      :last-child

       — у последнего.

      Селекторы:

      ul#main_navigation > li:first-child
      ul#main_navigation > li:last-child

      :first-child

       сработает после клика по первому дочернему элементу —

    • GTM
    • .

      :last-child

       сработает после клика по последнему дочернему элементу —

    • Death metal
    • .

      :first-of-type и :last-of-type

      Триггер с

      :first-of-type

       сработает на первом дочернем элементе заданного типа.

      :last-of-type

       — на последнем.

      Simo Ahava

      Web Analytics Developer

      Ukulele and death metal enthusiast

      Селекторы:

      div#author_info > p:first-of-type
      div#author_info p:last-of-type

      Триггер с

      :first-of-type

       сработает после клика по

      Web Analytics Developer

      , поскольку это первый

      -элемент внутри родительского элемента

      .

      Триггер с

      :last-of-type

       сработает после клика по

      Ukulele and death metal enthusiast

      .

      :not(selector)

      Сработает, если у элемента значение в скобках не совпадает с указанным.

      Селектор:

      a:not([href*="simoahava.com"]}

       

      Результат:

      Триггер сработает после клика по второй ссылке, поскольку селектор выбирает все ссылки за исключением тех, которые содержат

      [href*="simoahava.com"

      .

      :nth-child(n)

      Сработает у определенного дочернего элемента.

      n

       — номер элемента

      Селектор:

      ul#main_navigation > li:nth-child(2)

       

      Триггер сработает у второго элемента —

    • Ukulele
    • .

       

      Большая часть веб-аналитики основана на способности отслеживать взаимодействия с определенными элементами. Часто нам рекомендуют использовать id и class, но бывает и так, что у элемента нет ни класса, ни идентификатора.

      В этом случае помогают CSS-селекторы. Они позволяют определить каждый элемент на странице, поскольку у каждого элемента всегда есть своя уникальная позиция, которую можно отслеживать.

      Чем короче селектор — тем лучше он поможет найти элемент на странице.

      ©