Vai al contenuto

Problemi di scansione: il registro dei codici

Ogni problema della scansione Pro usa un codice stabile definito in Rankbeam\Seo\Pro\Scanning\IssueRegistry. Gli scanner creano i risultati tramite IssueRegistry::make(), che assegna gravità e campo dal registro e rifiuta i codici non definiti. Dashboard, esportazioni e punteggio Pro possono quindi leggere i codici senza interpretare messaggi tradotti. L'audit gratuito seo:audit espone i propri codici di metadati nel core; la sua copertura è più limitata di questo catalogo Pro.

Ogni codice contiene:

  • id: stringa stabile salvata in seo_scan_issues.issue_type.
  • severity: critical, warning oppure notice, fissata per codice. Gravità diverse richiedono codici distinti.
  • field: campo di seo_meta coinvolto, oppure page per i problemi della pagina.
  • execution class: dati necessari per eseguire il controllo, descritti sotto.
  • evidence: chiavi contenute nell'array context del problema.

Classi di esecuzione

Ogni controllo appartiene a una delle tre classi seguenti:

ClasseRichiedeEsecuzione
metadataModello e resolver core, senza recuperare la paginaScansione del modello con PageScanner; l'audit gratuito seo:audit copre un sottoinsieme di controlli sui metadati
renderedHTML restituito dalla pagina, tramite kernel nel processo o richiesta esternaScansione URL con UrlScanner
networkRichiesta in uscita per verificare una destinazione separata, come un canonical esternoScansione URL, sempre attraverso SsrfGuard

L'audit gratuito nel processo non equivale alla scansione Pro completa: i controlli metadata non richiedono rendering, mentre Pro può leggere l'HTML e verificare destinazioni canonical e hreflang via rete. Per filtrare il registro Pro usa IssueRegistry::byClass(IssueRegistry::EXEC_METADATA).

Codici dei metadati

PageScanner li rileva dal modello e dal resolver. La scansione URL può emettere anche missing_title, missing_description e i codici di lunghezza, leggendo il <head> effettivamente restituito.

CodiceGravitàCampoEvidenzaSignificato
missing_titlecriticaltitleNessun titolo esplicito né fallback calcolabile.
missing_descriptionwarningdescriptionNessuna meta description né fallback calcolabile.
missing_og_imagenoticeog_imageNessuna immagine Open Graph né fallback calcolabile.
missing_focus_keywordnoticefocus_keywordsNessuna parola chiave principale impostata.
duplicate_titlewarningtitletitle, duplicate_urlsTitolo riutilizzato da altre pagine nella stessa locale.
duplicate_descriptionwarningdescriptiondescription, duplicate_urlsDescrizione riutilizzata da altre pagine nella stessa locale.
title_too_longwarningtitlelength, max, scriptTitolo risolto sopra la soglia consigliata per l'alfabeto: 60 per il latino, circa 30 per CJK.
title_too_shortnoticetitlelength, min, scriptTitolo risolto sotto la soglia minima: 30 per il latino, circa 15 per CJK.
description_too_longwarningdescriptionlength, max, scriptDescrizione risolta sopra la soglia consigliata: 160 o circa 80.
description_too_shortnoticedescriptionlength, min, scriptDescrizione risolta sotto la soglia minima: 70 o circa 35.
robots_conflict_indexingcriticalrobotsrobotsDirettiva robots con index e noindex insieme.
robots_conflict_followingwarningrobotsrobotsDirettiva robots con follow e nofollow insieme.
noindex_warningwarningrobotsrobots, canonical, page_url, shipping_signalPagina con canonical autoreferenziale e noindex, da verificare; il canonical da solo non dimostra che debba essere indicizzata. Emesso dalle scansioni modello e URL.
invalid_canonicalcriticalcanonicalcanonicalCanonical non valido come URL.
cross_domain_canonicalwarningcanonicalcanonical, page_urlCanonical verso un host diverso da quello della pagina.
shared_canonicalnoticecanonicalcanonicalPiù pagine dichiarano lo stesso canonical.
insecure_canonicalwarningcanonicalcanonicalCanonical http:// su un sito https.
hreflang_invalid_codewarningalternatesinvalid_codesValore hreflang diverso da x-default e non riconosciuto come codice BCP-47 valido.
hreflang_missing_self_referencewarningalternateslocale, page_urlSono dichiarate alternative, ma nessuna riferisce la locale della pagina stessa.
hreflang_duplicate_codewarningalternatesduplicate_codesUno stesso codice hreflang è associato a più URL.
hreflang_missing_x_defaultnoticealternateslanguagesGruppo multilingue senza fallback x-default.
aeo_missing_authornoticeschemaArticolo nei dati strutturati senza entità autore.
aeo_article_missing_datenoticeschemaArticolo nei dati strutturati senza data di pubblicazione o modifica.

Le soglie di lunghezza usano la politica del core per alfabeto, adottata da Pro 2.33: 60/160 per il latino, circa 30/80 per CJK, contati in grafemi come nell'editor. Le soglie inferiori sono 30 per il titolo e 70 per la descrizione in latino, circa metà per CJK. Sono indicazioni del pacchetto, non limiti fissi dei risultati di ricerca. La chiave script identifica il gruppo usato. Si misura il valore risolto, inclusi fallback e suffisso del titolo.

I codici hreflang_* dei metadati controllano l'elenco alternates dichiarato dal resolver: codici non validi o duplicati, autoreferenza mancante e assenza di x-default in un gruppo multilingue. Si attivano solo quando esistono alternative. La reciprocità tra pagine richiede invece il controllo di rete facoltativo descritto sotto; non viene verificata da questi controlli sui metadati.

I codici aeo_* controllano la rappresentazione degli articoli nel JSON-LD risolto. Si attivano solo per tipi articolo, come Article, BlogPosting e NewsArticle, senza entità author o data datePublished / dateModified. Non segnalano pagine senza articoli. Dipendono da seo-pro.scan.checks.aeo, attivo per impostazione predefinita, e corrispondono ai controlli disponibili anche in seo:audit.

missing_focus_keyword richiede l'attivazione del campo

La segnalazione compare solo con il flusso delle parole chiave del core attivo: seo.keywords.enabled, predefinito false. Se è disattivato, la scansione non segnala la parola chiave mancante. L'audit gratuito e l'editor Filament leggono lo stesso interruttore.

Codici dell'HTML renderizzato

UrlScanner li rileva nell'HTML restituito. Per target sullo stesso host usa il kernel nel processo, senza traffico in uscita; per quelli esterni usa una richiesta protetta.

CodiceGravitàCampoEvidenzaSignificato
http_errorcriticalpagestatusRisposta HTTP 4xx o 5xx.
empty_responsecriticalpageCorpo della risposta vuoto.
missing_canonicalnoticecanonicalNessun <link rel="canonical"> nel head renderizzato.
noindex_pagenoticerobotsrobotsPagina noindex, segnalazione informativa. Se ha anche un canonical autoreferenziale, viene emesso invece noindex_warning, che incide sul punteggio.
missing_h1noticepageNessun titolo <h1>.
multiple_h1noticepagecountPiù di un <h1>, segnalazione informativa.
missing_image_altwarningpagecount, total, sampleImmagini del contenuto senza attributo alt; alt="" esplicito viene trattato come decorativo e non segnalato.
thin_contentnoticepageword_count, threshold, segmenterTesto sotto la soglia configurata. Il conteggio usa il tokenizer della checklist e ICU per cinese, giapponese e thailandese, con segmenter: intl ed ext-intl. Se la segmentazione necessaria non è disponibile, il verdetto viene sospeso, come descritto nella guida alla checklist.
mixed_contentwarningpagecount, sampleSottorisorse http:// in una pagina https.
html_lang_missingnoticepage<html lang> assente o vuoto; può impedire alle tecnologie assistive di scegliere la pronuncia corretta.
html_lang_invalidnoticepagedeclaredlang non valido come tag BCP-47, per esempio english, en_US o jp.
html_lang_mismatchwarningpagedeclared, declared_script, detected_scriptAlfabeto del testo visibile incompatibile con la lingua dichiarata, come lang="en" su testo giapponese. Controllo solo per alfabeto, senza indovinare la lingua tra lingue latine; richiede almeno 40 lettere.

Codici delle verifiche di rete

UrlScanner esegue queste verifiche solo con l'opzione corrispondente attiva: seo-pro.scan.url_checks.check_canonical_target per il canonical e check_hreflang_reciprocity per le alternative hreflang. Ogni destinazione passa da SsrfGuard, con schemi e host consentiti, rifiuto degli IP privati e limiti di tempo e dimensione. I redirect non vengono seguiti, così restano rilevabili. Canonical e alternative autoreferenziali vengono saltati perché la pagina è già stata recuperata.

CodiceGravitàCampoEvidenzaSignificato
blocked_urlnoticepagereasonDestinazione rifiutata da SsrfGuard prima della richiesta HTTP.
canonical_target_brokencriticalcanonicalcanonical, statusDestinazione canonical con errore HTTP.
canonical_target_redirectwarningcanonicalcanonical, status, locationCanonical verso un redirect; valuta l'URL finale.
canonical_target_noindexwarningcanonicalcanonicalDestinazione canonical a sua volta noindex.
canonical_target_blockednoticecanonicalcanonical, reasonDestinazione non verificabile per rifiuto della protezione o mancata risoluzione.
hreflang_not_reciprocalwarningalternateshreflang, href, statusL'alternativa non dichiara il link di ritorno. La coppia hreflang può essere ignorata; ciò non rende di per sé la traduzione non indicizzabile.
hreflang_target_unverifiednoticealternateshreflang, href, reasonDestinazione non recuperabile per protezione, errore, redirect o dimensione; reciprocità non verificata, non difetto confermato.

La verifica recupera al massimo hreflang_max_alternates destinazioni per pagina, 10 per impostazione predefinita, includendo x-default ed escludendo duplicati e pagina corrente. I codici dei metadati verificano l'elenco dichiarato; solo questo controllo legge l'altra pagina.

Tutti i percorsi di rete riusano SsrfGuard. SECURITY.md del repository Pro descrive il modello di minaccia e il rischio residuo TOCTOU.

Come i codici incidono sul punteggio

Il punteggio SEO Pro parte da 100 e sottrae una penalità fissa per ogni problema incluso nei criteri. Sono esclusi missing_focus_keyword, consultivo, noindex_page e multiple_h1, informativi, e blocked_url, canonical_target_blocked e hreflang_target_unverified, che indicano verifiche non riuscite. Anche hreflang_*, html_lang_* e aeo_* restano esclusi dal punteggio. La guida al calcolo contiene l'elenco completo e le penalità.

Ciclo di vita dei problemi

La scansione riconcilia i problemi del target anziché cancellarli e ricrearli. L'identità stabile combina target, scannable_type e scannable_id per un modello oppure url per route e sitemap, e issue_type. Ogni codice viene emesso al massimo una volta per target e scansione. I controlli con più occorrenze, come missing_image_alt, mixed_content e hreflang_*, le raccolgono in una riga con conteggi, campioni o elenchi di evidenze.

A ogni scansione del target:

  • Un risultato senza riga precedente viene creato open con detected_at.
  • Un risultato che corrisponde a una riga aperta aggiorna le evidenze e conserva il primo detected_at.
  • Un problema aperto che la scansione non rileva più, quando il controllo è stato completato, diventa fixed con resolved_at. La riga rimane salvata.
  • Un problema fixed che ricompare viene riaperto sulla stessa riga, aggiornando detected_at.
  • Un problema segnato ignored dall'utente nel dashboard viene lasciato invariato.
StatoSignificatoImpostato da
openPresente al controllo.Scansione, per risultati nuovi o ancora presenti
fixedPresente in precedenza, non più rilevato.Scansione successiva che completa il controllo senza ritrovarlo
ignoredSilenziato dall'utente; escluso da conteggi aperti e punteggio.Azione Ignore nel dashboard

Lo storico permette al report di mostrare correzioni e nuovi problemi nel periodo, senza affidarsi solo alla differenza tra snapshot. Dashboard, seo-pro:scan-status e punteggio considerano i problemi open, quindi le righe fixed non ne aumentano i conteggi. Le righe risolte vengono associate alla scansione che le ha chiuse e seguono la normale conservazione delle esecuzioni.

Configurazione

php
// config/seo-pro.php → 'scan'
'url_checks' => [
    'enabled' => true,
    'crawl_external' => false,             // fetch external URL targets (guarded)
    'check_canonical_target' => false,     // EXEC_NETWORK canonical validation (guarded)
    'check_hreflang_reciprocity' => false, // EXEC_NETWORK hreflang link-back crawl (guarded)
    'hreflang_max_alternates' => 10,       // targets fetched per page by that crawl
],
'checks' => [
    'length' => true,            // title/description length (metadata + rendered)
    'rendered_content' => true,  // H1 / alt / thin content / mixed content / html lang
],
'content' => [
    'min_word_count' => 200,     // thin_content threshold
    'evidence_sample' => 5,      // max example URLs stored per issue
],

Le richieste protette usano seo-pro.http.max_response_bytes, predefinito 2 MB. La scansione dello stesso host attraverso il kernel nel processo non applica questo limite.

Compatibilità: rinomina dei codici

Il precedente robots_conflict, che poteva avere due gravità, è stato diviso affinché ogni codice abbia una sola gravità:

Vecchio codiceNuovo codiceGravità
robots_conflict, index + noindexrobots_conflict_indexingcritical
robots_conflict, follow + nofollowrobots_conflict_followingwarning

Se salvi o filtri robots_conflict, passa ai due nuovi codici.

rankbeam/laravel-seo è distribuito con licenza MIT.