July 22, 2023

Фильтрации ботов на сайте

Борьба с ботами через CloudFlare & отложенную загрузку Яндекс.Метрики.

Настройка cloudflare

Заходим в домен, потом Security -> WAF. Настраиваем правила:

1️⃣ Пускаем хороших ботов:

  • Known Bots equals ✅
    Можно дополнительно добавить правило через [or] для Яндекс и Google:
    * User Agent -> equals -> «YandexBot»
    * User Agent -> equals -> «Google»

[Choose action: Skip]

Expression будет такой:

(http.user_agent eq "YandexBot") or (http.user_agent eq "Google") or (cf.client.bot)

2️⃣ Проверяем всех, кто идет с протоколом меньше HTTP2 или заходит напрямую:

  • HTTP Version is not in «HTTP/2, HTTP/3, SPDY/3.1»

And

  • Referer equals «»

[Choose action: JS Challenge]

Expression будет такой:

(not http.request.version in {"HTTP/2" "HTTP/3" "SPDY/3.1"} and http.referer eq "")


3️⃣ Фильтруем IPv6 и заход на HTTP:

  • IP Source Address is in «::/0»

Or

  • SSL/HTTPS equals ✖️

[Choose action: Managed Challenge]

Expression будет такой:

(ip.src in {::/0}) or (not ssl)

4️⃣ Блокируем страны:
* Country equals «Indonesia»
* Country equals «Unknown states, other entities or organizations»
* Добавляйте любые страны или континенты
[Choose action: JS Challenge]

Expression будет такой:

(ip.src in {::/0}) or (not ssl)


Отложенная загрузка кода Яндекс.Метрики

Просто подставьте ваш айди в metricaId и замените ваш текущий код счетчика.

Данный код подключает метрику если:

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

Сам код:

<script type="text/javascript">
  (function () {
    'use strict';

    // Флаг, что Метрика уже загрузилась.
    var loadedMetrica = false,
      // Ваш идентификатор сайта в Яндекс.Метрика.
      metricaId = 000000000000000,
      // Переменная для хранения таймера.
      timerId;

    // Для бота Яндекса грузим Метрику сразу без "отложки",
    // чтобы в панели Метрики были зелёные кружочки
    // при проверке корректности установки счётчика.
    if (navigator.userAgent.indexOf('YandexMetrika') > -1) {
      loadMetrica();
    } else {
      // Подключаем Метрику, если юзер начал скроллить.
      window.addEventListener('scroll', loadMetrica, {passive: true});

      // Подключаем Метрику, если юзер коснулся экрана.
      window.addEventListener('touchstart', loadMetrica);

      // Подключаем Метрику, если юзер дернул мышкой.
      document.addEventListener('mouseenter', loadMetrica);

      // Подключаем Метрику, если юзер кликнул мышкой.
      document.addEventListener('click', loadMetrica);

      // Подключаем Метрику при полной загрузке DOM дерева,
      // с "отложкой" в 1 секунду через setTimeout,
      // если пользователь ничего вообще не делал (фоллбэк).
      document.addEventListener('DOMContentLoaded', loadFallback);
    }

    function loadFallback() {
      timerId = setTimeout(loadMetrica, 1000);
    }

    function loadMetrica(e) {
      // Пишем отладку в консоль браузера.
      if (e && e.type) {
        console.log(e.type);
      } else {
        console.log('DOMContentLoaded');
      }

      // Если флаг загрузки Метрики отмечен,
      // то ничего более не делаем.
      if (loadedMetrica) {
        return;
      }

      (function (m, e, t, r, i, k, a) {
        m[i] =
          m[i] ||
          function () {
            (m[i].a = m[i].a || []).push(arguments);
          };
        m[i].l = 1 * new Date();
        (k = e.createElement(t)),
          (a = e.getElementsByTagName(t)[0]),
          (k.async = 1),
          (k.src = r),
          a.parentNode.insertBefore(k, a);
      })(
        window,
        document,
        'script',
        'https://cdn.jsdelivr.net/npm/yandex-metrica-watch/tag.js',
        'ym'
      );
      ym(metricaId, 'init', {clickmap: true, trackLinks: true, accurateTrackBounce: true});

      // Отмечаем флаг, что Метрика загрузилась,
      // чтобы не загружать её повторно при других
      // событиях пользователя и старте фоллбэка.
      loadedMetrica = true;

      // Очищаем таймер, чтобы избежать лишних утечек памяти.
      clearTimeout(timerId);

      // Отключаем всех наших слушателей от всех событий,
      // чтобы избежать утечек памяти.
      window.removeEventListener('scroll', loadMetrica);
      window.removeEventListener('touchstart', loadMetrica);
      document.removeEventListener('mouseenter', loadMetrica);
      document.removeEventListener('click', loadMetrica);
      document.removeEventListener('DOMContentLoaded', loadFallback);
    }
  })();
</script>

Источники: