Отслеживание полей формы в Яндекс.Метрике

31 мая, 2023

Подробное руководство по отслеживанию заполнений полей формы на вашем сайте для Яндекс.Метрики с использованием Google Tag Manager.

Введение

Интернет-маркетологи и веб-аналитики дошли уже до того уровня знаний и развития, когда могут без сторонней помощи выполнять сложные настройки для своего сайта и проектов заказчика, используя не только встроенный функционал счетчиков аналитики, но и вспомогательные инструменты, существенно упрощающие сами отслеживания и позволяющие передавать дополнительную информацию по совершаемым событиям в Яндекс.Метрику, Google Analytics, VK Рекламу и другие сервисы.

Именно JavaScript и Google Tag Manager - то, что поможет вам в решении данной задачи. Как и пять лет назад, когда я в блоге опубликовал статью Навыки и знания, необходимые в работе с Google Tag Manager, так и сейчас, я придерживаюсь того же мнения относительно компетенций и знаний современного специалиста. А с учетом развития IT-технологий, онлайн-образования, искусственного интеллекта и нейросетей в последние несколько лет, процесс изучения новых дисциплин и направлений стал проще и увлекательнее.

Если вы давно читаете мой блог, то наверняка видели материалы подобные этому и ранее. Например, целую лекцию по работе с различными элементами на странице на YoTube-канале:

Были еще и отдельные статьи по данной теме:

Во всех этих руководствах упор делался на связку продуктов Google - Google Tag Manager и Google Analytics. В этой публикации я разберу практический пример отслеживания различных полей с передачей этой информации в Яндекс.Метрику с помощью диспетчера тегов Google, JavaScript и параметров визитов. Это позволит вам обогатить свои отчеты новыми данными и еще точнее и глубже проводить анализ аудитории сайта с использованием соответствующих группировок, создавать сегменты и даже определять пользователей для ретаргетинга.

В качестве примера разберем форму подарочного сертификата на одном из моих тестовых сайтов. Выглядит она так:

Пример формы с полями

В ней присутствуют как стандартные поля для ввода информации, так и более сложные HTML-элементы для отслеживания. Например, переключатель (радиокнопка). Его настройка чуть сложнее, чем просто извлечь данные из классических полей (имя, телефон, e-mail и т.д.), но тоже выполнима. В зависимости от того, какое количество полей в форме на вашем сайте и какие типы они имеют, вы должны использовать определенные типы отслеживания.

Так или иначе, отслеживание различных полей формы на любом сайте с помощью Google Tag Manager сводится к двум простым действиям:

  1. определение типа поля в структуре HTML-элементов;
  2. использование переменной уровня данных (dataLayer) или собственного кода JavaScript для извлечения данных из самого поля;

Конечно же, необходимо еще совершить все оставшиеся настройки в диспетчере тегов Google - создать триггер активации и аналитический тег. Но ключевое - это понять, каким способом можно извлечь нужную информацию из того или иного поля/элемента формы, сохранить это значение в переменной, чтобы впоследствии вместе с активацией тега отправить данные в Яндекс.Метрику в качестве параметров визита.

Но перед тем, как мы начнем выполнять все эти настройки, я напоминаю: загрузка данных, которая может идентифицировать личность пользователя, запрещена политикой Яндекса. Но вы можете использовать данный способ для передачи, например, ID заявки, региона, комментария из формы и т.д. 

Давайте приступим!

Определение типов полей в структуре HTML-элементов

Для сбора пользовательских данных, как правило, используются формы. В HTML формы размечаются тегом <form>:

Такая форма внутри себя содержит элементы формы. Элементы формы - это различные типы элементов ввода, такие как текстовые поля, флажки, переключатели, кнопки отправки и многое другое. Самыми распространенными элементами формы являются элементы <input>.

Элемент <input> отображается несколькими способами, в зависимости от атрибута type:

  • <input type="text"> - однострочное поле ввода текста;
  • <input type="password"> - поле с паролем (Вебвизор в Яндекс.Метрике не записывает данные полей с таким типом);
  • <input type="radio"> - переключатель (для выбора одного из многих вариантов);
  • <input type="range"> - ползунок;
  • <input type="checkbox"> - флажок;
  • <input type="file"> - поле для отправки файла (file);
  • <input type="reset"> - кнопка для очистки формы;
  • <input type="submit"> - кнопка для отправки формы;
  • и другие.

Также существуют элемент <textarea>, который представляет собой элемент формы для создания области, в которую можно вводить несколько строк текста. В отличие от тега <input> в текстовом поле допустимо делать переносы строк, они сохраняются при отправке данных на сервер.

Таким образом, 99% всех форм в интернете для ввода какой-либо информации используют элементы двух типов - <input> и <textarea>. Именно их вам и нужно научиться отслеживать.

Для того, чтобы узнать тип конкретного поля формы, вам нужно сделать следующее - поставить курсор мыши внутрь самого поля, нажать правой кнопкой мыши и выбрать пункт Просмотреть код:

Просмотреть код

Вам откроется консоль разработчика в браузере (клавиша F12 для Google Chrome) с уже выделенным/проинспектированным полем:

Инспектирование конкретного поля

Как видите, у поля Имя получателя тип text - это текстовое поле для ввода информации согласно HTML-разметке. Поочередно выделяя каждое поле формы, выпишите всех их типы из атрибута type. В моем примере это будет так:

  • Имя получателя - text (текстовое поле);
  • Email получателя - text (текстовое поле);
  • Ваше имя - text (текстовое поле);
  • Ваш Email - text (текстовое поле);
  • Сумма - text (текстовое поле);

А вот поле Сообщение имеет другой тег - textarea:

Элемент textarea

Еще и поле Тема подарочного сертификата имеет тип radio - переключатель:

Элемент input с типом radio

Получается, что в моей тестовой форме 7 полей для отслеживания:

  • 5 полей с тегом input и типом type;
  • 1 поле с тегом input и типом radio;
  • 1 поле с тегом textarea.

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

Извлечение данных из полей формы

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

  1. использовать переменные уровня данных;
  2. написать собственные коды на JavaScript для извлечения данных из каждого поля.

В чем заключается отличие?

1. Использование переменных уровня данных

С помощью Google Tag Manager вы можете отслеживать любые события (взаимодействия) пользователей на вашем сайте. Все они могут быть добавлены одно за другим в объект dataLayer, а затем извлечены из уровня данных и использованы вместе с нужным триггером активации, пока страница не обновится или пользователь не покинет ее.

Это справедливо и для отслеживания формы. Когда пользователь отправляет форму, событие отправки формы, а также значения полей формы регистрируются в dataLayer. Затем GTM воздействует на это событие отправки формы, используя триггер отправки формы, и выясняет, что делать с информацией, которая только что была добавлена ​​в dataLayer. Сами значения полей формы будут отображаться в dataLayer после отправки формы.

Конечно же, все зависит от того, имеет ли ваша форма стандартный тип разметки (тег <form> и кнопку <submit>), или не имеет. Если да, то вы можете попробовать выполнить то, что я буду показывать ниже. Если нет - вам нужно использовать собственные коды на JavaScript или писать техническое задание и поручать эту задачу разработчику.

Поскольку в моем примере форма создана через тег <form> и имеет кнопку с типом submit:

Форма с тегом <form> и кнопкой для отправки submit

То я могу использовать стандартный триггер Отправка формы в качестве условия активации тега:

Триггер "Отправка формы"

Активировав режим предварительного просмотра Google Tag Manager и заполнив все поля формы, отправим тестовое обращение. На шкале событий отобразится триггер Form Submit, свидетельствующий о регистрации события отправки формы.

Триггер отправки формы

Если вы откроете API Call, то можете увидеть, какая информация доступна на уровне данных в различных переменных при совершении этого события:

API Call

Это информация, хоть и полезна, но не дает полного представления о том, что же сохранилось в переменной уровня данных gtm.element, поскольку она является объектом (тип данных object). Чтобы узнать подробности, перейдите в консоль разработчика на вкладку Console.

Примечание: важно, чтобы после отправки формы информация на уровне данных сохранилась, то есть была доступна на странице после ее отправки. Если вы отправили тестовую форму и вас перенаправило на другую страницу, на которой уровень данных обновился, или страница просто обновилась, то вы не сможете проанализировать dataLayer, поскольку вся информация на новой странице обнулилась/перезаписалась.

Теперь на вкладке Console мы можем написать конструкцию dataLayer и нажать Enter:

dataLayer в консоли разработчика

Нажав на черный треугольник, вы откроете список всех dataLayer.push событий, которые произошли на странице:

Список dataLayer.push событий

Событие отправки формы - это gtm.formSubmit, поскольку в качестве триггера активации в данном примере используется Отправка формы. Раскроем его:

Раскрытие gtm.formSubmit

Когда произошла отправка формы, на уровень данных передались значения некоторых переменных - gtm.elementClasses, gtm.elementId, gtm.elementTarget, gtm.elementUrl.

Значения переменных на уровне данных (dataLayer)

Все они имеют строковый тип данных (string). И только переменная уровня данных gtm.element является объектом (object) и имеет еще вложенность. Нажав еще раз на черный треугольник напротив переменной, вы увидите множество других ключей и их знаний, к которым у вас есть доступ:

Ключи в переменной gtm.element

Элементы с индексами 0,1,3..., 10 - это и есть элементы самой формы, где порядковый номер - это конкретный элемент формы. 0 - это первое текстовое поле с именем получателя, 1 - поля с e-mail'ом получателя и т.д. Вы можете убедиться в этом самостоятельно, просто наведя курсор на любой из них. В самой форме на сайте этот элемент подсветится:

Элементы формы в dataLayer

У каждого элемента есть еще вложенность, то есть его можно раскрыть еще глубже, чтобы найти итоговый ключ, в котором в свойстве будет сохранено значение из извлекаемого поля. Например, раскрыв поле Ваш Email, в котором я ввел значение электронной почты, я увижу его в ключе gtm.element в свойстве value:

Значение текстового поля в свойстве value

Раскрывать вложенность и искать итоговое значение нужно до тех пор, пока вы не найдете свойство, в котором будет отображаться введенная в поле информация. Как только вы найдете такое свойство, вам необходимо определить конечный путь к этому ключу. Для этого правой кнопкой мыши нажмите на полученное свойство и выберите пункт Copy property path:

Copy property path

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

Скопированный путь к свойству объекта gtm.element

Теперь полученный путь необходимо изменить на тот, который будет понятен Google Tag Manager. Для этого используйте точечную нотацию. Таким образом, итоговое значение, которое мы скопировали, будет трансформировано в gtm.element.3.value

Именно такую конструкцию (у вас конечный путь к ключу объекта gtm.element для конкретного поля будет другим) нужно вставить в новую переменную типа Переменная уровня данных:

Переменная уровня данных для конкретного поля

Сохраните переменную, задав ей имя. Теперь то же самое нужно проделать для всех оставшихся полей формы:

  • в объекте dataLayer раскрыть gtm.element;
  • спуститься на уровень ниже в конкретном поле формы;
  • найти конечное свойство с заполненным значением;
  • скопировать путь к этому ключу;
  • используя точечную нотацию, трансформировать его в имя переменной уровня данных;
  • в интерфейсе GTM создать столько переменных уровня данных, сколько полей в вашей форме.

Поскольку поля формы по расположению остаются неизменны в самой форме, то и ключи объекта gtm.element будут для этой формы всегда с такими индексами. В моем примере получились следующие имена переменных уровня данных:

  • Имя получателя - gtm.element.0.value
  • Email получателя - gtm.element.1.value
  • Ваше имя - gtm.element.2.value
  • Ваш Email - gtm.element.3.value
  • Сообщение - gtm.element.7.value
  • Сумма - gtm.element.8.value

Самое сложное - это извлечь таким способом данные о переключателе, потому что в ключе gtm.element каждое значение радиокнопки имеет собственный индекс:

Каждый элемент радиокнопки со своим свойством

  • gtm.element.4.value - День рождения
  • gtm.element.5.value - Другое
  • gtm.element.6.value - Новый год

Но при заполнении формы можно выбрать только одно из них. То есть сначала нужно проверить на условие выбора, и лишь после того, как мы найдем нужный элемент, который выбрал пользователь, извлечь его значение. Как это сделать?

Примечание: с помощью свойств объекта gtm.element легко можно извлекать значения для input и textarea, но только с текстовым содержимым (type = text). Для других типов рекомендуется использовать собственный код JavaScript.

К сожалению, простого способа извлечения значения с помощью переменной уровня данных для радиокнопки нет, поскольку каждую переменную нужно проверять на дополнительное условие (был ли переключатель установлен напротив gtm.element.4, gtm.element.5 или gtm.element.6). А это уже программирование и написание собственного кода. Именно этот вариант я разберу чуть дальше.

А пока давайте проверим корректность извлечения данных с помощью переменных уровня данных. Для этого повторно запустим режим отладки Google Tag Manager и снова отправим тестовое обращение. Затем на шкале событий выберем триггер Form Submit и откроем вкладку Variables:

Проверка корректности настройки переменных уровня данных

Если вы видите значения полей формы, введенных в самой форме, значит вы все сделали правильно! В противном случае перепроверьте ключи gtm.element и их свойства.

2. Собственный код JavaScript

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

А также прочитать несколько материалов, связанных с селекторами, поскольку без фундаментальных основ работы вам будет сложно выполнять все последующие сценарии для своего проекта:

Если в предыдущем примере мы использовали объект gtm.element и свойство value конкретного ключа для извлечения значений каждого поля формы, то сейчас нам придется использовать программирование и переменную типа Собственный код JavaScript, с помощью которой мы и будем извлекать значения полей формы, включая поле с радиокнопками.

Для этого вам необходимо проинспектировать каждый элемент формы (как вы это делали на предыдущем шаге) с использованием консоли разработчика. Только теперь, выделив нужное поле формы, в инспекторе элементов нажмите на него правой кнопкой мыши и выберите Copy - Copy selector:

Копирование селектора

Благодаря этому вы скопировали селектор конкретного поля формы. Вы можете перейти на вкладку Console и вставить эту строчку кода, нажав Enter:

, где вместо selector вы вставляете ваше значение скопированного селектора.

Если на вашем сайте установлена библиотека jQuery, то вы можете использовать другую конструкцию:

или

, где вместо selector вы также вставляете значение вашего скопированного селектора.

Проверка конструкции извлечения (три способа)

Все три вышеприведенных способа выполняют одну и ту же функцию - они извлекают значение из поля формы с заданным селектором. Только в первом случае используется классический JavaScript-код и конструкция document.querySelector, а в двух других - команда для jQuery с функцией val.

Если в консоли разработчика после выполнения кода вы видите нужный результат, то эту конструкцию вы можете использовать в новой переменной типа Собственный код JavaScript, взяв за основу нижеприведенный код:

, где вместо variable1 во всех местах вы можете задать свое собственное имя переменной. Например, если вы извлекаете значение из поля Имя, то variable1 можете заменить на user_name (во всех местах кода!) или любое другое, а вместо selector вы вставляете ваше значение скопированного селектора.

В результате у вас должно получиться примерно так:

Переменная с собственным кодом JavaScript для конкретного поля

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

Затем на шкале событий выберете триггер Form Submit и откройте вкладку Variables:

Проверка корректности настройки переменной с собственным кодом JS

Если собственный код JavaScript написан верно, то для текущего события отправки формы ваша переменная примет правильное значение из этого поля формы. Если нет, то вам нужно перепроверить селектор конкретного поля и сам код JS.

Повторите все эти действия для других полей формы:

  • проинспектируйте каждое поле формы;
  • скопируйте селектор для каждого из них с помощью опции Copy - Copy selector;
  • создайте столько переменных собственного кода JavaScript, сколько полей в вашей форме;
  • вставьте в них вышеприведенный код, заменив селектор и название переменной на свои;
  • сохраните переменные, задав для них отличительные имена.

Но как быть с переключателем в форме? Как отследить значение выбранного элемента? Точно так же, как и с обычными текстовыми полями, необходимо проинспектировать элемент с типом radio, чтобы найти его селектор:

Инспектирование переключателя

Но нам нужен селектор не для конкретного элемента, а общая конструкция для трех вариантов подарочного сертификата - День рождения, Другое и Новый год. Такой общей конструкцией для моего примера будет являться input[type=radio]. А чтобы выделить конкретный элемент, который выбрал пользователь, необходимо добавить атрибут checked, который как раз и будет возвращать тот элемент, который был выбран.

Перейдя в консоль разработчика на вкладку Console, можно добавить эту конструкцию целиком, чтобы убедиться, что JavaScript возвращает нужный элемент формы. Код классического JS будет выглядеть так:

Если на вашем сайте установлена библиотека jQuery, то вы можете использовать другую конструкцию:

или

Возврат выбранного элемента

Вышеприведенные конструкции возвращают выбранный HTML-элемент, но не его значение. А чтобы вернуть само значение выбранного элемента (День рождения, Другое и Новый год), необходимо в структуре DOM-дерева подняться на уровень выше и посмотреть в каком узле хранится эта информация:

Родительский узел со значением выбранного переключателя

Как видно из скриншота выше, значение выбранного элемента содержится между тегами <label></label>. Для извлечения этих данных в JavaScript есть свойство parentElement, которое возвращает элемент, являющийся родителем данного узла.

Свойство parentElement

Но нам нужен не элемент, являющийся родителем данного узла, а само текстовое значение. Поэтому к итоговой конструкции нужно добавить свойство innerText, которое получает его текстовое содержимое. Получится для классического JavaScript:

Для jQuery:

или

, где вместо input[type=radio] и label вы вставляете собственные селекторы для переключателя.

Возврат выбранного элемента

Примечание: в вашем примере родительский узел может иметь несколько уровней, например parentElement.parentElement. Универсальной конструкции нет, для своего проекта вам нужно будет отыскать конечное значение самостоятельно.

Именно такую конструкцию необходимо добавить в переменную собственного кода JavaScript в Google Tag Manager:

, где вместо certificate вы можете задать собственное название переменной.

Переменная с собственным кодом JavaScript для радиокнопки

Сохраните изменения.

После того, как вы создали переменные собственного кода JavaScript для извлечения всех полей форм, настало время совершить финальную отладку. Для этого повторно запустим режим отладки Google Tag Manager и снова отправим тестовое обращение. Затем на шкале событий выберем триггер Form Submit и откроем вкладку Variables:

Проверка корректности настройки переменных с собственным кодом JavaScript

Если вы видите значения полей формы, введенных в самой форме, значит вы все сделали правильно! В противном случае перепроверьте селекторы элементов и итоговые конструкции кода.

Примечание: если форм на вашем несколько, и вы желаете отслеживать их все, тогда вам нужно для каждой формы создать собственные переменные для извлечения значений полей формы, задав уникальные селекторы. Если у этих форм селекторы полей одинаковы, тогда вы можете использовать их для всех отслеживаемых форм.

Теперь, когда вы успешно создали переменные уровня данных и научились применять собственные коды JavaScript, вы можете свободно использовать их где угодно. Например, вы можете использовать их в параметрах визита Яндекс.Метрики (см. дальше), параметрах события Google Analytics 4, в других переменных или в качестве дополнительного условия активации или блокировки триггера. Возможностей много.

Сейчас нас интересует отслеживание полей формы для Яндекс.Метрики, поэтому давайте завершим настройку для этого счетчика аналитики.

Создание триггера

Чтобы вы смогли передать значения полей формы в Яндекс.Метрику, вам необходимо создать триггер активации. Таким триггером в этом примере является Отправка формы.

Триггер "Отправка формы"

Но для вашего сайта он может быть другим. Подробнее ознакомиться с возможностями отслеживания отправки формы с помощью диспетчера тегов Google вы можете в этой статье.

Создание цели в Яндекс.Метрике

Поскольку отслеживание отправки формы - это событие, то вам необходимо зайти в свой счетчик Яндекс.Метрики и создать цель типа JavaScript-событие. В качестве идентификатора цели вы можете задать произвольное название, например, send_form с условием совпадает:

JavaScript-событие для отправки формы

Скопируйте код цели, он вам пригодится на следующем шаге настройки в Google Tag Manager. Чтобы передавать значения полей формы кода цели с методом reachGoal будет недостаточно. Вам необходимо использовать метод params вместе с JavaScript-событием, добавив в конце скопированного кода цели еще один аргумент. Именно в нем будут передаваться дополнительные параметры, именуемые в Метрике параметрами визитов.

Параметры визитов – те данные, которые могут быть привязаны к визиту пользователя. Например, точное время совершенного события, значения выбранных полей формы или введенной в них информации, идентификатор заявки (если он генерируется на вашем сайте), URL-адрес страницы, на которой было совершено это событие, значение промокода или скидки, добавленного в отдельное поле, номер/вариант эксперимента и т.д. и т.п.

Примечание: подробнее о том, как передавать различные параметры визитов (один, несколько, 10, с ценой цели), включая статистические и динамические, читайте в этом материале.

Таким образом, конструкция, которую вам необходимо использовать для передачи параметров визита вместе с событием, следующая:

, где:

  • XXXXXX – идентификатор счетчика Яндекс.Метрики;
  • reachGoal – метод для отслеживания цели типа JavaScript-событие;
  • target – идентификатор цели:
  • params – параметры визита;

Такую конструкцию вы скопировали из интерфейса Яндекс.Метрики при создании JS-события, но без последнего аргумента params. Именно его вместе с созданными ранее переменными уровня данных требуется прописать в конце кода цели.

Создание тега

В завершение настройки создайте тег типа Пользовательский HTML и вставьте туда свой код цели для события отправки формы, а в конце кода цели пропишите четвертым параметр визита:

, где вместо XXXXXX  - идентификатор вашего счетчика, а в объекте formFields вы перечисляете в виде пары ключ:значение свои собственные названия полей и их значения, которые извлекаются с помощью созданных на предыдущем шаге переменных.

В Google Tag Manager это будет выглядеть так:

Тег Яндекс.Метрики

В качестве триггера активации выберите событие отправки формы, настроенное на предыдущем шаге.

Проверка настроек

Сохранив тег и опубликовав изменения в контейнере GTM, проверьте корректность передачи данных с помощью специального расширения Yandex Metrica Debugger или Яндекс.Метрика Инспектор. Для этого зайдите на свой сайт, заполните все поля формы и отправьте тестовую заявку. На шкале отладки вы должны увидеть ваше событие с переданными значениями параметров визита:

Проверка отслеживания отправки формы с полями (Яндекс.Метрика Инспектор)

Через некоторое время статистика станет доступна в отчетах Яндекс.Метрики. Общее количество достигнутых целей по отслеживанию отправки формы можно посмотреть в отчете Конверсии:

Отчет по конверсиям

А сами параметры через некоторое время отобразятся в отчете Параметры визитов (Отчет - Содержание - Параметры визитов). Раскрыв список параметра визита Отправка формы, внутри вы увидите все поля формы и их значения, которые вы отслеживаете:

Отчет "Параметры визитов" с данными полей формы

Из вашего отчета может быть удалена часть данных, поскольку детализация до уровня отдельных визитов и посетителей в Яндекс.Метрике отключена для исключения рисков деанонимизации пользователей. Показываются только строки с информацией не менее чем по 10 посетителям. Об этом свидетельствует соответствующая надпись над отчетом:

Из отчета могли быть удалены чувствительные данные

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

В Яндекс.Метрике параметры визитов можно использовать в качестве условия группировки и сегментации. Таким образом, вы сможете создать более детальные срезы, анализировать их, а также определять, какие услуги у вас самые востребованные, какого специалиста чаще всего выбирают, в какое время и т.д. и т.п. Медицина, банковские услуги, автомобильная тематика, недвижимость, интернет-магазин, производство - значения не имеет. Благодаря параметрам визитов вы можете существенно расширить данные вашего счетчика Яндекс.Метрики, передавая вместе с JavaScript-событием еще и параметры. Это очень похоже на параметры событий Google Analytics 4, которые вы можете передавать вместе с самим событием.

Еще материалы, которые могут быть вам полезны по данной теме:

Получайте бесплатные уроки и фишки

По контекстной, таргетированной рекламе и аналитике