В данном руководстве мы разберем бесплатный и, на мой взгляд, самый эффективный метод борьбы с ботами на сегодняшний день с использованием Google Tag Manager (в будущем статья будет дополнена и Менеджером тегов от Яндекса). Решение поможет блокировать отправку роботного трафика, конверсий и покупок от ботов в аналитику и, как следствие, не обучать на этих данных нашу рекламу. Так же вы сможете видеть в аналитике прозрачную статистику по ботам, но обо всем по порядку.
- Принцип работы
- Возможности антифрода с reCAPTCHA:
- Блокировка ботов и подозрительной активности на сайте;
- Расширенная аналитика трафика ботов (анализ процента трафика от роботов по площадкам рся, кампаниям и пр.);
- Почему не подходят стандартные метрики от Яндекса?
- Пошаговая инструкция:
Принцип работы моего антибота
Думаю, вы встречались с галкой «Я не робот» в формах на сайте. Не спешите уходить, все не так банально, как кажется. Многие из нас представляют себе проверку от raCAPTCHA так:

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

Но что происходит между нажатием на кнопку проверки и появлением гидрантов? Тут самое интересное: решение о том, показывать гидранты или нет, принимает не Google, а разработчик. Google лишь отправляет оценку по шкале от 0 до 1 (0.1, 0.2, … 0.9, 1), где 0 — это 100% робот, а 1 — человек. Более того, сейчас даже не требуется показывать кнопку «Я не робот», а сразу запрашивать оценку посетителя в невидимом для него режиме. Оценку можно получить для любого действия на сайте, будь то просто вход на него из рекламы или клик по номеру телефона. Хотите не отправлять в метрику клики по телефону от ботов? Теперь это можно сделать.
Что анализирует reCAPTCHA для оценки посетителя сайта?
Точные данные сервисом не раскрываются, чтобы не давать мошенникам сведения для обучения роботов, но кое что удалось узнать из открытых источников. ReCAPTCHA (например, v3 или Enterprise) анализирует:
1. Поведение пользователя:
- Движение мыши и клики: паттерны перемещения (плавные vs резкие, случайные vs алгоритмические).
- Задержки между действиями, скорость заполнения форм.
- Ритм набора текста, исправления ошибок.
- Как пользователь взаимодействует с кнопками, полями ввода.
- Время, проведенное на странице до/после действий.
2. Контекст сессии:
- История браузера, наличие cookies, активность в других вкладках.
- IP-адрес и геолокация: подозрительные регионы, частота запросов с одного IP, соответствие времени на ПК часовому поясу IP.
- Соответствие устройства характеристикам ОС, разрешению экрана, версии браузера.
3. Дополнительные сигналы:
- Сетевые данные: задержки сети, использование VPN/прокси.
- Активность аккаунта Google: Если пользователь авторизован, анализируется история его действий.
5. Машинное обучение:
- ReCAPTCHA использует модели, обученные на огромных массивах данных, чтобы выявлять паттерны, характерные для ботов (например, автоматические клики, массовые запросы).
Возможности антифрода с помощью reCAPTCHA
Мы можем получить оценку роботности сразу после начала визита, но чем дольше посетитель находился на сайте, тем больше про него информации и точнее оценка. Также на оценку влияет действие, которое вы передаете на проверку. Вы сами даете названия таким действиям и затем можете смотреть по ним статистику:

Т.е. мы будем забирать оценку в переменную Менеджера Тегов, дальше действия с ней ограничены только вашей фантазией. Вот несколько примеров того, что делаю я.
Блокировка ботов и подозрительной активности на сайте
Можно полностью заблокировать ботам вход на сайт, отправляя их на 404 страницу или не загружай для них счетчики аналитики, установив в триггере, отвечающим за загрузку счетчика условие, что уровень роботности должен быть больше N (N от 0.1 до 1.0). У своих клиентов мне безразлично, гуляют ли боты по сайту, в добавок я хочу видеть по ним статистику, поэтому я блокирую только отправку целей от ботов в Метрику, но не всех, а только тех, на которых обучаю рекламные кампании.

На скрине выше триггер GTM, который срабатывает только тогда, когда по email был совершен клик с оценкой роботности больше 0.5, т.е. вероятность того, что клик совершил человек более 50%. Этот триггер отвечает за передачу цели «клик по emal» в Яндекс Метрику и далее в Директ. Соответственно, я не обучаю рекламные кампании клиентов конверсиям от роботов и людей с подозрительной активностью, а при оплате за конверсии я не плачу за конверсии от ботов.
Статистика по трафику с роботами и без
Мы можем передавать оценку роботности как параметры визита, параметры посетителя параметр или ценность целей. Это дает неограниченные возможности в построение отчетов по роботам. Например, можно передавать три цели по визитам от ботов, сомнительным визитам и людям и делать вывод о качестве трафика:

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

И самое интересное. Можно анализировать статистику по качеству трафика, которые приводит конкретная рекламная кампания, группа объявлений или тип таргетинга:

Аналогичным образом можно посчитать и среднюю роботность площадки РСЯ

Почему не воспользоваться встроенными инструментами анализа и борьбы с ботами от Яндекса?
В аналитике от Яндекса есть встроенные метрики «Визиты роботов» и «Роботность», которые вполне успешно вычисляют роботов по поведению. А Яндекс Директ фильтрует визиты роботов.

Тогда зачем нам нужно создавать свои отдельные цели, параметры визитов и пр. показатели для аналитики роботов? Причин несколько.
- С моим вариантом вы сами выбираете критичный уровень роботности от 0 до 1 и решаете как работать с этими показателями.
- Встроенные в Метрику «Визиты от роботов» нельзя использовать во многих необходимых нам отчетах, таких как «Директ Площадки» и «Директ Сводка», а мои можно.
- Одна голова хорошо, а две лучше: если у нас есть возможность использовать в борьбе с фродом двух IT гигантов, вместо одного, то почему бы и нет. У Яндекса и Google разные алгоритмы обнаружения ботов и одних пропускают алгоритмы Яндекса, а вторых алгоритмы reCAPTCHA.

На скриншоте «Визиты роботов по поведению» — это встроенная метрика от Яндекса, а «Целевые визиты роботов» — моя цель, считающая визиты от роботов с помощью reCAPTCHA. Видно, что Яндекс обнаружил больше роботов, чем Google, но из рекламы (Директа) мой вариант смог обнаружить в 47 раз больше ботов, чем Метрика. Согласитесь, разница впечатляющая. Подозреваю, что ботофермы тренируют своих роботов обходить алгоритмы Яндекса для скликивания рекламы, поэтому мы и видим такой результат, но это лишь мое субъективное мнение, в добавок я сам выкрутил показатель роботности на тот уровень, который я считаю приемлемым и он может сильно отличаться от критериев Яндекса.
Тут стоит отметить, что Директ отфильтровывает клики от ботов и такие отфильтрованные визиты в Метрике не отображаются, а деньги по ним не списываются. К сожалению, фильтр работает не идеально и пропускает визиты части ботов.
Настройка антифрода на основе reCAPTCHA
Примечаний! Сервисы reCAPTCHA и GTM, принадлежат Google и могут подпадать под закон о трансграничной передаче данных, требующий уведомления об этом РКМ.
Для примера, будем получать оценку роботности в переменную менеджера тегов, но весь код можно адаптировать под использования без GTM с помощью обычной переменной JS, а так же передавать оценку в админку сайта или в CRM/Google Таблицу. Доработать решение сможет любой человек с базовыми знаниями PHP и JavaScript. Если же вы пользуетесь GTM на уверенном уровне, то не понадобится дорабатывать ничего. На dataLayer по любому интересующему вас действию будет падать оценка роботности и дальше можно использовать её любым способом, на который хватит фантазии.
Так же нам понадобится доступ к хостингу, т.к. часть кода необходимо разместить в корневой папки сайта, а если у вас сайт на конструкторе, тогда придется вешать часть кода на поддомене с обычным хостингом (это не дорого и скорее всего хватит бесплатного хостинга от beget, но это надо тестировать, т.к. я сам сижу на платном тарифе vps за 7руб. в день и не знаю особенности работы бесплатного варианта).
В текущем руководстве я дам базовый шаблон того что нужно сделать, чтобы у вас в GTM появилась оценка и один пример использования, но в дальнейшем на эту тему будет написана серия дополнительных решений, поэтому не забудьте подписаться на ТГ (ссылка внизу страницы), чтобы не пропустить новые статьи.
Регистрируемся в reCAPTCHA и получаем ключи API
Переходим на сайт Google reCAPTCHA по этой ссылке. В верхнем правом углу отобразится иконка аккаунта Google, через который будем создавать ключи API. Если вы не авторизованы, нажмите «sing in».

Далее жмем «Get started» и вводим следующие данные:
- Ярлык — удобное название проекта (не обязательно должно совпадать с названием сайта);
- Тип reCAPTCHA — С использованием оценок (v3);
- Домен — хост сайта (например zurov.ru). Ключи API будут выданы на домен и все поддомены (например shop.zurov.ru);
- Название проекта на GSP — удобное название проекта для Google Cloud Platform (это общее название для всех будущих сайтов)

Вам будет начисляться 10 000 бесплатных проверок в месяц. Если понадобится больше, придется покупать дополнительные проверки. На момент написания статьи за 8$ можно увеличить лимит до 100 000 проверок в месяц, но потребуется международная платежная карта или иной способ создания платежного аккаунта Google.
После того, как создадите проект сервис выдаст два ключа: ключ сайта и секретный ключ. Скопируйте их, они нам пригодятся дальше:

Размещаем серверный скрипт в корневой папке сайта
Здесь нам понадобится доступ к файлам сайта по ftp или к хостингу. Если у вас нет понимания как с этим работать, лучше попросите залить файл в корневую папку сайта своего разработчика или поддержку хостинга. Как правило, они идут на встречу в таких простых задачах.
Сразу отвечу на вопрос: «почему нельзя использовать этот скрипт в GTM?» Дело в том, что запрос к reCAPTCHA должен выполняться с вашего сервера. В таком случае система будет понимать, что его выполнили именно вы, а не робот и такой подход гарантирует, что назад вернется ответ именно от recaptcha, а не фейковая оценка от бота. Вот такой скрипт нам понадобится:
<?php if ($_SERVER['REQUEST_METHOD'] === 'POST') { $secret = 'your-secret-key'; $input = json_decode(file_get_contents('php://input'), true); $token = $input['recaptchaToken'] ?? ''; $verifyResponse = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=$secret&response=$token"); $responseData = json_decode($verifyResponse, true); echo json_encode([ 'success' => $responseData['success'], 'score' => $responseData['score'] ?? 0 ]); } ?>
Также этот скрипт и все другие необходимые файлы по мимо статьи будут лежать на github.
Замените your-secret-key на секретный ключ из reCAPTChA. Название файла задайте произвольное и запомните его. Расширение файла «.php». Лучше не использовать название файла, которое приведено в качестве примера здесь, т.к. оно публичное. В моем случае это будет bot_chek.php.
Добавляем теги reCAPTCHA антифрода в GTM
Здесь есть несколько вариантов. Если вы скачивали файлы с github, можно просто импортировать файл GTM-reCAPTCHA-Yandex.json в менеджер тегов со всеми необходимыми тегами, триггерами и переменными, а затем заменить значения в переменных на свои. Это быстрый подход, но я рекомендую использовать его для второго и последующих проектов, а для первого раза пропустить этот вариант и загрузить все вручную для лучшего понимания того что и зачем вы делаете.
Первый вариант: импорт json файла
- Перейдите на вкладку «Администрирование» и импортируйте файл GTM-reCAPTCHA-Yandex.json, скачанный с github:

В контейнер будут загружены следующие теги, триггеры и переменные:

В переменной recaptchaSiteKey нужно заменить ключ сайта на ваш, а в recaptchaServerPuth заменить bot_chek.php на название (путь) вашего серверного файла. На этом базовая настройка завершена. Механика работы будет аналогична, как при загрузки из JSON, так и при занесении всех тегов и переменных вручную, поэтому опишу её ниже после второго варианта.
Второй вариант: создаем все теги, триггеры и переменные вручную
Начнем с переменных.
Нам понадобится две переменные (такие же, как описывали в первом варианте) с типом «константа»:
- Имя — переменной recaptchaSiteKey; значение — ключ сайта, полученный в reCAPTCHA;
- Имя — recaptchaServerPuth; значение — название файла серверного скрипта, например bot_chek.php;
И две переменные с типом «Переменная уровня данных» и именами recaptchaScore и recaptchaAction. Все остальные настройки в этих переменных оставляем по умолчанию. В них будут попадать оценка от рекапчи (recaptchaScore) и оцениваемое действие (recaptchaAction).
Теперь добавим триггеры:
Два триггера с типом «Специальное событие»:
- Имя — event iNeedScore (или любое другое, удобное вам) и названием события iNeedScore;
- Имя — event recaptchaVerified (или удобное) и название события — recaptchaVerified.
И третий триггер для иллюстрации примера работы с таймером на 10 секунд с начала сеанса. Настройки на скриншоте:

Замените zurov.ru на хост вашего сайта. Если в списке нет переменной Referrer, её нужно включить в списке встроенных переменных GTM. Такой подход позволяет срабатывать таймеру один раз на сеанс, т.к. триггер с таймером действует в рамках одной страницы сайта и переход на другую страницу запускает его заново, но у каждой последующей страницы реферрер будет содержать хост вашего сайта и срабатывания триггера будет блокироваться.
Добавляем теги
Нам потребуется 4 тега типа Пользовательский HTML. Первый с триггером All Pages будет загружать скрипт и выводить бейдж Google reCAPTCHA на странице. Это стандартный код для любого сайта, использующего технологию reCAPTCHA, который выдает токены и анализирует поведение пользователя (своего рода счётчик). Назовем его reCAPTCHA badbe и добавим следующий код:
<script src='https://www.google.com/recaptcha/api.js?render={{recaptchaSiteKey}}'></script> <!-- <style> .grecaptcha-badge { visibility: hidden; } </style> -->
В {{recaptchaSiteKey}} загружается значение ключа сайта из ранее созданной переменной.
Если хотите, чтобы бейдж (значок) был невидимым, нужно удалить куски кода «<!—» и «—>». Это раскомментирует стили скрытия, но в таком случае Google требует уведомлять пользователя об использовании reCAPTCHA самостоятельно, например в подвале сайта или на странице Политики конфиденциальности. Пример текста от Google:
This site is protected by reCAPTCHA and the Google <a href="https://policies.google.com/privacy">Privacy Policy</a> and <a href="https://policies.google.com/terms">Terms of Service</a> apply.
Второй тег назовем DLpush iNeedScore, в качестве триггера активации установим таймер на 10 сек. из примера выше и добавим в него следующий код:
<script> window.dataLayer.push({ 'event': 'iNeedScore', 'recaptchaAction': 'target_event' }); </script>
Скрипт при срабатывании триггера отправляет на уровень данных событие iNeedScore и переменную recaptchaAction со значением target_event. Зачем нам это нужно, станет понятно в следующем теге. Пока же, если хотите запрашивать оценку не по таймеру на 10 секунд, а, допустим проверять тех, кто кликнул по email — просто замените триггер на тот, который отслеживает клики по email. Вместо target_event впишите идентификатор события клика по email, который вы используете в Яндекс Метрике, например click_email. Я для примера оставлю исходный вариант.
Третий тег обзовем reCAPTCHA set in server. Добавим к нему триггер, который слушает событие iNeedScore из прошлого тега. Мы создали его ранее с названием event iNeedScore. В поле для кода вставим следующее:
<script> var action = '{{recaptchaAction}}'; grecaptcha.ready(function() { grecaptcha.execute('{{recaptchaSiteKey}}', { action: action }) .then(function(token) { var xhr = new XMLHttpRequest(); xhr.open('POST', '/{{recaptchaServerPuth}}', true); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { try { var data = JSON.parse(xhr.responseText); window.dataLayer.push({ 'event': 'recaptchaVerified', 'recaptchaValid': data.success, 'recaptchaScore': data.score, 'recaptchaAction': action }); } catch (e) { console.error('Ошибка парсинга JSON:', e); } } }; xhr.send(JSON.stringify({ recaptchaToken: token })); }); }); </script>
Третий тег срабатывает при наступлении события iNeedScore второго тега и забирает значение из переменной recaptchaAction — того, что будем проверять. Затем он обращается к первому тегу (самой reCAPTCHA) и генерирует одноразовый токен. С токеном и названием проверяемого действия тег обращается к серверному скрипту (который в корне сайта) и тот уже отправляет все данные на сервера Google. После проверки серверный скрипт возвращает в наш тег результат и он отправляет его (результат) в GTM с событием recaptchaVerified и переменными:
- ‘recaptchaScore’ со значением оценки от 0 до 1;
- ‘recaptchaAction’: с названием проверенного действия.
Так же в отладчике GTM можно будет проверить была ли проверка успешной в recaptchaValid’. Если true, значит все прошло хорошо.
Сложно? Давайте разберем что произойдет на нашем 10 секундном триггере.
Как работает базовая настройка проверки визитов на фрод?
Через 10 секунд после начала визита будет срабатывать тег DLpush iNeedScore, который будет отправлять на уровень данных dataLayer событие iNeedScore — оно активирует проверку посетителя на робота и при успешной проверке возвращает:
- событие — recaptchaVerified;
- в переменную recaptchaScore — оценку от 0 до 1;
- в переменную recaptchaAction название проверяемого события — в нашем случае это target_event.
Вот так это будет выглядеть в отладчике GTM:

Как передать данные о проверке на фрод в Яндекс Метрику?
Для этого нам придется создать еще один тег с типом пользовательский HTML и триггером, срабатывающим при успешной проверке посетителя. Мы назвали этот триггер event recaptchaVerified. Код для тега такой:
<script> ym('{{YM-number}}', 'hit', '/reCAPTCHA', { params: { reCAPTCHA_score: '{{recaptchaScore}}' } }); var score10 = {{recaptchaScore}} * 10; ym('{{YM-number}}', 'reachGoal', 'botscore' + score10, {order_price: '{{recaptchaScore}}', currency: 'RUB'}); </script>
Замените {{YM-number}} на номер счётчика Яндекс Метрики.
Тег срабатывает при успешной проверке и отправляет в метрику:
- ym(‘{{YM-number}}’, ‘hit’, ‘/reCAPTCHA’, { params: { reCAPTCHA_score: ‘{{recaptchaScore}}’ } }) — отправляем просмотр виртуальной страницы /reCAPTCHA с параметром reCAPTCHA_score и оценкой роботности;
- ym(‘{{YM-number}}’, ‘reachGoal’, ‘botscore’ + score10, {order_price: ‘{{recaptchaScore}}’, currency: ‘RUB’}) — достижение целей botscore1, botscore2 — botscore10. Умножение целей на 10, вместо 0.1, 0.2 — 1.0 от reCAPTCHA нужно для корректной работы с аналитикой.
По целям я обычно такую настройку делаю:

Регулярное выражение botscore[0-3] соответствует botscore0, botscore1, botscore2 и botscore3. С остальными рег. выражениями аналогично. Получается три цели для аналитики процента роботов и одна общая собирательная для всех оценок. Именно по последней можно анализировать площадки РСЯ, кампании в Директе и пр. на среднюю роботность. Для этого нужно разделить общий доход по цели (сумму всех оценок) на количество достижений цели (общее число оценок).
Бонусом для дочитавших до конца дам еще один тег, которого нет в json файле. С помощью него можно передавать все классические цели типа email_click, phone_click, whatsapp_click, active_visit и пр. с оценкой роботности.
<script> ym('{{YM-number}}', 'reachGoal', '{{recaptchaAction}}', {botScore:'{{recaptchaScore}}'}); </script>
Нужно заменить {{YM-number}} на номер счетчика Метрики, а в качестве триггера активации поставить уже известный нам event recaptchaVerified. Выше я писал, что можно вместо target_event записывать в тег DLpush iNeedScore отслеживаемое событие, например click_email. Вот оно и вернется из reCAPTCHA в переменную recaptchaAction, которую мы передадим как идентификатор цели в Яндекс Метрику. Таким образом, копируя тег DLpush iNeedScore и добавляя в него разные триггеры активации по клику на контакты, активным визитам, отправкам формам и любым другим целям — мы будем отправлять на проверку именно достижение этой цели, а меняя в этом теге target_event на идентификатор цели метрики, в переменную recaptchaAction будет попадать нужная нам цель, а в recaptchaScore оценка роботности по этой цели. Дальше через наш последний тег все это будет передаваться в Метрику.
Так же вместо оценки роботности можно передавать ценность цели, умноженную на эту оценку. Так мы будем оценивать достижение цели в зависимости от вероятности того, что её совершил робот. К примеру, если ценность цели для нас составляет 1 000 рублей, то за робота мы не заплатим ничего, за посетителя с оценкой 0.3 — 300 руб., а за посетителя с оценкой 0.8 — 800 руб.
Вот пример кода:
<script> var newPrice = {{recaptchaScore}} * 1000; ym('{{YM-number}}', 'reachGoal', '{{recaptchaAction}}', {order_price: newPrice, currency: 'RUB'}); </script>
Вместо 1000 нужно поставить ценность цели, которую вы хотите платить за визит от 100% человека, но не забывайте, что визиты с vpn или с устройства без истории браузера такк же будут оцениваться ниже 1 и это стоит учитывать при передачи ценности цели.
Вместо итога
Понимаю, что статья получилась сложная. Если к решению будет большой интерес, я постараюсь сделать больше примеров и, возможно записать видео, с пошаговой настройкой. Не стесняйтесь задавать вопросы здесь и в телеграмме. Всегда отвечаю. Так же буду помогать с настройкой решения под ключ на коммерческой основе.