Ir al contenido

Lista de comprobación de la página ​

La lista de comprobación analiza el contenido durante la petición, sin colas ni llamadas de red, a partir del modelo, los metadatos resueltos y el texto de la propia página. Su resultado no es una puntuación numérica.

La lista de comprobación y la puntuación son independientes

La lista solo devuelve correcto / advertencia / fallo y es independiente de la puntuación SEO de Pro. No comparte códigos con sus criterios ni puede modificarla: las indicaciones editoriales quedan separadas de la puntuación. La densidad de palabras clave y la legibilidad, en particular, son orientativas; se explican más abajo.

Qué comprueba ​

ComprobaciónGrupoQué busca
keyword_in_titlekeywordLa palabra clave principal aparece en el título SEO.
keyword_in_descriptionkeywordLa palabra clave principal aparece en la metadescripción.
keyword_in_urlkeywordLa palabra clave principal aparece en el slug de la URL.
keyword_in_first_paragraphkeywordLa palabra clave principal aparece en el primer párrafo.
keyword_densitykeywordOrientativa. Las repeticiones resultan naturales; no hay un porcentaje objetivo.
title_lengthmetaEl título respeta los mismos límites que el editor y el escaneo: 30–60 para texto latino y unos 15–30 para CJK, según la política de longitud del paquete principal (Pro 2.33).
description_lengthmetaLa descripción respeta los mismos límites: 70–160 para texto latino y unos 35–80 para CJK.
content_lengthcontentHay suficiente texto en el cuerpo, según los intervalos de palabras configurados.
readabilitycontentOrientativa. Estima la legibilidad con la fórmula seleccionada para diez idiomas, LIX como alternativa o una heurística identificada y sin puntuación para japonés, chino y coreano.
has_imagemediaEl contenido incluye al menos una imagen.
internal_linkslinksEl contenido enlaza a páginas internas relacionadas.

Las comprobaciones de palabras clave se omiten cuando no hay una palabra clave principal: no devuelven ni un resultado correcto ni un fallo. La lista te pide que añadas una mediante el campo de palabra clave principal o saveSEO(['focus_keywords' => …]).

Coincidencia de palabras clave ​

La palabra clave y el texto se comparan tras normalizar mayúsculas y minúsculas y reducir las palabras a sus raíces. Así, «espresso grinder» coincide con «espresso grinders». Con el idioma de análisis correspondiente, el turco «İstanbul» coincide con «istanbul», el griego «ΟΔΟΣ» con «οδος» y el alemán «Straße» con «STRASSE», mediante CaseFolder del paquete principal. Indica el idioma del análisis con SeoPro::checklistFor($post, 'it') o --locale=it.

Desde Pro 2.36.1, las palabras clave, los sinónimos y los campos de texto utilizan el mismo tokenizador antes de la reducción a raíces. Las coincidencias requieren tokens completos y consecutivos: cat no coincide con education, y las frases japonesas utilizan los mismos límites de palabra de ICU que el cuerpo. Los apóstrofos y guiones separan tokens: meta-tag coincide con meta tag, y los apóstrofos rectos y curvos se tratan igual. Las marcas combinantes permanecen unidas a sus letras. La normalización de mayúsculas conserva los acentos, aunque el algoritmo de raíces de cada idioma puede aplicar reducciones adicionales.

El recuento elige la palabra clave o el sinónimo coincidente más largo en cada posición y cuenta ese tramo una sola vez. Los sinónimos duplicados y las alternativas más cortas que se solapan no aumentan artificialmente la densidad. Por ejemplo, la palabra clave seo, con el sinónimo seo tools, aparece dos veces en seo tools seo. ICU sigue siendo necesario para reconocer límites de palabra mediante diccionario en escrituras sin espacios; la alternativa con expresiones regulares no proporciona esos límites.

Desde Pro 2.37 se incluye un subconjunto de Snowball 3.1.1. No requiere otro paquete de Composer ni descarga nada durante la ejecución. Sigue siendo compatible con PHP 8.2.

MotorCuándo se utilizaIdiomas
snowballPredeterminado; los ajustes auto existentes seleccionan el mismo motor incluidoen, it, de, fr, es, pt, nl, ru, tr, el, pl, cs
builtinConfiguración explícita seo-pro.checklist.analysis.stemmer = builtinSolo inglés, con el anterior algoritmo ligero de flexiones; los demás idiomas usan coincidencia sin reducción
identityIdioma no compatible o modo none explícitoUcraniano, japonés, chino, coreano, tailandés y otros idiomas fuera del subconjunto incluido

Ambos lados de la comparación utilizan el mismo motor. La reducción de raíces es un algoritmo de reducción de sufijos, no un diccionario de sinónimos ni una garantía de equivalencia lingüística. Por ejemplo, el algoritmo griego puede hacer coincidir formas acentuadas y no acentuadas que el modo identity mantiene separadas. Los límites de tokens completos siguen impidiendo que cat coincida con education.

Actualización desde Pro 2.36 ​

La configuración auto existente utiliza ahora los algoritmos incluidos de forma uniforme, esté instalado o no wamania/php-stemmer. Revisa las indicaciones editoriales tras actualizar: los cambios de algoritmo pueden modificar las coincidencias, y el turco, griego, polaco y checo disponen ahora de reducción a raíces. Los algoritmos adicionales de catalán, danés, finés, noruego, rumano y sueco del adaptador opcional quedan fuera de este subconjunto y utilizan ahora identity.

Establece SEO_PRO_CHECKLIST_STEMMER=builtin para recuperar la anterior alternativa solo para inglés, o none para comparar sin reducción a raíces, normalizando mayúsculas en todos los idiomas. Regenera la caché de configuración después del cambio. Estos ajustes no reproducen los algoritmos multilingües del antiguo adaptador opcional; conservar exactamente aquellos resultados requiere mantener la versión anterior de Pro. No se reescriben los metadatos SEO guardados.

El adaptador incluido supera 600.395 pares oficiales de vocabulario y resultado, fijados por versión, en PHP 8.2, 8.3 y 8.4. Esto demuestra conformidad con el algoritmo, no aprobación editorial por hablantes nativos. El paquete incluye los hashes de origen, la adaptación exclusiva de sintaxis para PHP 8.2 y las licencias originales. Consulta THIRD-PARTY-NOTICES.md en la distribución del código fuente.

Segmentación de palabras ​

El recuento, la densidad de palabras clave y las estadísticas de legibilidad necesitan identificar palabras. Para escrituras con espacios, una expresión regular utiliza límites estables de letras y dígitos. El chino, japonés y tailandés necesitan segmentación mediante diccionario: una expresión regular puede interpretar un párrafo entero como una sola «palabra». Cuando está cargada ext-intl, el tokenizador pasa esos fragmentos al iterador de ICU basado en diccionario (IntlBreakIterator::createWordInstance), que divide 東京タワーは東京のランドマークです en palabras. Si ICU falta, está desactivado o no puede inicializarse, Pro omite las comprobaciones afectadas de longitud del contenido, legibilidad y palabras clave, e indica qué instalar o configurar. Un recuento poco fiable no se convierte en un fallo. Las comprobaciones independientes, como la longitud del título o las coincidencias en escrituras con espacios, siguen ejecutándose. seo-pro.checklist.analysis.segmenter = regex fuerza el mismo estado no disponible para textos que requieren diccionario.

El bloque analysis incluye word_count_status (available o unavailable) y segmentation_reason (null, missing_intl, disabled o initialization_failed). El tokenizador de bajo nivel conserva tokens alternativos por compatibilidad; comprueba este estado antes de interpretarlos como palabras.

El escaneo de la página renderizada emite un aviso word_segmentation_unavailable sin puntuación, en lugar de un diagnóstico de contenido escaso. Una incidencia de contenido escaso confirmada anteriormente permanece abierta hasta que se pueda comprobar de nuevo. Este escaneo incompleto no actualiza la puntuación: una existente conserva su scored_at original y un primer escaneo queda sin puntuación hasta que funcione la segmentación. Instala PHP ext-intl, activa el segmentador auto y vuelve a escanear para reanudar estas comprobaciones.

Qué motores analizaron la página ​

Cada lista incluye un bloque analysis con la escritura predominante del texto, el tokenizador (intl / regex), el motor de raíces (snowball / builtin / identity) y el método de legibilidad (formula / heuristic / lix). Aparece en toArray() / --json, al pie del modal de Filament y en la última línea de seo-pro:checklist:

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

El pie identifica el motor utilizado realmente, incluida la segmentación con expresiones regulares cuando falta ext-intl y la coincidencia identity cuando se desactiva la reducción a raíces.

La densidad de palabras clave es orientativa ​

La lista no establece una densidad ideal para posicionar. Esta comprobación es orientativa: muestra el recuento como información, nunca falla y nunca determina el estado global de la página. Revisa si las repeticiones resultan naturales, en vez de perseguir un porcentaje.

La legibilidad es orientativa ​

La lista estima la legibilidad con el método seleccionado para el idioma de análisis. Estas son las fórmulas y alternativas implementadas:

IdiomaFórmulaFuente
Inglés (en)Flesch Reading EaseFlesch 1948
Italiano (it)Índice GulpeaseLucisano y Piemontese 1988
Español (es)Fernández-HuertaFernández Huerta 1959
Francés (fr)Kandel-MolesKandel y Moles 1958
Alemán (de)erste Wiener SachtextformelBamberger y Vanecek 1984
Portugués (pt, pt_BR)Flesch adaptado al portugués brasileñoMartins et al. 1996
Neerlandés (nl)Flesch-DoumaDouma 1960
Ruso (ru)Adaptación de Flesch de ObornevaОборнева 2006
Turco (tr)AteşmanAteşman 1997
Polaco (pl)Pisarek, índice de años de escolarización normalizadoPisarek 1969
Japonés, chino, coreano (ja, zh, ko)Heurística sin puntuación; consulta más abajo—
Griego, ucraniano, checo (el, uk, cs)LIX, como alternativa porque aquí no se implementa una fórmula específica; sin calibración para estos idiomasBjörnsson 1968
Cualquier otroLIX (Läsbarhetsindex), alternativa sin calibraciónBjörnsson 1968

La puntuación de 0 a 100, donde un valor mayor indica mayor facilidad, es una convención del paquete. Los resultados de la familia Flesch y de Gulpease se limitan a ese intervalo; los índices Wiener, Pisarek y LIX se transforman a la misma escala. Una puntuación igual en distintos idiomas no implica la misma dificultad de lectura. Las fórmulas y sus coeficientes proceden de trabajos publicados; las estimaciones de tokens, oraciones y sílabas de Rankbeam no se han validado como un instrumento completo. No predicen comprensión ni posiciones en buscadores.

Desde Pro 2.37.1, el recuento de sílabas en turco y ruso trata las vocales adyacentes por separado (saat: 2; поэт: 2). Los demás estimadores siguen teniendo limitaciones: los grupos de vocales no distinguen algunos hiatos y vocales mudas. El inglés dispone de un pequeño mapa de excepciones, no de un diccionario de pronunciación. Por ejemplo, el español país y el francés monde pueden contarse mal. Revisa manualmente las palabras poco habituales y los nombres propios.

Estadísticas del texto y límites de la API ​

Las etiquetas HTML de bloque y los elementos br separan el texto; el énfasis en línea permanece unido a su palabra. Los saltos del código fuente en HTML normal se convierten en espacios, mientras que el texto plano y pre conservan los límites de línea. Se excluye el contenido de script, style y noscript. La extracción no evalúa la visibilidad CSS ni la página renderizada. Las entidades se decodifican una vez. Para las estadísticas de las fórmulas, las secuencias de letras o números cuentan como palabras; la puntuación aislada no. Los guiones y apóstrofos separan palabras. Los dígitos cuentan como tokens, pero no se les atribuyen sílabas. Las letras se cuentan en el texto original, sin que la reducción a raíces o la normalización alemana de ß a ss alteren su longitud.

La estimación de oraciones divide por los signos finales . ! ? 。 ! ? y los límites de bloque o línea, incluye un fragmento final sin puntuación y protege los decimales y una pequeña lista de abreviaturas habituales (Dr., Prof., e.g. y formas similares del inglés). Por eso, los encabezados y elementos de listas pueden contar como oraciones. Otras abreviaturas, citas, números, escrituras mixtas y textos con poca puntuación requieren especial atención. El idioma seleccionado determina el método; no detecta si cada oración está escrita en ese idioma.

El método toArray() de la calculadora directa añade un bloque assessment:

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

method distingue entre formula, lix, heuristic y unavailable (unspecified para resultados construidos manualmente sin metadatos de fórmula). Una entrada vacía o solo con puntuación es insufficient y devuelve isValid() = false; su antiguo score: 0 indica que no está disponible, no una dificultad de lectura. Las etiquetas de nivel escolar existentes para inglés e italiano son aproximadas; los demás idiomas y los resultados heurísticos o LIX ya no reciben esas etiquetas. calculateFleschKincaid() conserva su nombre público por compatibilidad, pero calcula Flesch Reading Ease, no el nivel escolar Flesch-Kincaid.

Las pruebas de las fórmulas fijan entradas contadas de forma independiente y los resultados aritméticos esperados para las diez fórmulas y LIX. Verifican el cálculo, no la calidad editorial nativa. La legibilidad sigue separada de la puntuación SEO de Pro.

Japonés, chino y coreano: una heurística identificada, nunca un número

Rankbeam implementa un método sin puntuación para estos idiomas. La calculadora devuelve un nivel según reglas aproximadas propias del paquete: longitud media de las oraciones en caracteres (ja ≤ 40/60/80, zh ≤ 30/45/60) o palabras (ko ≤ 12/18/25) y, para japonés, proporción de kanji; por encima de aproximadamente el 45 %, sube un nivel en los intervalos de dificultad del paquete. El resultado lleva heuristic: true y puntuación nula. El mensaje identifica la heurística y la comprobación sigue siendo orientativa para estos idiomas, independientemente de readability.advisory: informa, pero nunca determina el estado global. Los recuentos de palabras para ja/zh requieren segmentación ICU funcional; estas comprobaciones se omiten si no está disponible.

Al igual que la densidad, la legibilidad es orientativa por defecto: informa a quien escribe, pero no determina el estado global, una separación equivalente a la que Yoast mantiene entre sus análisis de legibilidad y SEO. Se omite por debajo del mínimo de palabras; las páginas con poco contenido corresponden a content_length. Puedes hacer que influya en el resultado si quieres que una página difícil de leer falle:

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
],

Consultar la lista de comprobación ​

Headless ​

Pro 2.36 lee los metadatos resueltos, getContentForSEO() y las palabras clave en el idioma de contenido solicitado, mientras las etiquetas de la lista mantienen el idioma del operador. Sin un idioma explícito, respeta el valor predeterminado de seoData() del modelo traducible. La acción de Filament sigue la pestaña de idioma del campo o el selector de idioma de la página.

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)

Cada CheckResult contiene id, group, label, status, message, una recommendation opcional y el indicador advisory.

Comando ​

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

En el editor de Filament, opcional ​

Con rankbeam/laravel-seo-filament instalado, el campo de palabra clave principal incorpora la acción On-page checklist. Al pulsarla se abre un modal con las mismas comprobaciones de correcto, advertencia y fallo sobre el contenido guardado del registro. El paquete de Filament nunca depende de Pro: la acción se conecta mediante el mismo punto de extensión unidireccional que las sugerencias de IA, sin afectar a las instalaciones headless.

Configuración ​

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,
        // …
    ],
],

Crear una comprobación personalizada ​

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.');
    }
}

Regístrala añadiendo su clase a seo-pro.checklist.rules. Una comprobación no debe reutilizar un identificador de incidencia de escaneo: la lista tiene un espacio de nombres separado que no afecta a la puntuación.

Cómo se lee el contenido ​

SeoPro::checklistFor($model) analiza:

  • Título y descripción: los valores resueltos, es decir, efectivos, que también miden los contadores del editor y el escaneo. Así, la lista no contradice esas mediciones.
  • Contenido: $model->getContentForSEO(), el accesor de HasSEO del paquete principal, que utiliza content / body / text por defecto. Sobrescríbelo en el modelo para indicar el cuerpo real.
  • URL: $model->getUrlForSEO().
  • Palabras clave principales: el valor guardado en seo_meta.focus_keywords.

Es un análisis puro: no descarga páginas ni escribe datos.

rankbeam/laravel-seo se distribuye bajo la licencia MIT.