{"id":14268,"url":"\/distributions\/14268\/click?bit=1&hash=1e3309842e8b07895e75261917827295839cd5d4d57d48f0ca524f3f535a7946","title":"\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0442\u044c \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u0430\u043c \u0438\u0433\u0440\u0430\u0442\u044c \u043d\u0430 \u0440\u0430\u0431\u043e\u0447\u0435\u043c \u043c\u0435\u0441\u0442\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e?","buttonText":"\u0423\u0437\u043d\u0430\u0442\u044c","imageUuid":"f71e1caf-7964-5525-98be-104bb436cb54"}

Контекстный кодинг: как улучшить работу с Google Tag Manager с помощью программирования

Пошаговая инструкция на примере GTM вместо Yagla.

В комментариях к статье «Google Tag Manager вместо Yagla» меня спросили, как реализовать текстовую подмену, если переменная podmena не равна заданному слову, а содержит его. Допустим, если в переменной есть слово «москва», а на сайте должно отобразиться «дешёвые слоны в Москве». Фактически — как использовать текстовую подмену на сайтах ещё эффективнее. Задача нетривиальная настолько, что достойна отдельной статьи.

Привет, я Александр Зарайский, руководитель обучающего центра контекстного рекламного агентства MOAB. Сегодня я покажу вам, как упростить работу в Google Tag Manager с помощью кодинга. Если вы ещё не читали мою статью «Google Tag Manager вместо Yagla», рекомендую сначала ознакомиться с ней, так как разобранный здесь пример сделан на её основе.

В чём вообще проблема?

Допустим, вы сделали текстовую подмену по инструкции из прошлой статьи. Теперь у вас в ссылке есть переменная podmena. Если вписать в неё значение, которое вы добавили в таблицу поиска — например, «москва», — то новый заголовок подставится автоматически. Вот так:

Но что, если вы захотите, чтобы переменная передавала не вписанные значения, а, допустим, значение {keyword} из вашей UTM-метки? Например, «купить инкубатор москва» или «купить инкубатор в москве», или даже просто слово «москве». Вот что получится:

Что-то пошло не так. Конечно, мы можем вписать в таблицу поиска каждое требуемое значение, но это очень долго. Да и редактировать таблицу поиска в дальнейшем будет трудно, особенно если накопится много ключевых слов. Таблица поиска может разрастись до нескольких сотен или даже тысяч строк, работать с которыми придётся вручную. Перспектива неприятная.

Впрочем, есть более простой и удобный вариант — именно его мы разберём.

Пошаговый алгоритм

Вот такой результат мы должны получить:

Давайте разбираться, как это сделать.

У нас есть готовая таблица поиска podmena, которая принимает три значения и даёт на выходе конкретный текст для заголовка:

Значения подтягиваются из URL переменной «Запросы для подмены».

В общем, всё, что мы делали для создания подмены, работает корректно.

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

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

Чтобы этого добиться, нужно сделать «прокладку» между podmena и таблицей поиска. Речь о «прокладке» в виде отдельной функции, которая будет проверять значение podmena, искать нужные фразы и передавать результат таблице поиска. Тем самым выполняя условие «содержит».

Звучит сложно? Всё не так страшно, давайте сделаем и разберём результат.

Для начала создадим новую переменную типа «Собственный код JavaScript» и назовем её «Проверка переменной podmena».

Оставить эту переменную пустой нельзя, потому сразу заполним её кодом. Те, кто хорошо знаком с JavaScript, спокойно добавляют код, сохраняют переменную и читают дальше. Для тех, кто не знает этого языка программирования, я добавил подробные объяснения.

Сам код:

function() { var podmena; //объявление новой переменной podmena = {{Запрос для подмены}}; //записываем значение podmena из URL в переменную return podmena; //возвращаем значение переменной }

Вот что мы сделали:

  • Объявили функцию JavaScript.
  • Объявили переменную.
  • Записали значение «Запрос для подмены» в переменную.
  • Сделали так, чтобы функция возвращала значение podmena в качестве результата.

Теперь подробный разбор:

1. Объявление функции JavaScript — комбинация «function()». Рабочие процессы функции обрамлены в фигурные скобки:

«function() { }»

Обычно фигурные скобки пишут с новой строки для удобства понимания.

2. Мы создали переменную комбинацией «var [название переменной]». Необязательно называть переменную podmena. Можно, например, назвать переменную «var p», но это будет менее понятно, правда? Чтобы не запутаться в коде, выбирайте понятные названия для переменных.

Любое объявление переменной заканчивается точкой с запятой:

«var podmena;»

Так компьютер поймёт, что это отдельная переменная.

3. Мы указали, что переменная podmena равна значению из URL переменной «Запрос для подмены»:

podmena = {{Запрос для подмены}};

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

4. Теперь переменная podmena имеет точно такое же значение, что и «Запрос для подмены», и последнее, что делает функция, это возвращает значение:

return = podmena;

Функция будет возвращать значение, где бы она ни была вызвана. Теперь мы эту функцию прикрепим к таблице поиска, и перемычка готова! Смотрите:

Если в таблицу поиска установить в качестве входной переменной новую функцию, будет происходить вот что:

  • Podmena в URL передаёт значение в «Запрос для подмены».
  • «Запрос для подмены» передаёт значение в функцию.
  • Функция передаёт значение в таблицу поиска.

Так функция становится нужной нам перемычкой. Но пока она ещё ничего не делает с тем значением, которое получает. Потому давайте улучшим функцию следующим кодом:

function() { var podmena = {{Запрос для подмены}}; //принимаем значение podmena из URL var stringForCheck = "москв"; //искомое значение, которое будем искать в podmena var stringIfSuccess = "москва"; //какое значение вернем, если найдем нужное значение var checkOut = podmena.indexOf(stringForCheck); //ищем индекс нужного значения в переменной if (checkOut > 0) //если он нашелся, возвращаем ожидаемое значение { return stringIfSuccess; } return podmena; }

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

Теперь давайте разбираться.

Как видите, мы упростили объявление переменной и запись значения, соединив всё вместе:

var podmena = {{Запрос для подмены}};

Работает так же, как и в прошлом коде, только запись короче.

Также мы создали две переменных:

var stringForCheck = "москв";

var stringIfSuccess = "москва";

Их роль я объясню чуть позже.

Ещё у нас есть переменная:

var checkOut = podmena.indexOf(stringForCheck);

В эту переменную checkOut мы записываем не просто значение podmena, а индекс значения stringForCheck, которое есть в значении podmena.

То есть stringForCheck у нас равно «москв». Если это значение «москв» будет в podmena, нам вернётся индекс, который покажет, где это слово в строке начинается.

Предположим, что podmena = «инкубатор москва». Тогда при проверке podmena.indexOf(“москв”); индекс будет равен 10. То есть слово “москв” начинается с 10 буквы в строке.

Если искомого слова не найдётся, индекс будет равен -1.

Так мы сделали ищейку, которая находит нужные слова! Это именно то, что нужно для текущей задачи.

Осталось только обработать результат ищейки и выдать ответ. Обработать ответ можно примерно таким образом:

Если слово нашлось в тексте (индекс не равен -1), то функция должна об этом сообщить в таблицу поиска.

В другом случае (индекс равен -1) функция ничего не делает и передаёт результат в таблицу поиска.

Именно такую обработку и совершают последние строки кода:

if (checkOut > 0) { return stringIfSuccess; } return podmena;

Здесь if совершает проверку переменной checkOut. Если переменная больше нуля (checkOut > 0), совершаются действия в фигурных скобках (return stringIfSuccess). Если checkOut меньше нуля (например, -1), действие в фигурных скобках совершаться не будет.

В конце функции есть значение

return podmena;

return — команда к завершению функции. То есть когда объявляется return, функция возвращает указанное рядом с return значение (return «что-то»; //например) или может ничего не указывать и вызвать

return;

Тогда функция себя завершит и ничего не вернет после обработки.

А теперь ещё раз обратим внимание на комбинацию:

if (checkOut > 0) { return stringIfSuccess; } return podmena;

Если условие if срабатывает, то произойдет

return stringIfSuccess;

Функция завершит работу и вернет значение. А return podmena; уже не сработает, так как функция завершила свою работу ранее.

Если условие if не сработало, то у нас сработает стандартное return podmena.

Вот и всё! С помощью этого кода реализуется алгоритм поиска указанного слова (stringForCheck) и возвращается нужное значение (stringIfSuccess), если фраза найдена. Так что уже неважно, какое ключевое слово находится в podmena, лишь бы там была интересующая нас фраза.

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

function() { var podmena = {{Запрос для подмены}}; //принимаем значение podmena из URL //искомые значения, которые будем искать в podmena var stringForCheck = ["москв", "петербург", "питер", "красноярск", "житомир"]; //какое значение вернем, если найдем искомое var stringIfSuccess = ["москва", "петербург", "петербург", "красноярск", "житомир"]; var result = podmena; for (var i = 0; i < stringForCheck.length; i++) { var checkOut = podmena.indexOf(stringForCheck[i]); //ищем индекс искомого значения в переменной if (checkOut >= 0) //если он находится, возвращаем ожидаемое значение { return stringIfSuccess[i]; } } return podmena; }

Итак. Что мы добавили:

1. В значении переменной появились перечисленные в кавычках слова, заключённые в квадратные скобки.

2. Добавился цикл for.

А теперь расшифруем.

1. У нас есть переменная

var stringForCheck = ["москв", "петербург", "петербург", "красноярск", "житомир"];

Благодаря квадратным скобкам она хранит не одно значение, а несколько. Такая переменная носит гордое название «массив».

Теперь доступ к данным переменной можно получить только с указанием индекса желаемого значения. Важно — индекс всегда начинается с нуля.

Например, если мы хотим найти «питер» и вписать это значение в другой переменной, нужно указать:

var anotherVariable = stringForCheck[2];

А если нужно вписать значение «москв», то:

var anotherVariable = stringForCheck[0];

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

Мы задаём условие цикла:

for (var i = 0; i < stringForCheck.length; i++)

Для этого создаём переменную i и приравниваем её к нулю:

var i = 0;

Затем задаём условие:

i < stringForCheck.length;

Этот метод stringForCheck.length возвращает значение длины массива stringForCheck. Если посмотреть в код выше, мы увидим, что там записано пять слов через запятую. Соответственно, этот метод вернёт значение 5.

Мы проверяем, что i меньше длины stringForCheck. Пока это справедливо, алгоритм в фигурных скобках будет выполняться.

И последнее:

i++)

Эта строчка указывает, что после выполнения всего алгоритма в фигурных скобках цикла for к переменной i прибавляется единица.

Итак, что происходит:

1. Создаётся переменная i и приравнивается к нулю.

2. Сверяется i с длиной массива stringForCheck.

3. Выполняется алгоритм, если i меньше длины массива.

4. Прибавляется единица к i.

5. Проверка повторяется с п.2.

Если условие п.2 не выполняется, то цикл for завершается.

Итак, давайте рассмотрим работу алгоритма цикла.

for (var i = 0; i < stringForCheck.length; i++) { var checkOut = podmena.indexOf(stringForCheck[i]); if (checkOut >= 0) { return stringIfSuccess[i]; } }

Тут всё просто и знакомо. Мы задаём переменную checkOut. Приравниваем её значение к индексу значения массива. И тут есть важный момент: мы ищем индекс переменной stringForCheck[i]. То есть мы используем переменную i, чтобы каждую итерацию цикла for получать каждое значение массива по очереди (сначала 0, потом 1, потом 2 и так далее). Так цикл for проходит по всем значениям массива, а значит, по всем городам, которые записаны в переменной stringForCheck.

Дальше происходит проверка: если индекс текущего значения больше нуля (найдено текущее проверяемое слово), то функция завершается (return) и возвращается значение из другой переменной stringIfSuccess. А в stringIfSuccess у нас записан ряд значений, которые имеют такую же очередь, как и в stringForCheck. Поэтому в таблицу поиска вернётся нужное значение.

Разберём на примере, чтобы было понятно. Предположим, значение podmena = «инкубатор в петербурге»;

Далее задаются нужные переменные, и начинается цикл for.

Первый цикл, i равно нулю.

Происходит проверка:

var checkOut = podmena.indexOf(stringForCheck[0]); if (checkOut >= 0) { return stringIfSuccess[0]; }

stringForCheck[0] у нас равен «москв», а в переменной podmena такого значения нет, потому проверка if будет неудачной, и цикл for пойдёт на следующий круг.

Второй цикл, i теперь равен единице.

Происходит следующая проверка:

var checkOut = podmena.indexOf(stringForCheck[1]); if (checkOut >= 1) { return stringIfSuccess[1]; }

stringForCheck[1] у нас равен «петербург». Такое значение в переменной podmena есть. Следовательно, проверка if будет успешной, и функция завершит работу и вернёт значение stringIfSuccess[1], который равен «петербург».

Так можно проверять множество значений на наличие в pomena и возвращать нужные нам переменные.

Если вы впервые сталкиваетесь с программированием и осилили всю эту информацию, то поздравляю с базовым введением в программирование.

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

В заключение

Эта функция — лишь один из вариантов удобной работы с GTM. Её можно улучшить и сделать более гибкой.

Надеюсь, я подтолкнул вас к новым идеям применения JavaScript для работы с GTM. Если остались вопросы или появились мысли, как можно улучшить функцию, — пишите в комментариях

0
24 комментария
Написать комментарий...
Yuriy Khait

Спасибо за статью!
Мы как раз много GTM-им в контексте, а настолько подробного мануала не было :)

Ответить
Развернуть ветку
Александр Зарайский
Автор

Приятно слышать )
Если будут пожеланию по другим темам GTM, пишите )

Ответить
Развернуть ветку
Олег Е

Александр, есть такое пожелание! Было бы здорово, если бы Вы пролили свет на АБ тестирование результатов подмен в текущей реализации. Спасибо за статью, за эту и за будущую! )

Ответить
Развернуть ветку
Александр Зарайский
Автор

Имеется ввиду, сравнение эффективности подставляемых заголовков друг с другом? По сути, это отдельная статья по инструменту Google Optimize и не уверен, хорошо ли тут сработают подставляемые заголовки... Или, возможно, я не уловил Вашу мысль )

Ответить
Развернуть ветку
Ольга Азарова

Это слишком круто, чтобы быть правдой. Спасибо. В закладки !!!

Ответить
Развернуть ветку
Александр Зарайский
Автор

Приятно читать, Ольга ) Надеюсь поможет

Ответить
Развернуть ветку
Maksym Myroshnyk

Спасибо за такое качественное дополнение темы GTM

Ответить
Развернуть ветку
Александр Зарайский
Автор

Рад, что понравилось )

Ответить
Развернуть ветку
Анна Ященко

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

Ответить
Развернуть ветку
Александр Зарайский
Автор

Предлагайте еще темы, также подробно поделюсь, если смогу )

Ответить
Развернуть ветку
Анна Ященко

на любые темы по контексту, конверсии? )) или ГТМ? )

Ответить
Развернуть ветку
Александр Зарайский
Автор

Ну что бы продолжить тему, лучше ГТМ )
А если есть сложные вопросы по контексту и конверсиям, то предлагайте

Ответить
Развернуть ветку
Артём Заковряжин

Волосы шевелятся под мышками от таких возможностей.....
А теперь, внимание, знатоки: я правильно понимаю, что источник трафика может быть не только из Google Ads, но и из ЯД????

Ответить
Развернуть ветку
Александр Зарайский
Автор

Естественно. Сразу отвечу на возможный вопрос - подмена работает на любой источник трафика, если подмена установлена в ссылке )

Ответить
Развернуть ветку
Eugene Gultyaev

Очень хорошо! Надо будет обкатать

Ответить
Развернуть ветку
Ilya Lapenkov

Как инициировать вызов тега после полной загрузки DOM если сайт на react.js?

Ответить
Развернуть ветку
Александр Зарайский
Автор

GTM всегда вызывает тег после полной загрузки DOM, если не ошибаюсь. Но можно привязать условие срабатывания тега, на после того, как DOM было загружено. Не совсем понял, в чем может быть загвоздка при react.js. Можете пояснить?

Ответить
Развернуть ветку
Ilya Lapenkov

тот html тег, который меняется, прилетает в дом после отработки тега GTM. То есть в скрипт тега корректно передается подмененный текст, но в доме не происходит изменений. Не пойму как отловить событие полной загрузки документа. И да, у сайта микросервисная архитектура.

Ответить
Развернуть ветку
Mister Egos

Если подменить текст нужно не после загрузки DOM, а в произвольный момент, то нужно использовать не триггер "Просмотр страницы", а триггер "Пользовательское событие".

В javascript-коде вашего сайта в момент, когда страница готова к замене текста, нужно выполнить dataLayer.push({'event': 'react_is_ready'});

Тут react_is_ready - это произвольное имя события в вашем триггере в GTM. Чтобы добавить строку в нужное место, потребуются навыки программирования. Всё остальное сможете сделать по статье.

Но! Визуальная задержка перед подменой текста может оказаться критичным моментом, который в итоге потребует переноса всей логики из GTM в react. Нужно пробовать и смотреть, как это выглядит на практике

Ответить
Развернуть ветку
Александр Зарайский
Автор

Отличный ответ, Эгос ) Кое что и для подчерпнул

Ответить
Развернуть ветку
Макс Сноу

Отличный мануал, подробно, понятно и, как всегда, с роскошными гифками, так что еще и наглядно =) кстати, какую программу используете для записи гифок?

Ответить
Развернуть ветку
Александр Зарайский
Автор

Рад, что помогает статья )
Для записи использовалась Camtasia Studio 2018

Ответить
Развернуть ветку
Денис Саулин

Просто КРАСАВА! Мне это нафиг не нужно, но очень интересно!

Ответить
Развернуть ветку
Александр

Нефига себе как можно....

Ответить
Развернуть ветку
21 комментарий
Раскрывать всегда