Функциональная спецификация · раздел админки № 4

SEO-редакция

Раздел «SEO» операторской админки: блочный редактор статей с ИИ-помощником и SEO-баллом, публикация на домен своего продукта в один клик, аналитика каждой статьи из четырёх источников.

Версия: v3 · 27.08.2026 Статус: draft — до закрытия открытых вопросов §24 Владелец: владелец продукта (заказчик спецификации) Приоритеты: MUST обязательно · SHOULD желательно · COULD при возможности
Как читать этот документЭто живая спецификация: каждое решение по открытым вопросам вносится сюда же, а не остаётся в переписке. §1–4 объясняют «зачем и для кого», §5–7 — рамку решений, §8–21 — поведение системы в деталях (каждое нормативное требование имеет номер вида ED-3, на который ссылаются задачи и тесты), §22–23 — граничные случаи и качество, §24–27 — план, вопросы и границы. Тест полноты: разработчик может строить, а QA — писать тест-план, не задавая вопросов вне этого документа.

01

Проблема и цели

Проблема. У продуктов «По душе» (события) и «По любви» (знакомства) нет канала бесплатного стабильного притока пользователей из поиска: нет блога, публичные страницы не оптимизированы, а команда не обладает SEO-экспертизой, чтобы писать находимые статьи вручную. Платный трафик дорожает; органический поиск — единственный канал, который со временем дешевеет.

Решение. Инструмент внутри своей админки, который берёт SEO-экспертизу на себя: менеджер сосредоточен на смысле, система — на находимости, а ИИ ускоряет производство при обязательном человеческом контроле.

Метрики успеха

МетрикаРольОпределениеЦель
Конверсии из статейглавнаяКлики «скачать приложение» + клики по событиям/анкетам из статей (cta_click + feed_item_click, §18)стабильный недельный поток новых пользователей из статей; целевая цифра — открытый вопрос O-3 (§26)
Визиты из поискавспомогательнаяПросмотры статей с источником Яндекс/Googleрост месяц к месяцу после 3-го месяца (индексация инерционна)
Доля статей «в топе»вспомогательнаяСтатьи со средней позицией ≤ 10 хотя бы по одному запросу≥ 30% опубликованных к 6-му месяцу
Здоровье контентагигиеническаяСредний SEO-балл опубликованных; доля «дочитал»балл ≥ 80; дочитываемость ≥ 25%

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

02

Допущения

03

Персоны

Персона A · главная

Марина, контент-менеджер

Пишет хорошо, в SEO — ноль. Не знает слов «canonical» и «метатег» и не должна узнать. Ей нужны: понятная цель («доведи балл до 80»), подсказки императивами («сократи заголовок до 60 знаков»), ИИ, который делает черновую работу. Роль в админке: Content.

Персона B

Админ платформы

Настраивает: авторов, базу знаний, витринные анкеты, бюджеты ИИ. Смотрит сводную аналитику и отвечает за то, чтобы блог не попал под фильтры. Роль: Admin.

Персона C

Читатель из поиска

Пришёл из Яндекса с конкретным вопросом («куда сходить в москве на выходных»). Ждёт быстрый ответ в первом экране, скан-структуру, живые примеры. Идеальный исход — клик по событию или «скачать приложение».

Не персона

SEO-специалист

Профессионала с Ahrefs и Key Collector в команде нет и не предполагается — инструмент не обязан удовлетворять его привычки (это non-goal, §27).

04

Сценарии использования

S1 — статья с ИИ, от идеи до публикации (главный путь)

  1. Марина открывает SEO → Статьи → «Новая статья», выбирает продукт «События».
  2. В подборе запросов вводит «куда сходить в москве» — видит частотности и сезонность, отмечает главный запрос и 4 дополнительных.
  3. Жмёт «Попросить ИИ»: получает план (H1, разделы, где CTA и лента), правит два раздела, жмёт «Написать».
  4. Через минуту черновик в редакторе с плашкой «Черновик от ИИ — вычитайте». Балл 64: чек-лист просит сократить title, добавить внутренние ссылки и alt к картинкам.
  5. Марина вычитывает, правит факты, вставляет блок «Лента» (Москва, 14 дней, 6 карточек), принимает у ИИ два предложения по title. Балл 84. Жмёт «Вычитано», затем «Опубликовать».
  6. Статья открывается на домене «По душе» по адресу /blog/kuda-shodit-v-moskve; Яндекс получает IndexNow-пинг. Общее время: ~1,5 часа вместо дня.

S2 — статья без ИИ

Как S1, но текст Марина пишет сама с нуля; ИИ-панель свёрнута. Все подсказки, балл и публикация работают одинаково — ИИ строго опционален (плашки «вычитайте» нет).

S3 — доработка по аналитике

Через месяц во вкладке «Аналитика» у статьи подсказка: «запрос "куда сходить в москве бесплатно" — позиция 11, близко к топу». Марина открывает статью из карточки аналитики, добавляет раздел про бесплатные события, жмёт «Опубликовать изменения» — дата обновления меняется, поисковики видят свежесть. Через две недели по графику видно рост кликов после отметки публикации.

S4 — авария и откат

Стажёр случайно удалил половину опубликованной статьи и опубликовал. Марина открывает «⋯ → Версии», сравнивает с предыдущей, жмёт «Восстановить» и публикует. В аудит-логе видно, кто и что сделал. Потерь нет.

S5 — конфликт: двое в одной статье

Пока Марина редактирует, Олег открывает ту же статью — видит плашку «Сейчас редактирует Марина» и режим «только чтение». Ему нужно срочно: жмёт «Всё равно редактировать» — блокировка переходит к нему, у Марины появляется предупреждение «Редактирование перехватил Олег — ваши несохранённые правки: скопировать». Никто молча не потерял работу. (Механика — EC-9, §22.)

05

Решения (история двух грилей)

ВопросРешениеКомментарий
ТематикаОба приложенияПоле «продукт» обязательно: events | dating; определяет домен, контекст ИИ, CTA, тип ленты.
ДоменыУ каждого продукта свойСобытия — новый домен (купить); дейтинг — не решено (O-2). Движок один.
Язык и поискРусский, упор на ЯндексGoogle — вторым номером.
Кто публикуетЛюбой менеджерДоступ к разделу = право публиковать (роли Admin, Content).
ИИOpenRouterВсе 4 режима; ИИ не публикует сам; ИИ-черновик требует вычитки.
База знаний ИИДокументы + живые данныеКурируемые доки + свежие цифры каталога событий.
РедакторБлочный (Notion-like)Контент — структура блоков, не сырой HTML.
Лента в статьеДа, опциональноЖивые события или витринные анкеты; клики — в аналитике.
АналитикаГибрид, 4 источникаСвой счётчик + Метрика (+Вебвизор) + Вебмастер + GSC.
ИнструментыВордстат · балл · читабельностьАнализ конкурентов из выдачи — исключён полностью.
Жизненный циклВерсии + расписаниеСнапшот при публикации, откат, отложенная публикация.
АвторствоАвторы-персоныСправочник; страница автора на сайте.
Цель статьиПриложения + вебОбе конверсии считаются; главная метрика проекта — §1.
Главная метрикаУстановки из статейГриль-2: успех = конверсии, не голый трафик.
Конфликт правокМягкая блокировкаГриль-2: «редактирует Х» + перехват с предупреждением (EC-9).

06

Домены и архитектура

ПродуктДоменСтатусЧто живёт
«По душе» (события)<домен-событий>.ruкупить — блокер этапа 0 (O-1)витрина событий + блог /blog/…
«По любви» (дейтинг)не выбран (кандидат plbvi.ru)открытый вопрос O-2блог /blog/…; движок тот же

Принцип: один движок — много доменов. Блог — одно приложение с серверным рендером, развёрнутое на обоих доменах; настройка SITE_PRODUCT решает, чьи статьи домен отдаёт. Смена/добавление домена — конфигурация, не разработка. На каждый домен — свой комплект внешних привязок: счётчик Метрики, сайт в Вебмастере, ресурс GSC, sitemap, robots.txt, ключ IndexNow. Менеджер этого не видит: он выбирает продукт статьи, остальное система делает по нужному домену.

Админка · SEOменеджер + ИИ
→
Сервер (Django)статьи, версии, счётчик, интеграции
→
Блог-движок (SSR)домен событий · домен дейтинга
→
Поисковикиsitemap + IndexNow → индекс → читатели
→
Аналитикасчётчик · Метрика · Вебмастер · GSC

Серверный рендер обязателен (Яндекс рендерит JavaScript нестабильно). Кеш страниц 5–10 минут; после публикации кеш конкретной страницы сбрасывается принудительно.

07

Состав раздела и реестр требований

Вкладка 1

Статьи

Список + редактор (§9–15).

Вкладка 2

Аналитика

Дашборд + карточки статей (§19).

Вкладка 3

База знаний

Документы для ИИ (§20).

Вкладка 4

Авторы

Авторы-персоны (§20).

Реестр верхнеуровневых требований. Каждое — атомарное и проверяемое; детали — в указанном разделе. Приоритеты SHOULD/COULD подтверждаются владельцем (вопрос O-5).

IDСистема должна…ПриоритетДетали
LS-1показывать список статей с фильтрами, сортировкой и действиямиMUST§9
ED-1давать блочный редактор с автосохранением ≤ 5 с после паузы вводаMUST§10
ED-2поддерживать все типы блоков из §10, включая CTA и карточку событияMUST§10
ED-3ограничивать одновременное редактирование мягкой блокировкой с перехватомMUST§22 EC-9
MT-1вести title/description с пиксельным предпросмотром сниппета и автогенерациейMUST§11
MT-2генерировать всю техническую разметку страницы без участия менеджераMUST§11
SC-1считать SEO-балл 0–100 по 20 проверкам §12 живо при редактировании; истина — на сервереMUST§12
KW-1давать подбор запросов из Вордстата с кешем 7 днейMUST§13
AI-1генерировать статью целиком: бриф → план → черновик, с флагом «нужна вычитка»MUST§14
AI-2давать ИИ-чат с контекстом статьи и diff-подтверждением правокMUST§14
AI-3давать правку выделенного текста (перефразировать/сократить/расширить/упростить)SHOULD§14
AI-4генерировать картинки по описаниюSHOULD§14
AI-5не давать ИИ публиковать и блокировать публикацию невычитанного ИИ-черновикаMUST§14, §16
FD-1поддерживать блок «Лента событий» с живым фильтром и учётом кликовMUST§15
FD-2поддерживать блок «Лента анкет» только из витринных анкет с согласиемCOULD§15
PB-1публиковать статью конвейером §16 (версия → страница → sitemap → IndexNow)MUST§16
PB-2вести версии с просмотром, сравнением и откатомMUST§16
PB-3поддерживать отложенную публикацию (точность ≤ 1 мин)SHOULD§16
PB-4хранить историю slug и вечно отдавать 301 со старых адресовMUST§16
BL-1отдавать страницы блога серверным рендером со всеми страницами §17MUST§17
BL-2держать Core Web Vitals статей в зоне «хорошо»MUST§23
TR-1считать события чтения собственным анонимным счётчикомMUST§18
AN-1собирать метрики из Метрики/Вебмастера/GSC раз в сутки и показывать вкладку §19MUST (этап 2)§19
KB-1вести базу знаний и авторов-персон с влиянием на ИИ и страницыMUST§20
AC-1ограничивать раздел ролями и писать действия в аудит-логMUST§21

08

Модель данных

Статья (Article)

ПолеТипОписание
idUUIDИдентификатор.
productenumevents | dating. Обязательно. Определяет домен. После первой публикации не меняется (EC-12).
statusenumdraft → scheduled → published → unpublished; из unpublished можно вернуть в published.
slugстрока, уник. в продуктеАдрес /blog/<slug>; правила §11.
slug_historyсписок строкПрежние slug — вечные 301 (PB-4).
h1строка ≤ 120Видимый заголовок, единственный H1 страницы.
seo_title / seo_descriptionстроки ≤ 120 / ≤ 300Для выдачи; правила §11.
cover + cover_altкартинка (S3) + строкаОбложка ≥ 1200×630 = og:image; лимит загрузки 10 МБ (EC-6).
leadтекст ≤ 400Лид-абзац; Яндекс часто берёт сниппет отсюда.
blocksJSONМассив блоков §10. Сырой HTML не хранится.
authorFK → AuthorОбязателен для публикации.
keywordsJSON1 primary + до 10 secondary, с частотностями и датой снятия.
tagsсписок строкРубрики блога.
needs_reviewboolАвто-true при ≥ 50% текста от ИИ; публикация заблокирована до снятия человеком (AI-5).
seo_score0–100Последний серверный расчёт (SC-1).
editing_lockсотрудник + heartbeatМягкая блокировка (EC-9); снимается при выходе или молчании 2 мин.
scheduled_at / published_at / updated_atdatetimeРасписание / первая публикация / последняя публикация изменений.
created_byсотрудникДля аудита; на сайте не показывается.

Остальные сущности

СущностьПоляНазначение
ArticleVersionarticle, №, снапшот публикуемых полей, кто/когдаСоздаётся при каждой публикации; просмотр, сравнение, откат (PB-2).
Authorslug, имя, фото, био ≤ 600, регалии, is_activeАвтор-персона; страница /blog/authors/<slug>. Удаление запрещено — только деактивация (EC-13).
KnowledgeDocзаголовок, markdown, продукт, is_active, updated_atАктивные — целиком в контекст ИИ (§20).
ArticleChatarticle, сообщения, расход токеновИстория ИИ-чата статьи.
BlogHitarticle, тип, анонимный session_id, класс источника, время, payloadСырые события счётчика; хранение 180 дней (§18).
ArticleMetricDailyarticle, дата, источник (own/metrika/webmaster/gsc), метрики JSONСуточные агрегаты; хранятся вечно; вся вкладка §19 строится на них.
ShowcaseProfileимя, возраст, город, фото, «о себе» ≤ 200, согласие (дата/основание), is_activeВитринная анкета для ленты дейтинга; только ручные записи с согласием (FD-2).

09 · LS

Список статей

Таблица в стандартном стиле админки (панель, sticky-шапка, пагинация по 20).

СтолбецСодержимоеСортировка
Статьямини-обложка + H1 + slug серымпо алфавиту
Продуктбейдж «События» / «Знакомства»—
СтатусЧерновик · Запланирована (со временем) · Опубликована · Снята; + метка «нужна вычитка»да
SEO-баллчисло: 0–49 красный · 50–79 жёлтый · 80–100 зелёныйда
Авторавтор-персона—
Опубликована / обновленадатыда (по умолчанию новые сверху)
Просмотры 30 днчисло (появляется на этапе 2)да

Фильтры: статус, продукт, автор, рубрика, «нужна вычитка», поиск по названию/slug. Действия строки: в редактор · в аналитику · открыть на сайте · дублировать (копия-черновик) · снять с публикации. Удаление — только черновиков, с подтверждением; опубликованные не удаляются — снимаются (история и метрики сохраняются). Состояния экрана: пусто — крупные «Начать с нуля / Попросить ИИ»; загрузка — скелетон; ошибка — тост + «Повторить» без падения оболочки.

10 · ED

Редактор

/ops → SEO → Статьи → «Куда сходить в Москве на выходных»
Полотно статьиОбложка → H1 → лид → блоки. «+» между блоками, перетаскивание. Автосохранение ≤ 5 с после паузы (ED-1); индикатор «Сохранено 14:02 / Сохранение… / Нет связи — правки в браузере» (EC-8).
SEO-панельБалл-кольцо → чек-лист по группам (пункт раскрывается в «что сделать и почему») → метаданные (title, description, slug, обложка) → запросы → настройки (автор, рубрики, продукт).
ИИ-чатСворачиваемая панель; видит текущий текст; быстрые кнопки. Правки — только через diff-подтверждение.

Шапка: статус · индикатор сохранения · «Предпросмотр» (страница как на сайте, в новой вкладке, с noindex) · «Опубликовать» / «Опубликовать изменения» · меню «⋯»: версии, запланировать, снять с публикации, дублировать. Плашка мягкой блокировки — если статью уже редактируют (S5, EC-9).

Типы блоков (ED-2)

БлокНастройкиРендер
Абзацжирный, курсив, ссылка (внешние — rel="noopener", опция nofollow)<p>
ПодзаголовокH2 / H3 (H1 в блоках запрещён)<h2>/<h3> с якорем
Картинкафайл ≤ 10 МБ (сжатие в WebP, ресайзы), alt обязателен, подпись, ширина: колонка/широкая<figure> c width/height, lazy-load ниже первого экрана
Списокмаркированный / нумерованный<ul>/<ol>
Цитататекст + источник<blockquote>
Врезкасовет / важно / фактстилизованный <aside>
Вопрос-ответпары «вопрос → ответ»секция FAQ (H2 + пары H3/абзац); schema-разметку FAQ не ставим (§27)
Кнопка приложения (CTA)«скачать приложение» (сторы по продукту) / произвольная ссылка + тексткнопки; клик → cta_click
Карточка событияпоиск по каталогу → событиеживая карточка; архивное событие скрывается (EC-4)
Лента§15живая подборка
Разделитель—<hr>

Вставка из Word/Google Docs очищается до поддерживаемых блоков. «Содержание» генерируется автоматически из H2 при их числе ≥ 3.

11 · MT

Метаданные: title, description и остальное

Заголовок для выдачи (seo_title → <title>) — MT-1

Описание (seo_description → meta description)

Адрес (slug)

Автоматическая разметка (MT-2 — менеджер её не видит и не может сломать)

<title>Куда сходить в Москве: 15 идей на выходные — По душе</title>
<meta name="description" content="Собрали 15 проверенных мест…">
<link rel="canonical" href="https://ДОМЕН/blog/kuda-shodit-v-moskve">  ← срезает UTM
<meta property="og:type" content="article">   + og:title/description/url/site_name
<meta property="og:image" content="…1200×630…">
<meta name="twitter:card" content="summary_large_image">
<script type="application/ld+json">            ← для Google; Яндексу хватает HTML+OG
{ "@type":"Article", "headline":h1, "image":[16:9, 4:3, 1:1],
  "author":{"@type":"Person","name":автор,"url":стр.автора},
  "datePublished":…, "dateModified":…,
  "publisher":{"@type":"Organization","name":бренд,"logo":…} }
</script>
<script type="application/ld+json">{ "@type":"BreadcrumbList", … }</script>

Плюс: видимые даты «Опубликовано / Обновлено», блок автора, noindex на черновиках и предпросмотрах.

12 · SC

SEO-балл: 20 проверок и весов

78

Считается кодом (без ИИ) при каждом сохранении, живо в редакторе; истина — серверный пересчёт при публикации (SC-1). Зоны: 0–49 · 50–79 · 80–100. Публикация возможна с любым баллом; при < 50 — предупреждение (EC-10). Текст перед проверками лемматизируется («Москва/в Москве/москвичи» — одно слово).

#Группа / проверкаУсловие «зачёт»Вес
1Мета · Titleзаполнен, ≤ 580 px, лемма главного запроса в первых 4 словах8
2Description120–160 знаков, содержит главный запрос, не дублирует title7
3Slugлатиница, ≤ 6 слов, содержит транслит ключа3
4Обложказадана, ≥ 1200×630, alt заполнен5
5Структура · H120–90 знаков, содержит главный запрос4
6ИерархияH3 не раньше первого H2, без пропусков уровней4
7Подзаголовкипри > 800 слов — H2 каждые ≤ 350 слов4
8Лид-абзацзаполнен, ≤ 400 знаков, содержит леммы запроса, без «воды»5
9Прямой ответдля H2-вопросов первый абзац секции — самодостаточный ответ (ставка на ИИ-ответы поисковиков)5
10Контент · Объём≥ 600 слов; 300–599 — половина5
11Главный запрослеммы в title, H1 и первых 100 словах8
12Доп. запросы≥ 60% secondary в H2 или тексте6
13Без переспамани одна значимая лемма > 3% слов (анти-фильтр Яндекса)4
14Читабельностьпредложений > 20 слов ≤ 25%; абзацы ≤ 4 предложений; подсветка канцелярита с заменами7
15Медиа · Altу 100% картинок4
16Иллюстрированность≥ 1 визуальный блок на 500 слов4
17Ссылки · Внутренние2–5 на наши статьи/события; редактор предлагает кандидатов6
18Внешние источникипри цифрах/фактах — ≥ 1 ссылка на первоисточник4
19Прочее · Авторвыбран4
20CTA≥ 1 CTA-блок (кнопка/карточка/лента)3
Итого100

Веса — серверная конфигурация, меняются без релиза. Каждый пункт в панели раскрывается в объяснение простым языком: что сделать и почему это важно.

13 · KW

Подбор запросов (Вордстат)

  1. Менеджер вводит тему (и, опционально, регион).
  2. Система показывает: частотность, топ связанных запросов за 30 дней, динамику по месяцам (сезонность), географию; у каждого запроса — эвристический интент («информационный» / «коммерческий — статья такой не возьмёт»).
  3. Менеджер отмечает 1 главный + до 10 дополнительных — они прикрепляются к статье, проверки №1, 11, 12 начинают их отслеживать.

Кеш обязателен: квота API ~1000 обращений/сутки; ответы кешируются 7 дней (запрос+регион). Частотности прикреплённых запросов обновляются раз в месяц фоном. Поведение при исчерпании квоты — EC-2.

14 · AI

ИИ-помощник

Вызовы — через сервер (ключ OpenRouter в браузер не попадает), ответы стримятся. Три модельные настройки: писательская (длинные тексты), быстрая (title/description/мелкие правки), картиночная; меняются в конфигурации без релиза.

Контекст каждого запроса

  1. SEO-гайд — зашитая выжимка правил §11–12 в форме инструкции.
  2. База знаний — активные документы по продукту статьи + общие (§20).
  3. Живой срез данных — автосводка каталога (события по городам, категории, примеры), кеш 1 час; для дейтинга — факты из базы знаний.
  4. Статья — блоки, метаданные, запросы, балл, незакрытые пункты чек-листа.

Статичная часть кешируется на стороне модели (prompt caching) — повторные обращения кратно дешевле. Проверки балла, читабельность и разметка работают без ИИ — мгновенно и бесплатно; ИИ включается только там, где нужен текст.

Режимы

  1. Статья целиком (AI-1): бриф (тема/пожелания или запрос из §13) → план (H1, разделы, места CTA и ленты; правится и перегенерируется) → генерация секциями с видимым прогрессом и стопом → черновик с флагом «нужна вычитка».
  2. Чат (AI-2): полный контекст статьи; предложения правок — diff «было → станет» с «Применить/Отклонить»; молчаливых изменений не бывает. Быстрые кнопки: план, лид, 5 title, сократить на треть, проверить факты (сверка с базой знаний). История хранится у статьи.
  3. Правка выделенного (AI-3): перефразировать · сократить · расширить · упростить · исправить ошибки; на быстрой модели; тот же diff.
  4. Картинки (AI-4): в блоке «Картинка» и в обложке: описание сцены (ИИ предлагает по секции) → 2–4 варианта → выбранный уходит в S3 обычной картинкой. Стиль бренда — документ базы знаний.
Ограничители (AI-5)ИИ никогда не публикует. Черновик с ≥ 50% ИИ-текста получает needs_review; «Опубликовать» недоступна до нажатия «Вычитано» (фиксируется в аудите). Месячный бюджет — настройка с индикатором: 80% — предупреждение, 100% — генерация выключена (чат и правки на быстрой модели — до 120%). Расход виден по каждой статье. Поведение при недоступности ИИ — EC-1.

15 · FD

Блок «Лента»

Лента событий (FD-1) — для статей продукта «события»

НастройкаВариантыПо умолчанию
Источникфильтр каталога: город, категории, период (ближайшие N дней), только бесплатныегород из темы, 14 дней
Ручной режимконкретные события списком (id)выкл
Сортировкаближайшие / популярныеближайшие
Количество3–96
Видсетка карточек / компактный списоксетка
Заголовок блокасвой текст«Ближайшие события»

Карточка: обложка, название, дата ближайшего сеанса, место, цена. Клик → страница события на том же домене. Прошедшие выпадают сами; пустая лента не рендерится совсем (EC-5). Первичный рендер серверный (индексируется, даёт свежесть), на клиенте — тихая актуализация.

Лента анкет (FD-2, COULD) — для статей продукта «знакомства»

Источник — только витринные анкеты (ShowcaseProfile): ручной набор с зафиксированным согласием (или редакционные персоны). Карточка: фото, имя, возраст, город, строка «о себе»; клик — умная ссылка на установку/открытие приложения (стор по устройству). Публичных страниц анкет не существует.

Жёсткое правило приватностиРеальные анкеты пользователей никогда не попадают на публичные индексируемые страницы. Только витринный набор с согласием (152-ФЗ); управление — роль Admin.

Аналитика ленты: feed_view (блок доехал до экрана) и feed_item_click (id и позиция карточки) — свой счётчик; в карточке статьи — CTR ленты и топ карточек; клики входят в главную метрику конверсий (§1).

16 · PB

Публикация

Конвейер «Опубликовать» (PB-1)

  1. Блокеры (не пускают): нет H1 · нет автора · нет обложки · не снят needs_review · пустой текст. Предупреждения (пускают после подтверждения): балл < 50 · нет прикреплённых запросов.
  2. Версия — снапшот в ArticleVersion (PB-2).
  3. Статус → published; выставляются даты.
  4. Страница — сброс кеша /blog/<slug> на домене продукта; доступна сразу со всей разметкой §11.
  5. sitemap.xml домена пересобирается (lastmod = updated_at).
  6. IndexNow-пинг в Яндекс (индексация за часы); Google — по sitemap. Ошибка пинга не блокирует публикацию — ретрай фоном (EC-3).
  7. Тост: «Опубликовано → открыть на сайте».

Остальные переходы

17 · BL

Публичный блог

СтраницаАдресСодержимое
Главная блога/blogкарточки статей (обложка, H1, лид, автор, дата, время чтения), пагинация по 12, рубрики.
Статья/blog/<slug>обложка → H1 → автор+даты+время чтения → лид → «Содержание» (H2 ≥ 3) → блоки → блок автора → «Читайте также» (3 по рубрикам, автоматически).
Рубрика/blog/t/<tag>статьи рубрики; мета по шаблону.
Автор/blog/authors/<slug>фото, био, регалии, статьи. Обязательна для E-E-A-T.
Карта сайта/sitemap.xmlстатьи + рубрики + авторы этого домена, lastmod.
RSS/blog/rss.xmlпоследние 20 — доп. канал быстрой индексации.
robots.txt/robots.txtразрешает всё + ссылка на sitemap. На публичных доменах не должно быть следов стенда: ни X-Robots-Tag: noindex, ни basic auth.

18 · TR

Свой счётчик

Скрипт < 2 КБ на страницах статей. Анонимный: случайный session_id на вкладку, без кук идентификации и PII. Публичная ручка без авторизации; боты отсекаются по User-Agent и отсутствию взаимодействий. Зачем при Метрике: мгновенные цифры в админке, независимость, вечное хранение агрегатов.

СобытиеКогдаПолезная нагрузка
viewоткрытие статьикласс источника: yandex / google / другой поиск / соцсеть / прямой / внутренний (по referer, URL не хранится)
scroll25 / 50 / 75 / 90%порог
read90% скролла и ≥ 45 с«дочитал» — главная метрика качества
timeуход со страницыактивные секунды
cta_clickклик CTAid блока, назначение (стор/веб)
feed_view / feed_item_clickлента на экране / клик карточкиid блока; id и позиция карточки

Сырые BlogHit — 180 дней; ночная свёртка в ArticleMetricDaily (source=own) — вечно. «Дочитал», «клик CTA», «клик ленты» дублируются в Метрику как цели (сегменты + Вебвизор по дочитавшим).

19 · AN

Аналитика (этап 2)

Словарь метрик — единственные определения, всюду одинаковые

МетрикаОпределениеИсточник
Просмотрысобытия viewсчётчик
Из поискадоля view с источником yandex/googleсчётчик
Дочитываемостьread / viewсчётчик
Время на статьемедиана активных секундсчётчик (сверка — Метрика)
Показы / клики / CTR выдачипоказы в результатах поиска и кликиВебмастер + GSC, раздельно
Позициясредняя по запросам за период, отдельно Я и GВебмастер + GSC
Конверсия(cta_click + feed_item_click) / view — главная метрика проектасчётчик
Поведение-деталиглубина, отказы, карта кликов, записи сессийМетрика (переход по ссылке с фильтром статьи)

Внешние API опрашиваются ночью за вчера → ArticleMetricDaily. Вкладка открывается мгновенно из нашей базы; у внешних данных подпись «данные за <дата>». История не теряется (GSC сам хранит лишь 16 мес).

Сводный дашборд (период 7 / 30 / 90 дней)

Тайлы: конверсии из статей (главная, с динамикой) · визиты из поиска · опубликовано статей · средняя дочитываемость · средний SEO-балл. Ниже: топ-5 статей по конверсиям и топ-10 запросов (Я+G).

Список статей

Столбцы: статья · продукт · опубликована · просмотры (спарклайн) · % из поиска · дочитываемость · позиция Я/G · конверсия. Сортировка по всем; фильтры: продукт, автор, рубрика, период.

Карточка статьи

  1. Шапка: обложка, H1, «открыть на сайте» / «в редактор», балл.
  2. Воронка: показы → клики (CTR) → просмотры → дочитали → конверсии.
  3. График просмотров и кликов из поиска с отметками публикаций изменений (S3).
  4. Запросы: таблица (запрос · показы · клики · CTR · позиция · динамика), вкладки Яндекс/Google; подсказка «позиция 5–15 — близко к топу, усильте в тексте».
  5. Источники: поиск (Я/G) / соцсети / прямые / внутренние.
  6. Поведение: пороги дочитывания, медианное время; кнопки «Карта кликов» и «Записи сессий (Вебвизор)» — в Метрику с фильтром по адресу.
  7. CTA и лента: клики по каждой кнопке; CTR ленты, топ-5 карточек.

20 · KB

База знаний и Авторы

База знаний: список документов (заголовок, продукт, активен, обновлён) + markdown-редактор. Стартовый набор: «Продукт "По душе"» · «Продукт "По любви"» · «Аудитория» · «Тон и стиль» (пишем так / не так) · «Факты и цифры» (с датами) · «Запретные темы» · «Стиль иллюстраций». Деактивация выводит из контекста ИИ немедленно. Индикатор суммарного объёма активных документов; при превышении лимита — предупреждение, какие ужать.

Авторы: имя, slug, фото (квадрат ≥ 400 px), био ≤ 600, регалии, активен. Используются в выборе автора, блоке автора, странице автора, разметке Article. Деактивированный скрыт из выбора; его статьи и страница работают (EC-13). Удаление запрещено.

21 · AC

Интеграции · RBAC · аудит

СервисЧто берём / шлёмОграниченияЧастота
OpenRouterтексты (2 модели) + картинки; prompt cachingмесячный бюджет; учёт по статьямпо запросу
Вордстат APItopRequests, dynamics, regions~1000/сутки, OAuthпо запросу + кеш 7 дн
МетрикаReporting API; Management API (автосоздание целей); ссылки в Вебвизор~5000/сутки; счётчик на доменночь, за вчера
Вебмастермониторинг запросов; IndexNow; переобходсайт на домен; подтверждение правночь; IndexNow — при публикации
GSCsearchanalytics.queryресурс на домен; задержка ~2 дняночь
S3 (существующий)обложки, картинки, фото авторов; WebP-ресайзыфайл ≤ 10 МБпри загрузке

22 · EC

Граничные случаи и тексты ошибок

IDСитуацияПоведение системыЧто видит менеджер
EC-1OpenRouter недоступен / таймаутредактор полностью работает; ИИ-кнопки неактивны; начатая генерация сохраняет готовые секции«ИИ-помощник временно недоступен. Всё остальное работает. Повторить»
EC-2квота Вордстата исчерпанаотдаём кеш с датой снятия; живые запросы — завтра«Показаны данные от 21 августа — лимит подбора на сегодня исчерпан»
EC-3IndexNow-пинг упалпубликация не блокируется; ретрай фоном до 24 чничего (журнал — в аудите)
EC-4событие из карточки ушло в архивкарточка не рендерится на сайтев редакторе карточка помечена «событие прошло — замените»
EC-5лента пуста по фильтрублок не рендерится целикомв редакторе предупреждение «сейчас лента пуста — расширьте фильтр»
EC-6картинка > 10 МБ или не картинкаотказ загрузки«Файл больше 10 МБ. Сожмите или выберите другой»
EC-7slug занятсуффикс -2«Такой адрес занят статьёй "…" — сохранили как …-2»
EC-8обрыв связи при набореправки копятся в браузере; отправка при восстановлении; конфликт версий — диалог сравненияиндикатор «Нет связи — правки сохраняются локально»
EC-9двое редактируют (ED-3)мягкая блокировка: у второго read-only + «Всё равно редактировать» (перехват); heartbeat 30 с, молчание 2 мин снимает блок«Сейчас редактирует Марина» / у первого: «Редактирование перехватил Олег — скопировать несохранённые правки»
EC-10публикация с баллом < 50подтверждение с перечнем главных проблем«Балл 42. Главное: title длиннее нормы, нет внутренних ссылок. Опубликовать всё равно?»
EC-11смена slug опубликованнойвечный 301 со старого адреса«Адрес изменится. Старый будет перенаправлять автоматически. Продолжить?»
EC-12смена продукта после публикациизапрещена (статья «переехала» бы между доменами)поле неактивно: «Продукт нельзя менять после публикации — создайте копию»
EC-13автор деактивированего статьи и страница работают; выбрать его для новых нельзяв списке авторов помечен «неактивен»
EC-14время расписания в прошломотказ сохранения расписания«Выберите время в будущем»
EC-15Метрика/Вебмастер/GSC не ответили ночьюпоказываются последние собранные данные; ретрай следующей ночьюв аналитике подпись «данные Метрики за 25 августа»
EC-16бюджет ИИ исчерпангенерация выключена; чат/правки на быстрой модели до 120%«Месячный бюджет ИИ израсходован. Генерация включится 1 сентября. Админ может поднять лимит»

23 · NF

Нефункциональные требования

IDОбластьТребование (проверяемое)
NF-1Скорость блогаCore Web Vitals статей в «хорошо» на 75-м перцентиле: LCP < 2,5 с · INP < 200 мс · CLS < 0,1. Обложка WebP/AVIF + fetchpriority; размеры у всех картинок и лент; JS на странице — только счётчик, Метрика, гидрация ленты.
NF-2Скорость админкиСписок статей ≤ 1 с при 1000 статей; пересчёт балла в редакторе ≤ 300 мс; автосохранение не блокирует набор.
NF-3НадёжностьПубликация атомарна: либо все шаги 2–5 конвейера §16, либо статус не меняется и менеджеру показана ошибка. Недоступность любого внешнего API не ломает ни редактор, ни публикацию (EC-1, EC-3, EC-15).
NF-4СохранностьПотеря текста недопустима: автосохранение ≤ 5 с, локальный буфер при обрыве (EC-8), версии при публикации, мягкая блокировка (EC-9).
NF-5БезопасностьКлючи интеграций — только на сервере. Публичная ручка счётчика — троттлинг по IP и объёму. Счётчик не собирает PII (NF-6). Админ-API — существующий fail-closed RBAC.
NF-6ПриватностьНа публичных страницах нет данных реальных пользователей (правило §15). Счётчик — анонимный, referer хранится только классом источника.
NF-7СовместимостьАдминка: последние версии Chrome, Firefox, Safari, Edge. Блог: те же + мобильные браузеры (mobile-first — обязательное условие индексации).
NF-8ЛокализацияТолько русский; модель не блокирует добавление языков позже (§27).

24

Критерии приёмки и готовность

Ключевые критерии (формат «дано → когда → тогда»)

A-1 · Публикация
Дано: черновик с H1, автором, обложкой и снятой вычиткой. Когда: менеджер жмёт «Опубликовать». Тогда: страница открывается на домене продукта за ≤ 60 с, содержит все теги §11 (проверка валидаторами Google Rich Results и Вебмастера), присутствует в sitemap, IndexNow вернул успех (или встал в ретрай), в списке статус «Опубликована», создана версия.
A-2 · Вычитка ИИ
Дано: статья, где ≥ 50% текста сгенерировал ИИ. Когда: менеджер пытается опубликовать без «Вычитано». Тогда: публикация недоступна, показано объяснение; после «Вычитано» (записано в аудит) публикация доступна.
A-3 · Балл
Дано: статья, нарушающая проверку №1 (title 75 знаков). Когда: менеджер укорачивает title до 58 знаков с ключом в начале. Тогда: пункт чек-листа становится зелёным и балл растёт на его вес без перезагрузки страницы, ≤ 1 с.
A-4 · Блокировка
Дано: Марина редактирует статью. Когда: Олег открывает её же. Тогда: у Олега read-only с плашкой; после «Всё равно редактировать» блокировка у Олега, Марина предупреждена и может скопировать несохранённое; правки Марины не записываются молча поверх.
A-5 · Лента
Дано: опубликованная статья с лентой «Москва, 14 дней, 6 карточек». Когда: одно из событий заканчивается. Тогда: при следующем обновлении кеша страницы (≤ 10 мин) карточка исчезает, новая занимает место; клик по карточке фиксирует feed_item_click с id и позицией.
A-6 · Переезд адреса
Дано: опубликованная статья со slug A. Когда: менеджер меняет slug на B и публикует. Тогда: адрес A вечно отдаёт 301 на B; B — в sitemap; A — нет.
A-7 · Снятие
Дано: опубликованная статья. Когда: «Снять с публикации». Тогда: страница отдаёт 410, исчезает из sitemap, метрики и версии сохранены, «Вернуть» публикует обратно.
A-8 · Счётчик
Дано: читатель открыл статью из Яндекса, доскроллил до конца за 3 минуты, кликнул CTA. Тогда: записаны view (источник yandex), scroll 25–90, read, time, cta_click; в админке цифры видны ≤ 1 мин; в Метрике засчитаны цели.

Готовность этапов (Definition of Done)

25

Этапы запуска

0

Фундамент инфраструктура · параллельно этапу 1

Идёт параллельно разработке, а не перед ней: фоновый воркер, OpenRouter и Вордстат нужны рано; домен, Метрика + Вебмастер + GSC + IndexNow — только к го-лайву (последний шаг этапа 1). Разработка и приёмка — на закрытом стенде.

→ К моменту готовности кода — публичный адрес и все ключи; ничто не ждёт друг друга.

1

Писать и публиковать ядро

MUST: список и редактор (§9–10), метаданные (§11), балл (§12), Вордстат (§13), ИИ-генерация и чат (§14), лента событий (§15), конвейер публикации и версии (§16), блог (§17), счётчик пишет с первого дня (§18), база знаний и авторы (§20), RBAC (§21). SHOULD (режутся первыми при сдвиге сроков): правка выделенного, расписание, ИИ-картинки. COULD: лента анкет.

→ Первая статья опубликована; данные копятся с первого дня.

2

Видеть результат аналитика

Ночные сборщики трёх API; вкладка «Аналитика» целиком (§19); подсказки «близко к топу».

→ По каждой статье видно, приносит ли она пользователей и что усилить.

26

Открытые вопросы · риски

IDВопросВладелецБлокирует
O-1Имя и покупка домена событийкомандатолько го-лайв (открытие индексации и кабинеты); разработке не мешает
O-2Домен дейтинга: plbvi.ru или новыйкомандапубликацию dating-статей (писать можно сразу)
O-3Целевая цифра главной метрики (конверсий/мес к 6-му месяцу)владелец продуктаничего; нужна для оценки успеха
O-4Масштаб: авторов и статей в месяц (сейчас — допущение Д-1)владелец продуктабюджет ИИ; при > 40/мес — пересмотр защиты R-1
O-5Подтвердить приоритеты SHOULD/COULD (§25): расписание, ИИ-картинки, правка выделенного, лента анкетвладелец продуктапорядок работ этапа 1
O-6Аккаунт OpenRouter и способ оплатыкомандаИИ-функции
O-7Юр. оформление согласий витринных анкеткоманда + Adminленту анкет (FD-2)

Все вопросы должны быть закрыты (и решения внесены в эту спеку) до начала соответствующих работ; O-1, O-6 — до старта этапа 0/1.

R-1 · Фильтры за ИИ-контентМассовый неотредактированный ИИ-текст режут оба поисковика (Яндекс: −30–50% индекса качества за 2–4 месяца). Защита: обязательное «Вычитано», авторы, живые данные в статьях, разумный темп (Д-1).
R-2 · НакруткаНакрутка поведенческих факторов — главный источник банов Яндекса (фильтр 8–12 мес). Не делаем ни в каком виде; работаем на честный CTR и удержание.
R-3 · Инерция индексацииПервые 2–3 месяца трафика почти не будет — это норма для нового домена. Не принимать решений о закрытии проекта раньше 4-го месяца (метрики §1 считать с 3-го).

27

Что сознательно не делаем (non-goals)

28

Заметки для разработки

Точки в существующем коде

API админки (все — в ENDPOINT_RULES, запись — seo.write)

GET/POST   /seo/articles                     список / создание
GET/PATCH  /seo/articles/{id}                чтение / автосохранение
POST       /seo/articles/{id}/publish | unpublish | schedule | review-done
POST       /seo/articles/{id}/lock | unlock  мягкая блокировка (heartbeat)
GET        /seo/articles/{id}/versions       POST …/versions/{n}/restore
POST       /seo/articles/{id}/score          серверный пересчёт
GET        /seo/keywords?q=®ion=          Вордстат (кеш)
POST       /seo/ai/chat | generate | edit | image     (SSE-стриминг)
GET/POST/PATCH /seo/authors, /seo/kb, /seo/showcase-profiles
GET        /seo/analytics/summary | articles | articles/{id}

Публичные ручки (домены блога, без авторизации)

GET  /api/v1/blog/articles?page=&tag=     список (SSR)
GET  /api/v1/blog/articles/{slug}         статья (404 / 410 / 301 по slug_history)
GET  /api/v1/blog/feed/{block_id}         данные ленты
POST /api/v1/blog/track                   счётчик (батч, троттлинг по IP)

Переменные окружения

OPENROUTER_API_KEY            SEO_AI_MODEL_WRITER / _FAST / _IMAGE
SEO_AI_MONTHLY_BUDGET_RUB     WORDSTAT_OAUTH_TOKEN
METRIKA_TOKEN                 METRIKA_COUNTER_EVENTS / _DATING
WEBMASTER_TOKEN               GSC_CREDENTIALS_JSON
INDEXNOW_KEY_EVENTS / _DATING BLOG_DOMAIN_EVENTS / _DATING
SITE_PRODUCT                  (events | dating — на каждом деплое витрины)

29

История версий документа

ВерсияДатаЧто изменилось
v127.08.2026Первый гриль (15 решений), базовая спецификация: 4 вкладки, ИИ, публикация, аналитика, этапы.
v227.08.2026Мультидоменная публикация; блок «Лента»; анализ конкурентов исключён; детализация: модель данных, правила title/description, 20 проверок балла, конвейер публикации, API.
v327.08.2026Реструктуризация по канону функциональных спецификаций (гриль-2 + исследование best practices): проблема и метрики успеха (главная — конверсии из статей), допущения, персоны, сценарии S1–S5, реестр нумерованных требований с приоритетами MUST/SHOULD/COULD, мягкая блокировка редактирования, таблица граничных случаев EC-1…EC-16 с текстами ошибок, НФТ NF-1…NF-8, критерии приёмки A-1…A-8 и DoD этапов, открытые вопросы с владельцами, статус документа.
v3.128.08.2026Правка арифметики §12: веса двадцати проверок давали в сумме 97 при заявленных «Итого 100». Три очка добавлены обложке (4→5: она же og:image и блокер публикации), иллюстрированности (3→4) и внешним источникам (3→4) — самым лёгким весам относительно их влияния. Условия проверок не менялись.
v3.228.08.2026Добавлен §30 «Состояние реализации»: что из спеки уже живёт в коде (§8, §12, §21 целиком; §9, §10 — на уровне API), где реализация сознательно отошла от буквы и почему, что нужно пересобрать на стенде. Требования не менялись.

30

Состояние реализации

Зачем этот разделСпецификация писалась до кода, и через месяц по ней будет непонятно, что уже живёт, а что ещё нет. Здесь — состояние на 28.08.2026, ветка feature/seo-w1-backend (три коммита, не запушены). Контракт админ-API как он построен — backend/docs/SEO_ADMIN_API.md; решения, которые не надо «чинить» обратно, — docs/internal/14-seo-section.md.

По разделам спецификации

РазделСостояниеЧто именно
§8 Модель данныхсделаноДесять таблиц, две миграции. У статьи две копии: колонки — черновик, published — снимок показываемых полей (иначе правка опубликованной уезжала на сайт сама).
§9 Список статейAPI готовСемь фильтров, сортировки, пагинация, дублирование, удаление только черновика. Экрана нет — это S-2.
§10 РедакторAPI готовАвтосейв по полям, валидатор блоков (11 типов, санитайзер инлайна), мягкая блокировка с перехватом, загрузка картинок. Самого редактора нет — S-3/S-4.
§11 МетаданныечастичноПоля, правила адреса (транслит, стоп-слова, суффикс, вечные 301) и пиксельная ширина заголовка есть. Разметка страницы (og:*, JSON-LD) — за витриной, F-2.
§12 SEO-баллсделаноВсе двадцать проверок, чек-лист в ответе автосейва, явный пересчёт, пороги для индикаторов панели. Статья 3127 слов — 9 мс при бюджете 300.
§13 ВордстатнетЗапросы прикрепляются руками в keywords; проверки №1, 11, 12 их уже читают. Клиент и кеш — B-5.
§14 ИИ-помощникнетB-6. Таблицы под чат и расход заведены.
§15 ЛентачастичноБлок есть в схеме и валидаторе, считается визуальным и CTA-блоком. Наполнение и рендер — B-8/F-3.
§16 ПубликациянетB-7. Снимок публикуемых полей уже собирается моделью, конвейеру остаётся его положить.
§17 Публичный блогнетB-8 + F-1…F-4.
§18 СчётчикнетТаблицы есть, ручка и свёртка — B-9.
§19 АналитиканетЭтап 2, после го-лайва.
§20 База знаний, авторычастичноТаблицы есть, автор выбирается в статье и проверяется баллом. CRUD справочников — B-10.
§21 RBAC и аудитсделаноПродукт seo, четыре секции, действие seo.write; каждая ручка в ENDPOINT_RULES, иначе 403. Автосейв и биение замка в журнал не пишут — иначе тысячи строк в сутки на автора.
§22 Граничные случаичастичноЗакрыты EC-6, EC-7, EC-9, EC-11, EC-12, EC-13. Остальные ждут своих задач (ИИ, Вордстат, расписание, аналитика).

Что уже работает целиком

Менеджер заводит статью и получает адрес из заголовка → набирает текст блоками, статья сохраняется сама, второй редактор видит плашку блокировки → загружает обложку, сервер сжимает её в WebP и сам читает размеры из файла → балл и чек-лист обновляются тем же ответом, что и сохранение. Проверено сквозным прогоном по HTTP; на стенде раздел ещё не разворачивался.

Образ пересобратьПоявились зависимости: pillow, pymorphy3 со словарём и razdel. Без морфологии балл продолжает считаться, но по словоформам, а не по леммам — то есть занижен; об этом теперь предупреждает системная проверка Django на старте.

Где реализация сознательно отошла от буквы спеки

Каждое отклонение помечено Δ в SEO_ADMIN_API.md и объяснено там же. Коротко: