Перейти к содержимому

Чек-лист страницы — с учётом ключевого слова, pass/warn/fail

Чек-лист страницы — привычный пользователю RankMath или Yoast цикл редакторской работы: выберите фокусное ключевое слово и получите список цветовых проверок «оптимизирована ли страница под него?». Проверяются ключевое слово в заголовке, URL, первом абзаце и метаописании, а также длина, изображения, внутренние ссылки и читаемость.

Он выполняется внутри запроса, без очереди и сети, на основе модели, резолвера и текста страницы, и намеренно не выдаёт число.

Чек-лист ≠ оценка

Чек-лист содержит только pass / warn / fail и полностью отделён от SEO-оценки Pro. У него нет общих кодов с методикой оценки, и он никогда не меняет её: редакторские подсказки отделены от числовой методики. В частности, плотность ключевых слов и читаемость — рекомендации (ниже).

Что проверяется

ПроверкаГруппаЧто ищет
keyword_in_titlekeywordФокусное ключевое слово в SEO-заголовке.
keyword_in_descriptionkeywordФокусное ключевое слово в метаописании.
keyword_in_urlkeywordФокусное ключевое слово в слаге URL.
keyword_in_first_paragraphkeywordФокусное ключевое слово в первом абзаце.
keyword_densitykeywordРекомендация. Естественная плотность употребления (без целевого значения, см. ниже).
title_lengthmetaЗаголовок в том же диапазоне, что у редактора и сканирования: 30–60 для латиницы, около 15–30 для CJK, по политике длины ядра (Pro 2.33).
description_lengthmetaОписание в том же диапазоне: 70–160 для латиницы, около 35–80 для CJK.
content_lengthcontentДостаточный объём основного текста (настраиваемые диапазоны числа слов).
readabilitycontentРекомендация. Приблизительная читаемость по выбранной формуле (десять языков), резервному LIX или явно обозначенной эвристике без оценки для японского, китайского и корейского.
has_imagemediaВ контенте есть хотя бы одно изображение.
internal_linkslinksКонтент ссылается на связанные внутренние страницы.

Проверки ключевого слова пропускаются (не проходят и не проваливаются), если фокусное слово не задано; чек-лист просит добавить его. Используйте поле фокусного ключевого слова или saveSEO(['focus_keywords' => …]).

Сопоставление ключевых слов

Ключевое слово и текст сравниваются после свёртки регистра и стемминга: «espresso grinder» совпадает с «espresso grinders», а с учётом локали анализа турецкое «İstanbul» — с «istanbul», греческое «ΟΔΟΣ» — с «οδος», немецкое «Straße» — с «STRASSE» (CaseFolder ядра). Передайте локаль анализа: SeoPro::checklistFor($post, 'it') или --locale=it.

С Pro 2.36.1 ключевые слова, синонимы и текст полей перед стеммингом используют один токенизатор. Совпадения требуют последовательных целых токенов: cat не совпадает с education, а японские фразы используют те же границы слов ICU, что и основной текст. Апострофы и дефисы разделяют токены, поэтому meta-tag совпадает с meta tag, а прямые и типографские апострофы ведут себя одинаково. Комбинируемые знаки остаются при своих буквах. Свёртка регистра сохраняет диакритику; стеммер конкретного языка может выполнять дополнительные сокращения.

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

С Pro 2.37 стемминг использует встроенное подмножество Snowball 3.1.1. Дополнительный пакет Composer не нужен, во время выполнения ничего не скачивается. PHP 8.2 остаётся поддерживаемым.

ДвижокКогда используетсяЯзыки
snowballПо умолчанию; существующие настройки auto выбирают тот же встроенный движокen, it, de, fr, es, pt, nl, ru, tr, el, pl, cs
builtinЯвный seo-pro.checklist.analysis.stemmer = builtinТолько английский, со старым облегчённым стеммером словоизменений; остальные языки сопоставляются без изменения основы
identityНеподдерживаемый язык или явный режим noneУкраинский, японский, китайский, корейский, тайский и другие языки вне встроенного подмножества

Обе стороны сравнения используют один движок. Стемминг — алгоритм сокращения суффиксов, а не словарь синонимов и не гарантия языковой эквивалентности. Например, греческий алгоритм может сопоставить формы с ударением и без него, которые при сопоставлении без стемминга различаются. Границы целых токенов всё ещё не дают cat совпасть с education.

Обновление с Pro 2.36

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

Задайте SEO_PRO_CHECKLIST_STEMMER=builtin для прежнего резервного алгоритма только для английского или none для сопоставления со свёрткой регистра без изменения основы во всех языках. После изменения пересоберите кеш конфигурации. Эти настройки не воспроизводят старые многоязычные алгоритмы необязательной обёртки; для точного сохранения тех результатов нужен предыдущий выпуск Pro. Сохранённые SEO-метаданные не перезаписываются.

Встроенный адаптер проходит 600 395 закреплённых официальных пар словарь/результат на PHP 8.2, 8.3 и 8.4. Это подтверждает соответствие алгоритму, а не редакторское одобрение носителем языка. Хеши источников, адаптация синтаксиса для PHP 8.2 без изменения алгоритма и лицензии исходных проектов входят в пакет. См. THIRD-PARTY-NOTICES.md в исходном дистрибутиве.

Разделение на слова

Подсчёту слов, плотности ключевого слова и статистике читаемости нужны слова. Для письменностей с пробелами регулярное выражение использует стабильные границы буквенно-цифровых токенов. Китайскому, японскому и тайскому нужна словарная сегментация: регулярное выражение может принять абзац за одно «слово». При загруженном ext-intl токенизатор передаёт такие фрагменты словарному итератору границ ICU (IntlBreakIterator::createWordInstance), который делит 東京タワーは東京のランドマークです на слова. Если ICU отсутствует, отключён или не инициализируется, Pro пропускает затронутые проверки длины контента, читаемости и ключевых слов с сообщением об установке/настройке. Ненадёжный подсчёт не превращается в провал. Независимые проверки, включая длину заголовка и сопоставление письменностей с пробелами, продолжаются. seo-pro.checklist.analysis.segmenter = regex принудительно задаёт то же состояние недоступности для текста, которому нужна словарная сегментация.

Блок analysis содержит word_count_status (available или unavailable) и segmentation_reason (null, missing_intl, disabled или initialization_failed). Низкоуровневый токенизатор сохраняет резервные токены для совместимости; прежде чем считать их словами, проверьте это состояние.

Сканирование отрендеренной страницы выдаёт не влияющее на оценку замечание word_segmentation_unavailable вместо заключения о недостаточном контенте. Ранее подтверждённая проблема недостаточного контента остаётся открытой до повторной проверки. Такое неполное сканирование не обновляет оценку страницы: прежняя сохраняет исходный scored_at, а первое сканирование не даёт оценки, пока сегментация не заработает. Установите PHP ext-intl, включите сегментатор auto и повторите сканирование, чтобы возобновить проверки.

Какие движки анализировали страницу

Каждый чек-лист содержит блок analysis: преобладающая письменность текста, токенизатор (intl / regex), стеммер (snowball / builtin / identity) и метод читаемости (formula / heuristic / lix). Он доступен в toArray() / --json, в нижней строке модального окна Filament и последней строке seo-pro:checklist:

Analysis: locale ja · script cjk · tokenizer intl (ICU dictionary) · stemmer identity · readability heuristic

Эта строка показывает фактически использованный движок, включая сегментацию регулярными выражениями без ext-intl и сопоставление без изменения основы при выключенном стемминге.

Плотность ключевого слова — рекомендация

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

Читаемость — рекомендация

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

ЛокальФормулаИсточник
Английский (en)Flesch Reading EaseFlesch 1948
Итальянский (it)Индекс GulpeaseLucisano & Piemontese 1988
Испанский (es)Fernández-HuertaFernández Huerta 1959
Французский (fr)Kandel-MolesKandel & Moles 1958
Немецкий (de)erste Wiener SachtextformelBamberger & Vanecek 1984
Португальский (pt, pt_BR)Flesch, адаптированный для бразильского португальскогоMartins et al. 1996
Нидерландский (nl)Flesch-DoumaDouma 1960
Русский (ru)Адаптация формулы Флеша ОборневойОборнева 2006
Турецкий (tr)AteşmanAteşman 1997
Польский (pl)Pisarek (нормализованный индекс лет обучения)Pisarek 1969
Японский, китайский, корейский (ja, zh, ko)Эвристика без оценки, см. ниже
Греческий, украинский, чешский (el, uk, cs)LIX — резервный вариант, поскольку отдельная формула здесь не реализована; для этих языков не откалиброванBjörnsson 1968
ОстальныеLIX (Läsbarhetsindex) — неоткалиброванный резервный вариантBjörnsson 1968

Отображаемая оценка 0–100 (выше = легче) — соглашение пакета. Результаты семейства Flesch и Gulpease ограничиваются диапазоном; Wiener, Pisarek и LIX переводятся на эту шкалу. Одинаковые оценки разных языков не означают одинаковой сложности чтения. Формулы коэффициентов взяты из опубликованных работ; оценки токенов, предложений и слогов Rankbeam не проверены как целостный измерительный инструмент. Они не прогнозируют понимание текста или позиции в поиске.

С Pro 2.37.1 при подсчёте слогов турецкого и русского соседние гласные учитываются отдельно (saat: 2; поэт: 2). У остальных оценщиков слогов остаются ограничения: группы гласных не учитывают некоторые зияния и непроизносимые гласные. Для английского есть небольшой список исключений, но это не словарь произношения. Например, испанское país и французское monde могут считаться неверно. Незнакомые слова и имена собственные проверяйте вручную.

Статистика текста и ограничения API

Блочные HTML-теги и элементы br разделяют текст; встроенное выделение остаётся частью слова. Переносы исходника внутри обычного HTML сворачиваются в пробелы, а простой текст и pre сохраняют границы строк. Содержимое script, style и noscript исключается. Извлечение не оценивает видимость по CSS или отрендеренную страницу. Сущности декодируются один раз. Для статистики формул последовательности букв/цифр считаются словами, одна пунктуация — нет. Дефисы и апострофы разделяют слова. Цифры считаются токенами без предполагаемых слогов. Буквы считаются по исходному тексту, без изменения длины из-за стемминга или свёртки немецкого ßss.

Приблизительные предложения разделяются конечными . ! ? 。 ! ? и границами блоков/строк, включают последний фрагмент без конечного знака и защищают десятичные числа и небольшой список распространённых сокращений (Dr., Prof., e.g. и похожие английские формы). Поэтому заголовки и пункты списков могут считаться предложениями. Особая осторожность нужна с другими сокращениями, цитатами, числами, смешанными письменностями и текстом с малым количеством пунктуации. Выбранная локаль определяет метод, а не распознаёт язык каждого предложения.

toArray() прямого калькулятора добавляет блок assessment:

json
{
  "status": "computed",
  "method": "formula",
  "formula": "flesch_reading_ease",
  "inputs_estimated": true,
  "score_scale": "normalized_0_100",
  "grade_level_estimated": true
}

method различает formula, lix, heuristic и unavailable (unspecified для созданных вручную результатов без метаданных формулы). Пустой ввод или одна пунктуация имеют insufficient, а isValid() равно false; прежнее score: 0 — маркер недоступности, а не оценка сложности. Существующие английские/итальянские обозначения школьных уровней приблизительны; остальные языки и результаты эвристик/LIX больше их не получают. calculateFleschKincaid() сохраняет публичное имя метода ради совместимости, но вычисляет Flesch Reading Ease, а не школьный уровень Flesch-Kincaid.

Тесты формул фиксируют независимо подсчитанные входные величины и ожидаемую арифметику для всех десяти именованных формул и LIX. Они проверяют вычисления, но не заменяют оценку текста носителем языка. Читаемость остаётся отдельной от SEO-оценки Pro.

Японский, китайский и корейский: явно обозначенная эвристика, никогда не число

Для этих языков Rankbeam реализует метод без числовой оценки. Калькулятор возвращает уровень по собственным приблизительным правилам пакета: средняя длина предложения в символах (ja ≤ 40/60/80, zh ≤ 30/45/60) или словах (ko ≤ 12/18/25), а для японского ещё доля кандзи (выше примерно 45 % повышает категорию сложности пакета на один шаг). Результат помечен heuristic: true и имеет null вместо оценки. Сообщение чек-листа указывает «эвристика», и проверка остаётся рекомендательной для этих языков независимо от readability.advisory: приблизительное правило информирует, но не определяет общий статус чек-листа. Подсчёт слов для ja/zh требует работающей сегментации ICU; при её недоступности проверки пропускаются.

Как и плотность ключевых слов, читаемость по умолчанию рекомендательная: информирует автора, но не определяет общий статус страницы — такое же разделение Yoast проводит между анализами читаемости и SEO. Ниже минимального числа слов проверка пропускается: недостаточный объём — задача content_length, а не читаемости. Сделайте её обязательной, если трудный текст должен приводить к провалу:

php
// config/seo-pro.php → 'checklist'
'readability' => [
    'min_words' => 50,     // below this → skipped (too little copy to judge)
    'advisory'  => true,   // false → a 'difficult' page fails the checklist
],

Чтение чек-листа

Без интерфейса

Pro 2.36 читает итоговые метаданные, getContentForSEO() и фокусные ключевые слова в запрошенной локали контента, а подписи чек-листа остаются на языке оператора. Без явной локали учитывается значение seoData() по умолчанию модели перевода. Действие Filament следует языковой вкладке поля или переключателю локали страницы.

php
use Rankbeam\Seo\Pro\Facades\SeoPro;

$checklist = SeoPro::checklistFor($post);          // or ($post, 'it') for a locale

$checklist->status();        // 'pass' | 'warn' | 'fail' (advisory + skips ignored)
$checklist->summary();       // ['passed' => 6, 'warnings' => 2, 'failures' => 1, 'skipped' => 0]
$checklist->failures();      // CheckResult[]
$checklist->recommendations(); // failures first, then warnings
$checklist->toArray();       // JSON-ready payload (no score key)

Каждый CheckResult содержит id, group, label, status, message, необязательный recommendation и флаг advisory.

Команда

bash
php artisan seo-pro:checklist "App\Models\Post" 42
php artisan seo-pro:checklist "App\Models\Post" 42 --json     # machine-readable
php artisan seo-pro:checklist "App\Models\Post" 42 --strict   # non-zero exit on any failure (CI)
php artisan seo-pro:checklist "App\Models\Post" 42 --locale=it

В редакторе (Filament, необязательно)

При установленном rankbeam/laravel-seo-filament у поля фокусного ключевого слова появляется действие «Чек-лист страницы». Оно открывает модальное окно с теми же проверками pass/warn/fail для сохранённого контента записи. Пакет Filament никогда не зависит от Pro: действие подключается через тот же односторонний механизм расширения, что и предложения ИИ, поэтому установки без интерфейса не затрагиваются.

Конфигурация

php
// config/seo-pro.php → 'checklist'
'checklist' => [
    'enabled' => true,             // shows the Filament action; headless API always works

    'content' => [
        'min_words' => 200,        // below this → fail (too thin)
        'good_words' => 600,       // below this → warn; at/above → pass
    ],

    'internal_links' => [
        'min' => 2,                // internal links needed to pass
    ],

    'readability' => [
        'min_words' => 50,         // below this → skipped
        'advisory' => true,        // false → a hard-to-read page fails the checklist
    ],

    // The check registry. Each entry implements
    // Rankbeam\Seo\Pro\OnPage\Rules\Check and is resolved from the container
    // (custom checks get the Stemmer/StopWords toolkit injected). Remove a
    // line to drop a check, reorder to reorder, or append your own.
    'rules' => [
        \Rankbeam\Seo\Pro\OnPage\Rules\Keyword\KeywordInTitleCheck::class,
        // …
    ],
],

Собственная проверка

php
use Rankbeam\Seo\Pro\OnPage\ChecklistContext;
use Rankbeam\Seo\Pro\OnPage\CheckResult;
use Rankbeam\Seo\Pro\OnPage\Rules\AbstractCheck;

class KeywordInSubheadingCheck extends AbstractCheck
{
    public function id(): string { return 'keyword_in_subheading'; }
    public function group(): string { return 'keyword'; }
    public function label(): string { return 'Focus keyword in a subheading'; }

    public function run(ChecklistContext $context): CheckResult
    {
        $keyword = $context->primaryKeyword();

        if ($keyword === null) {
            return $this->skipNoKeyword();
        }

        return str_contains($context->htmlContent, '<h2')
            ? $this->pass('Found a subheading.')
            : $this->warn('No subheading found.', 'Add an H2 that includes the keyword.');
    }
}

Зарегистрируйте её, добавив класс в seo-pro.checklist.rules. Проверка не должна повторно использовать идентификатор кода проблемы сканирования: у чек-листа отдельное пространство имён, не влияющее на оценку.

Как читается контент

SeoPro::checklistFor($model) анализирует:

  • Заголовок / описаниеитоговые значения, те же, что измеряют счётчики редактора и сканирование, поэтому чек-лист им не противоречит.
  • Контент$model->getContentForSEO() (аксессор HasSEO ядра; по умолчанию content / body / text). Переопределите его в модели, чтобы указать настоящий основной текст.
  • URL$model->getUrlForSEO().
  • Фокусные ключевые слова — сохранённые seo_meta.focus_keywords.

Это чистый анализ: страницы не загружаются и ничего не записывается.

rankbeam/laravel-seo распространяется под лицензией MIT.