Классический совет по каннибализации ключевых слов: нашёл две страницы, которые ранжируются по одному запросу — определи главную, а остальные подчисти или склей редиректом. Проблема в том, что данный случай — это ещё не диагноз, а вот радикальные действия могут только ухудшить ранжирование. Причиной может быть шум одной недели, естественное пересечение смежных тем, или запрос, где две твои же страницы законно делят выдачу. Настоящая каннибализация — это когда конкурирующая страница действительно забирает трафик, который должен был идти нужной, и делает это не первую неделю.
Это третий и последний воркфлоу из связки 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..25const dominanceScore = compShare <= 0.35 ? 0 : clamp((compShare - 0.35) / 0.55 * 25, 0, 25);// Персистентность: 0..10const 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 |
Условие |
|---|---|
|
|
суммарно меньше 10 показов и меньше 2 кликов |
|
|
risk_score ≥ 30 |
|
|
risk_score ≥ 55 |
|
|
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);
Результат — предложение с меткой уверенности:
|
Метка |
Уверенность |
Что значит |
|---|---|---|
|
|
высокая |
точное совпадение с эталонным запросом категории |
|
|
высокая |
сработал один однозначный маркер-слово |
|
|
низкая |
сработали маркеры нескольких категорий сразу — нужна ручная проверка |
|
|
— |
запрос про конкретную модель бренда, намеренно не привязывается ни к одной категории |
|
|
— |
ни один маркер не сработал |
Разница с основным скорингом принципиальна: 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 дней подробно с таймлайном правок
Позволяет отличить сезонный спад от технической просадки и сопоставить тренд с реальными релизами.
-
Линия baseline: отсечка, с которой начался регулярный мониторинг и замеры.
-
Маркеры правок (
SEO - 1 авг,SEO - 12 авг): точечные даты выкатки правок из таблицыSEO_Change_Log. Наглядно видно, изменился ли тренд после изменений на странице. -
Сведение Google и Яндекс на одну шкалу: позволяет мгновенно заметить расхождение между поисковиками.
2. Матрица изменений по категориям за последний месяц
Построчный срез в разрезе каждого раздела каталога: Яндекс-визиты, Google-клики и показы с индикаторами динамики (▲ / ▼ / ●).
-
Фиксация ножниц: если показы растут (
Google: 68 → 109 ▲), а клики стоят на месте (1 → 1 ●) — проблема в сниппете, кликабельности (CTR) или несоответствии интента. -
Категории-локомотивы: сразу показывает ядро трафика — 7 036 из 13 996 показов Google приходятся на одну категорию («Категория 1»).
3. Тепловая карта primary-запросов (Google vs Яндекс)
Срез по 16 эталонным запросам категорий с цветовой кодировкой: 🟢 топ 1-4, 🟡 топ 5-10, 🔴 >10. Стрелки месячного движения подключаются после накопления истории от 21 до 45 дней.
-
Алгоритмический рассинхрон: «Категория 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-резюме)
Макротренд: трафик категорий снизился сильнее общего движения сайта (Яндекс по сайту +5.8%, по категориям -28.2%). При этом показы в Google просели синхронно с общим трендом каталога.
Драйверы: основной объём трафика удерживают категории сегментов «Alpha» и флагманская линейка «Бренд X». В Яндексе локальный спад затронул большинство ключевых посадочных страниц.
SERP: в Google в первой четвёрке ранжируются эталонные запросы категорий Alpha, Beta, Gamma и Delta. В Яндексе в топ-4 удерживаются коммерческие посадочные категорий Epsilon, Alpha и Zeta.
Прогноз: 🟡 НАБЛЮДАТЬ. Трафик категорий падает быстрее сайта, зафиксированы единичные пересечения интентов без подтверждённого коммерческого ущерба. Рекомендовано подготовить варианты разграничения интентов в метатегах и продолжать сбор метрик.
Модель ожиданий по сайту: почему плохой месяц — не всегда 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';}
|
Статус |
Код |
Логика классификатора |
В отчёте за месяц |
|
🟢 Норма |
|
Раздел растёт или держится в русле тренда сайта |
0 категорий (весь каталог просел сильнее сайта) |
|
🟡 Наблюдение |
|
Разнонаправленные метрики или отскок на коротком окне |
10 категорий (в т.ч. «категория 1») |
|
🔴 Внимание |
|
Синхронное падение по месяцу и году без отскока |
0 категорий (системного краха нет) |
|
⚪ Мало данных |
|
Меньше 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. Пайплайн работы с ней выстроен так, чтобы исключить ложные выводы:
-
Фиксация правки (руками): заносим URL, дату релиза, суть изменения и проверяемую гипотезу со статусом
WATCH. -
Расчёт эффекта (n8n): нода
Analyze SEO Changes Monthlyсравнивает фактическую динамику с модельной за равные отрезки времени «до» и «после» даты внедрения, а затем строит график восстановления, когда накопится репрезентативный объём данных. -
Валидация результата (руками): система может показать, что трафик восстанавливается быстрее или медленнее прогноза, но перевести статус в
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 / конкурент 2177д: владелец 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…) и пороги подобраны инженерной оценкой, а не обучены на исторических данных бизнеса. |
|
Фильтрация шума |
Защита от ложных тревог: уровень |
Чувствительность к конфигу: модель слепо доверяет |
|
Инженерия и бюджет |
0 рублей на платные тарифы: двухуровневый TTL-кэш и точечные дозапросы строго удерживают SerpApi в лимите 250 запросов/мес. |
Хрупкость при переносе: домен захардкожен в хелперах, а бренд ловится базовой регуляркой — при копировании на другой сайт код нужно вычищать руками. |
|
Валидация решений |
Контроль причинности: n8n показывает динамику до/после, но статус |
Человеческий фактор: система не закрывает инциденты автономно — разбор спорных кейсов и ведение лога правок требуют дисциплины оператора. |
Стоимость
GSC, Яндекс.Метрика и Яндекс.Вебмастер — бесплатные. У SerpApi для живых SERP-проверок есть бесплатный лимит — 250 запросов в месяц, дальше тарифы стартуют от $25 за 1000. Вся конструкция с TTL-кэшем и точечным дозапросом построена так, чтобы держаться в этом бесплатном лимите: свежий кэш перекрывает большинство прогонов, а живой запрос идёт только для действительно неоднозначных случаев. Весь дизайн freshness/backfill существует ровно для того, чтобы никогда не пришлось переходить на платный план.
Код
Репозиторий тот же — n8n-seo-monitor-suite. Воркфлоу из этой статьи — в monthly-anticannibal/: README с полной схемой обеих таблиц состояния, форматом карточки инцидента и списком статусов контроля primary-запросов.
Про GEO-мониторинг видимости в ИИ-ответах и про ежедневный/еженедельный контент-аудит — первые две статьи цикла.
ссылка на оригинал статьи https://habr.com/ru/articles/1080278/