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

Это третий и последний воркфлоу из связки n8n-seo-monitor-suite. Про GEO-мониторинг видимости в ИИ-ответах и про ежедневный/еженедельный контент-аудит я уже писал.

Воркфлоу и пример сообщения
Воркфлоу и пример сообщения

Один воркфлоу, два независимых запуска

Как и в предыдущих двух, здесь общий источник правды на несколько кадансов: Daily_Monitor (те же URL категорий, что и в контент-аудите), Master_Briefs (эталонные Title/H1/границы интента) и Owner_Map - таблица "какой URL за каким запросом закреплён" читаются и помесячным отчётом, и еженедельным сканом каннибализации.

                [ ОБЩИЙ КОНФИГ ]
    Daily_Monitor · Baseline_Metrics · Master_Briefs · Owner_Map
                         │
        ┌────────────────┴─────────────────┐
        ▼                                   ▼
┌────────────────────────┐        ┌──────────────────────────┐
│ ПОМЕСЯЧНЫЙ ОТЧЁТ         │        │ СКАН КАННИБАЛИЗАЦИИ      │
│ 1-е число месяца         │        │ понедельник, 09:00       │
├─────────────────────────┤        ├────────────────────────────┤
│ • GSC/Метрика/Вебмастер │        │ • GSC query+page, 4 среза │
│   28д к прошлым 28д и   │        │   (28д/7д × текущий/пред.)│
│   аналогичному месяцу   │        │ • риск-скоринг 0-100      │
│   год назад              │        │ • контроль primary-запросов│
│ • модель "ожидаемо по    │        │   (не влияет на скоринг)  │
│   сайту" вместо порога   │        │ • Query Discovery         │
│ • трекинг ручных правок  │        │ • живой SerpApi — только  │
│   (SEO_Change_Log)       │        │   когда кэш не годится    │
└───────────┬──────────────┘        └─────────────┬──────────────┘
            │                                       │
            ▼                                       ▼
     Monthly_Log (append)          Cannibalization_State / _History (upsert)

Оба режима читают и пишут в общие таблицы свежести (SEO_Run_State, SEO_Page_Snapshot) и если данные за нужный день уже собраны другим прогоном, повторный фетч GSC/Метрики не делается.

Два вида конфликта

Скан различает два сценария:

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

  • Сквозной перехват: категорию обгоняет карточка товара, статья или любой другой URL не того типа.

Это не одна и та же проблема: если категорию обгоняет сосед-категория, то вопрос в границах интента и Title/H1 обеих. Если карточка товара обгоняет категорию - вопрос уже в перелинковке и хлебных крошках, а не в переписывании текста.

Модель риска: шесть факторов, а не "пересечение = тревога"

Ядро - Code-нода Cannibalization Engine, 1500+ строк. Для каждой пары "владелец / конкурент" по общему кластеру запросов считаются шесть компонентов, каждый с собственным потолком:

Фактор

Вес

Что меряет

Доминирование

0-25

доля показов конкурента в паре; ниже 35% - 0 баллов

Смещение позиции

0-20

насколько конкурент выше владельца в выдаче

Захват кликов

0-15

доля кликов конкурента, если есть минимум 2 клика в паре

Тренд периода

0-20

владелец падает, конкурент растёт - на 28-дневном и 7-дневном окне отдельно

Структурное несоответствие

0-10

у владельца 0 показов при 10+ у конкурента, запрещённая страница, легаси-редирект

Персистентность

0-10

сколько прогонов подряд конфликт держится (0 при первом появлении, максимум с третьего)

Код: вычисление факторов риска и итогового Risk Score
// Доминирование: 0..25
const dominanceScore = compShare <= 0.35 ? 0 : clamp((compShare - 0.35) / 0.55 * 25, 0, 25);

// Персистентность: 0..10
const persistenceScore = prevRuns >= 3 ? 10 : (prevRuns >= 2 ? 7 : (prevRuns >= 1 ? 4 : 0));

Сумма (максимум 100) умножается на коэффициент уверенности от 0.25 до 1.0, который понижает итоговый балл, если суммарных показов в паре мало:

let confidence = pairImp >= 300 ? 0.95 :
                 pairImp >= 100 ? 0.85 :
                 pairImp >= 30  ? 0.70 :
                 pairImp >= 10  ? 0.50 : 0.30;
const riskScore = Math.round(rawScore * confidence);

Итоговые пороги:

Severity

Условие

LOW_DATA

суммарно меньше 10 показов и меньше 2 кликов

WATCH

risk_score ≥ 30

HIGH

risk_score ≥ 55

CRITICAL

risk_score ≥ 75, конкурент держит ≥65% показов пары, и либо 2+ прогона подряд, либо 200+ показов

Условие для CRITICAL явно требует ИЛИ повторяемости, ИЛИ объёма - один разовый всплеск трафика конкурента, даже сильный, сам по себе не может пробить критический порог. Это прямой ответ на проблему, которую в daily-weekly решали на глаз по графику; здесь разделение сигнала от шума зашито в формулу.

Диагноз зависит от типа конфликта

Движок классифицирует характер конфликта и для каждого типа даёт свою рекомендацию:

  • Легаси-редирект тянет видимость: сигнал переклейки/переобхода, не повод трогать контент.

  • Категория против категории: сверить Title/H1/H2 и границы интента обеих, ничего не менять до подтверждения конкретного пересечения.

  • Товар против категории: проверить анкоры, хлебные крошки и блоки рекомендаций; фразу из карточки не убирать автоматически.

  • Статья против категории: возможна нормальная смешанная выдача (информационный и коммерческий интент законно уживаются) - сначала подтвердить, потом решать.

Четыре разных типа конфликта → четыре разных способа решения, а не одно радикальное решиние "объединить страницы".


Живой SERP - по расписанию кэша, а не всегда

GSC и Метрика бесплатные, живой запрос в SerpApi - нет. Поэтому вызывается он не каждый прогон:

  • кэш SERP-позиции живёт 14 дней (SERP_CACHE_TTL_DAYS);

  • на прогон - жёсткий потолок в 32 живых запроса (SERP_LIVE_MAX_QUERIES), даже если кандидатов на проверку больше;

  • локация и домен зашиты явно (Moscow,Moscow,Russia, google.ru/yandex.ru) — SERP чувствителен к гео, случайный запрос без локации показал бы не ту выдачу.

Эти правила я использую под свою ситуацию, чтобы уложиться в бесплатные лимиты на 250 запросов в месяц.

Отдельный, более узкий случай - "доуточнение неизвестных позиций владельца". Если по кластеру в топ-10 уже сидит чужая страница сайта, а свежей проверки именно позиции владельца ещё не было - это тот самый неоднозначный случай, где кэш не отвечает на вопрос. Нода-планировщик собирает только такие пары:

Код: отбор запросов на доуточнение позиций владельца
// Нужно свежее доуточнение позиции владельца, только если в TOP10 уже сидит другая страница сайта
if (dataErr || !found || ownerMatch) continue;
const exactOk = !!er && !boolVal(er.data_error, false) && ...;
if (exactOk) continue;
tasks.push({ engine, slug, category, query: q, owner_url: owner, reason: 'OWNER_POSITION_UNKNOWN' });

То есть живой запрос тратится не на повторную проверку, а конкретно на пробел в доказательной базе - где без него нельзя сказать, реальный это конфликт или нет.

Query Discovery — подсказывает кластер, не назначает его

Отдельная очередь: какие запросы вообще появились в GSC, но ещё не прописаны в Owner_Map. Для каждого такого запроса нода пытается угадать владельца по маркерам-словам с проверкой на границу слова (чтобы "ложки" не сработало внутри "вилки"):

// Маркер должен начинаться на границе токена
return new RegExp(`(^|[^а-яёa-z0-9])${esc}[а-яёa-z0-9-]*`, 'i').test(q);

Результат - предложение с меткой уверенности:

Метка

Уверенность

Что значит

MASTER_PRIMARY

высокая

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

RULE_MARKER

высокая

сработал один однозначный маркер-слово

AMBIGUOUS

низкая

сработали маркеры нескольких категорий сразу - нужна ручная проверка

MODEL_QUERY

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

UNCLASSIFIED

ни один маркер не сработал

Разница с основным скорингом принципиальна: Discovery никогда не становится доказательством каннибализации сама по себе - это отдельная очередь на ревью, а не источник инцидентов.


Контроль важных запросов отдельно от скоринга

Кроме взвешенной оценки, у каждой категории есть primary_query из Master_Briefs - эталонный запрос, за которым следят отдельно от того, попал ли он в скоринг. Проверка сверяет, кто фактически лидирует в GSC, с кэшированным или живым SERP, и выдаёт один из статусов: подтверждён нужный URL, подтверждён конфликт, смешанный результат, владелец вне топ-10, ошибка данных или "неоднозначный запрос", если в нём есть название бренда и в выдаче участвует главная страница или карточка товара (по бренду законно ранжируется что угодно, это не конфликт категорий).

Это сознательно отдельный от скоринга слой: контроль эталонных запросов ничего не добавляет и не снимает с risk_score, это параллельная сверка "ранжируется то, что должно?", ценная сама по себе, даже когда общий скоринг ничего не подсветил.

Визуализация: граф конфликтов, а не просто список

На выходе скана - два изображения. Первое - это Graphviz DOT-граф: блок целевой категории → блок с перехваченными запросами и цветом по severity → блок конкурирующей страницы. Показываются только два самых рискованных активных конфликта, с явной пометкой "ещё N - в полном отчёте", если их больше.

Второе изображение - это обычный горизонтальный bar-чарт risk_score по всем активным инцидентам, тот же принцип, что и в контент-аудите: зелёного тут нет в принципе, чарт рисует только то, что уже прошло порог WATCH.

Помесячный отчёт: три графика, модель отклонения от сайта и AI-резюме

Отчёт 1-го числа месяца включает не только каннибализацию — у него собственный аналитический контур, сопоставимый по объёму со всей остальной системой.

Раз в месяц воркфлоу генерирует управленческий пакет:

  • Текстовую экспресс-сводку в Telegram (трафик, конверсии, поведение и срез после переоптимизации).

  • AI-интерпретацию поверх детерминированных расчётов с прогнозом (? НАБЛЮДАТЬ).

  • Три графических среза (макротренд, матрица категорий, позиции в выдаче).

  • Прикреплённый файл SEO_Categories_Monthly_YYYY-MM-DD.md с постраничной аналитикой по всем 16 категориям и сравнением год к году.


Три графика: от макротренда к позициям в выдаче

1. История 6 месяцев (сжато) + последние 60 дней подробно с таймлайном правок
Позволяет отличить сезонный спад от технической просадки и сопоставить тренд с реальными релизами.

SEO категорий: история 6 месяцев и 60 дней подробно
SEO категорий: история 6 месяцев и 60 дней подробно
  • Линия baseline: отсечка, с которой начался регулярный мониторинг и замеры.

  • Маркеры правок (SEO - 1 авг, SEO - 12 авг): точечные даты выкатки правок из таблицы SEO_Change_Log. Наглядно видно, изменился ли тренд после изменений на странице.

  • Сведение Google и Яндекс на одну шкалу: позволяет мгновенно заметить расхождение между поисковиками.


2. Матрица изменений по категориям за последний месяц
Построчный срез в разрезе каждого раздела каталога: Яндекс-визиты, Google-клики и показы с индикаторами динамики (▲ / ▼ / ●).

SEO категории: изменения за последний месяц
SEO категории: изменения за последний месяц
  • Фиксация ножниц: если показы растут (Google: 68 → 109 ▲), а клики стоят на месте (1 → 1 ●) - проблема в сниппете, кликабельности (CTR) или несоответствии интента.

  • Категории-локомотивы: сразу показывает ядро трафика - 7 036 из 13 996 показов Google приходятся на одну категорию ("Категория 1").


3. Тепловая карта primary-запросов (Google vs Яндекс)
Срез по 16 эталонным запросам категорий с цветовой кодировкой: ? топ 1-4, ? топ 5-10, ? >10. Стрелки месячного движения подключаются после накопления истории от 21 до 45 дней.

SERP primary: текущие позиции категорий
SERP primary: текущие позиции категорий
  • Алгоритмический рассинхрон: "Категория 3" сидят на #1 в Яндексе и на #5 в Google; "Категория 5" - #4 в Яндексе и >10 в Google. Это сразу отсекает текстовый переспам и указывает на ссылочные или поведенческие различия.

  • Изолированный контроль: статус primary-запросов не влияет на скоринг каннибализации это параллельная витрина ранжирования ключевых страниц.


Экспресс-сводка и AI-выжимка в Telegram

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

Пример сообщений в Telegram: экспресс-сводка и AI-резюме

? SEO Сводка по Категориям (30 дней)

ТРАФИК И ДИНАМИКА • Яндекс Визиты: 140 (пред. 30 дней: 195, Δ -55 ?) • Google Клики: 220 (пред. 30 дней: 360, Δ -140 ?) • Google Показы: 31 500 (пред. 30 дней: 45 000, Δ -13 500 ?)

ПОСЛЕ ПЕРЕОПТИМИЗАЦИИ (факт к ожиданию по сайту) • Яндекс: 170 → 140 ? -17.6% · ожидалось ~185 · хуже тренда сайта • Google клики: 350 → 220 ? -37.1% · ожидалось ~310 · хуже тренда сайта • Google показы: 42 000 → 31 500 ? -25.0% · ожидалось ~30 800 · в русле сайта

КОНФЛИКТЫ И ВЫДАЧА • ?️ Каннибализация категорий: 1 конфликт (ущерб низкий) • ? Межтиповой перехват: 1 пересечение (ущерб низкий) • ? SERP primary (16 запросов): Google 4? / 4? / 8? · Яндекс 3? / 6? / 7?

? SEO-анализ категорий за месяц (AI-резюме)

  1. Макротренд: трафик категорий снизился сильнее общего движения сайта (Яндекс по сайту +5.8%, по категориям -28.2%). При этом показы в Google просели синхронно с общим трендом каталога.

  2. Драйверы: основной объём трафика удерживают категории сегментов "Alpha" и флагманская линейка "Бренд X". В Яндексе локальный спад затронул большинство ключевых посадочных страниц.

  3. SERP: в Google в первой четвёрке ранжируются эталонные запросы категорий Alpha, Beta, Gamma и Delta. В Яндексе в топ-4 удерживаются коммерческие посадочные категорий Epsilon, Alpha и Zeta.

  4. Прогноз: ? НАБЛЮДАТЬ. Трафик категорий падает быстрее сайта, зафиксированы единичные пересечения интентов без подтверждённого коммерческого ущерба. Рекомендовано подготовить варианты разграничения интентов в метатегах и продолжать сбор метрик.


Модель ожиданий по сайту: почему плохой месяц — не всегда RED

Оценивать категорию в вакууме бессмысленно: если раздел упал на 15%, а весь каталог из-за сезонности просел на 30%, категория чувствует себя лучше рынка.

Система рассчитывает две оценки отклонения от ожидания: structural_residual_pct (к годовому тренду сайта) и short_residual_pct (к динамике за последний месяц). Итоговый статус балансирует оба сигнала: если годовой тренд отрицательный, но за последние 30 дней наметился разворот вверх, категория не уходит в тревогу.

Код: расчет ожиданий по сайту и калибровка статуса
const expectedFromSite = (yoyValue, siteCurrent, siteYoy) =>
  (Number(siteYoy) > 0 ? Number(yoyValue) * Number(siteCurrent) / Number(siteYoy) : null);

const residualPct = (actual, expected, minExpected = 1) =>
  (expected !== null && Number(expected) >= minExpected 
    ? round1((Number(actual) / Number(expected) - 1) * 100) 
    : null);

// Разворот на коротком окне смягчает застарелый негативный годовой тренд
if (structural === 'CATEGORY_SPECIFIC_LOSS') {
  if (shortRelative === 'BETTER_THAN_SITE' || shortS === 'UP') return 'YELLOW';
  return 'RED';
}

Статус

Код

Логика классификатора

В отчёте за месяц

? Норма

GREEN

Раздел растёт или держится в русле тренда сайта

0 категорий (весь каталог просел сильнее сайта)

? Наблюдение

YELLOW

Разнонаправленные метрики или отскок на коротком окне

10 категорий (в т.ч. "категория 1")

? Внимание

RED

Синхронное падение по месяцу и году без отскока

0 категорий (системного краха нет)

Мало данных

LOW_DATA

Меньше 10 визитов/кликов (нерепрезентативный объём)

6 категорий (выводы отложены)

Детальный Markdown-аудит

Вместе с графиками бот отправляет файл SEO_Categories_Monthly. В нём каждая категория расписана по визитам, отказам, времени на странице и динамике YoY. Это позволяет сразу провалиться в цифры конкретного URL, получившего статус YELLOW.

Пример полного Markdown-отчёта
# SEO-анализ категорий за месяц · 30 дней

> Только категории каталога.

## ? После переоптимизации

- Яндекс-визиты: **79 → 56** (-29.1%); ожидалось по движению сайта ~83; **хуже общего тренда сайта**.
- Google клики: **185 → 109** (-41.1%); ожидалось по движению сайта ~148; **хуже общего тренда сайта**.
- Google показы: **19 906 → 14 398** (-27.7%); ожидалось по движению сайта ~14 041; **примерно в русле сайта**.

## ? Сводка за последние 30 дней

- Яндекс-визиты: **81 → 56** (-30.9%)
- Google клики: **181 → 108** (-40.3%)
- Google показы: **20 011 → 13 996** (-30.1%)
- Яндекс по всему сайту: **2 533 → 2 691** (+6.2%)
- Google клики по всему сайту: **1 871 → 1 457**
- Google показы по всему сайту: **88 831 → 60 970**

## ? Год к году · дополнительный контекст

- Яндекс: 4 из 16 категорий · 54 → 32 (-40.7%)
- Google клики: 6 из 16 · 69 → 71 (+2.9%)
- Google показы: 9 из 16 · 7 506 → 12 709 (+69.3%)

## ? SERP primary — позиции и динамика

> Показана позиция именно назначенной категории (owner URL). Месячные стрелки появятся после накопления истории 21–45 дней.

- Primary-запросов: **16**
- Текущий срез: **2026-08-27**
- Google: TOP 1–4 **4** · 5–10 **4** · >10 **8**
- Яндекс: TOP 1–4 **3** · 5–10 **6** · >10 **7**

| Категория | Primary query | Google | Δ | Яндекс | Δ |
|---|---|---:|---:|---:|---:|
| Категория Alpha | `купить товар alpha каталог` | #2 | — | #3 | — |
| Категория Beta | `товары категории beta цена` | #4 | — | >10 | — |
| Категория Gamma | `линейка оборудования gamma` | #5 | — | #1 | — |
| ... | *[ещё 13 primary-запросов]* | ... | — | ... | — |

## ? Изменения под наблюдением

*Активных WATCH-изменений нет.*

---

## ? Норма — 0

*Нет*

---

## ? Требуют наблюдения — 10

### ? Категория Alpha (Флагманская линейка)

**Яндекс Визиты:** **20**
├ Предыдущие 30 дней: 33 (Δ -13) ?
└ Год назад: 9 (Δ +11) ?

**Google Показы:** **7 036**
├ Предыдущие 30 дней: 8 176 (Δ -1 140) ?
└ Год назад: 1 430 (Δ +5 606) ?

**Google Клики:** **34**
├ Предыдущие 30 дней: 48 (Δ -14) ?
└ Год назад: 40 (Δ -6) ?

**Поведение**
Отказы: **50%**
└ Предыдущие 30 дней: 48.5% (Δ +1.5 п.п.) ?

Время: **1м 21с**
└ Предыдущие 30 дней: 1м 4с (Δ +16с) ?

Глубина: **1.6**
└ Предыдущие 30 дней: 1.55 (Δ +0.05) ?

*? Вывод:* За месяц показатели идут в разные стороны: локальный спад месяца на фоне долгосрочного роста к прошлому году. Яндекс снижается, Google-клики снижаются, Google-показы снижаются.

---

### ? Категория Beta (Сегмент Pro / Тяжёлая серия)

**Яндекс Визиты:** **6**
├ Предыдущие 30 дней: 16 (Δ -10) ?
└ Год назад: 32 (Δ -26) ?

**Google Показы:** **524**
├ Предыдущие 30 дней: 1 201 (Δ -677) ?
└ Год назад: 101 (Δ +423) ?

**Google Клики:** **8**
├ Предыдущие 30 дней: 23 (Δ -15) ?
└ Год назад: недостаточно данных для сравнения

**Поведение**
Отказы: **33.3%**
└ Предыдущие 30 дней: 31.3% (Δ +2.1 п.п.) ?

Время: **4м 58с**
└ Предыдущие 30 дней: 4м 23с (Δ +35с) ?

Глубина: **2**
└ Предыдущие 30 дней: 3.31 (Δ -1.31) ?

⚪ Поведение: выборка меньше 10 визитов из Яндекса — не используем как устойчивый сигнал.

*? Вывод:* Категория снижается заметно сильнее общего тренда сайта. За месяц: Яндекс снижается, Google-клики снижаются, Google-показы снижаются. Требуется ручной аудит сниппетов.

---

... [остальные 8 категорий в статусе ? Требуют наблюдения опущены для краткости] ...

---

## ? Требуют внимания — 0

*Нет*

---

## ? Проверка данных — 0

*Нет*

---

## ⚪ Мало данных — 6

... [6 категорий каталога с выборкой менее 10 визитов/кликов опущены: выводы отложены до накопления данных] ...

---

## ⚙️ Данные

- Метрика Яндекс: OK / OK / OK
- GSC: OK / OK / OK
- Snapshot: PAGE-V3:2026-08-30:M:2026-08-30
- Каннибализация: CANNIB:2026-08-30:YQ:2026-08-30

Отслеживание ручных правок - система не закрывает вопрос сама

Для контроля внедрений заведена таблица SEO_Change_Log. Пайплайн работы с ней выстроен так, чтобы исключить ложные выводы:

  1. Фиксация правки (руками): заносим URL, дату релиза, суть изменения и проверяемую гипотезу со статусом WATCH.

  2. Расчёт эффекта (n8n): нода Analyze SEO Changes Monthly сравнивает фактическую динамику с модельной за равные отрезки времени "до" и "после" даты внедрения, а затем строит график восстановления, когда накопится репрезентативный объём данных.

  3. Валидация результата (руками): система может показать, что трафик восстанавливается быстрее или медленнее прогноза, но перевести статус в RESOLVED может только специалист.

Это осознанное ограничение автоматизации, а не недоработка: подтверждение причинно-следственной связи (помогла именно наша правка, а не апдейт выдачи или сезонный всплеск) всегда остаётся за человеком.


Почему логика детерминированная, а LLM — только рассказчик

Здесь работает тот же инженерный принцип, что и в предыдущих статьях цикла (GEO-детект без второй модели, regex вместо тяжёлого HTML-парсера в контент-аудите):

Вся аналитика строго детерминирована: risk_score, severity, lifecycle и логика диагнозов рассчитываются исключительно математикой в Code-нодах на чистом JS.

LLM (в моём случае Qwen) получает на вход уже готовый JSON и выступает исключительно в роли интерфейса - собирает сухие цифры в связную сводку для Telegram. Замените модель на любую другую, отключите её вовсе или отдавайте сырые данные напрямую в дашборд - скоринг, вердикты и приоритеты не изменятся ни на балл.

Результаты: как именно получается 59 из 100

Собранный воркфлоу производит инцидент-карточки такого вида:

Кластер: "ложки / вилки" — HIGH 59/100
Владелец: /collection/example-a · Конкурент: /collection/example-b (категория)
Confidence: HIGH (0.9) · Lifecycle: PERSISTING · Consecutive runs: 11
Показы 28д: владелец 0 / конкурент 127 (100% доля конкурента)
Клики 28д: владелец 0 / конкурент 0
Пред. 28д: владелец 0 / конкурент 217
7д: владелец 0 / конкурент 14; пред. 7д: владелец 0 / конкурент 37

Разложить 59 баллов на компоненты можно прямо по формуле:

Фактор

Расчёт

Балл

Доминирование

доля конкурента 100% (потолок)

25

Смещение позиции

у владельца 0 показов, у конкурента позиция ≤20

20

Захват кликов

кликов 0 у обоих - фактор не сработал

0

Тренд периода

у владельца 0 показов и до, и после - падать неоткуда, тренд не засчитан

0

Структурное несоответствие

владелец 0 показов при конкуренте 10+

10

Персистентность

11 прогонов подряд ≥ 3

10

Сырая сумма

65

Confidence

127 показов в паре → 0.85, плюс +0.05 за 7+ запросов в кластере

×0.90

Итог

round(65 × 0.90)

59 → HIGH

Показательный момент: у конкурента снижение показов 217 → 127 за месяц и 37 → 14 за неделю - конфликт объективно слабеет, но lifecycle всё равно остаётся PERSISTING, а не переключается в IMPROVING, потому что для IMPROVING риск-скор должен упасть минимум на 10 баллов от прошлого замера, а не просто показать снижение показов конкурента. Отдельная деталь — при confidence 0.90 и compShare 100% формально выполнены два из трёх условий CRITICAL (доля ≥65%, 11 прогонов ≥2), но сама планка risk_score ≥75 не взята: без вклада от тренда и кликов сырых 65 баллов даже с максимальным confidence не хватает. Конфликт стабильный и объёмный, но не "горит" - ровно то разделение, ради которого и городился шестифакторный подсчёт вместо одного правила "доля выше X% → тревога".

Плюсы и ограничения подхода

Область

Сильные стороны (Плюсы)

Ограничения и компромиссы

Скоринг и аналитика

Диагноз вместо списка пересечений: шкала риска 0-100 с конкретным планом действий вместо голого факта совпадения URL.

Эвристические веса: коэффициенты (25/20/15…) и пороги подобраны инженерной оценкой, а не обучены на исторических данных бизнеса.

Фильтрация шума

Защита от ложных тревог: уровень CRITICAL требует повторов или объёма; свежий месячный отскок гасит застарелую годовую тревогу.

Чувствительность к конфигу: модель слепо доверяет Owner_Map - при ошибке в таблице скоринг честно рассчитает риск для неправильной пары.

Инженерия и бюджет

0 рублей на платные тарифы: двухуровневый TTL-кэш и точечные дозапросы строго удерживают SerpApi в лимите 250 запросов/мес.

Хрупкость при переносе: домен захардкожен в хелперах, а бренд ловится базовой регуляркой - при копировании на другой сайт код нужно вычищать руками.

Валидация решений

Контроль причинности: n8n показывает динамику до/после, но статус RESOLVED подтверждает только человек, исключая ложные автовыводы.

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

Стоимость

GSC, Яндекс.Метрика и Яндекс.Вебмастер - бесплатные. У SerpApi для живых SERP-проверок есть бесплатный лимит - 250 запросов в месяц, дальше тарифы стартуют от $25 за 1000. Вся конструкция с TTL-кэшем и точечным дозапросом построена так, чтобы держаться в этом бесплатном лимите: свежий кэш перекрывает большинство прогонов, а живой запрос идёт только для действительно неоднозначных случаев. Весь дизайн freshness/backfill существует ровно для того, чтобы никогда не пришлось переходить на платный план.

Код

Репозиторий тот же — n8n-seo-monitor-suite. Воркфлоу из этой статьи - в monthly-anticannibal/: README с полной схемой обеих таблиц состояния, форматом карточки инцидента и списком статусов контроля primary-запросов.

Про GEO-мониторинг видимости в ИИ-ответах и про ежедневный/еженедельный контент-аудит - первые две статьи цикла.

Комментарии (0)