Προβλήματα σάρωσης — το μητρώο κωδικών προβλημάτων
Κάθε πρόβλημα που αναφέρει η σάρωση Pro είναι ένας σταθερός κωδικός προβλήματος από ένα ενιαίο μητρώο, το Rankbeam\Seo\Pro\Scanning\IssueRegistry. Οι σαρωτές δεν επινοούν ποτέ κωδικούς επιτόπου — κατασκευάζουν κάθε πρόβλημα μέσω του IssueRegistry::make(), που ορίζει τη σοβαρότητα και το πεδίο από το μητρώο και απορρίπτει κάθε κωδικό που δεν έχει οριστεί. Έτσι, ο παρακάτω κατάλογος αποτελεί μια σύμβαση στην οποία μπορείτε να βασιστείτε: οι πίνακες ελέγχου, οι εξαγωγές και η βαθμολογία Pro διαβάζουν κωδικούς αντί να αναλύουν μηνύματα. Το δωρεάν seo:audit χρησιμοποιεί το δικό του μητρώο μεταδεδομένων του Core, με στενότερη κάλυψη και ορισμένους διαφορετικούς κωδικούς hreflang.
Κάθε κωδικός περιλαμβάνει:
- id — τη σταθερή συμβολοσειρά που αποθηκεύεται ως
seo_scan_issues.issue_type. - severity —
critical,warningήnotice· σταθερή ανά κωδικό (χωρίζουμε έναν κωδικό αντί να μεταβάλλουμε τη σοβαρότητά του). - field — το πεδίο του
seo_metaπου αφορά ή page για ευρήματα σε επίπεδο σελίδας. - κλάση εκτέλεσης — τι χρειάζεται ένας καταναλωτής για να το εντοπίσει (δείτε παρακάτω).
- τεκμήρια — τα κλειδιά που περιέχει ο πίνακας
contextτου προβλήματος.
Κλάσεις εκτέλεσης
Κάθε έλεγχος ανήκει σε ακριβώς μία από τρεις κλάσεις, ανάλογα με όσα χρειάζεται για να εκτελεστεί:
| Κλάση | Απαιτήσεις | Ποιος μπορεί να τον εκτελέσει |
|---|---|---|
| metadata | το μοντέλο + ο resolver του Core — χωρίς ανάκτηση σελίδας | η σάρωση μοντέλου (PageScanner)· το δωρεάν seo:audit καλύπτει ένα υποσύνολο ελέγχων μεταδεδομένων |
| rendered | το HTML που σερβίρει η σελίδα (αίτημα kernel μέσα στη διεργασία ή εξωτερική ανάκτηση) | η σάρωση URL (UrlScanner) |
| network | μια εξερχόμενη ανάκτηση για επικύρωση ενός διαφορετικού προορισμού (κανονική διεύθυνση URL που δείχνει αλλού) | η σάρωση URL, πάντα μέσω του SsrfGuard |
Γι' αυτό ένας δωρεάν έλεγχος μέσα στη διεργασία δεν μπορεί ποτέ να ισοδυναμεί με την πλήρη σάρωση Pro: μόνο οι κωδικοί metadata μπορούν να υπολογιστούν χωρίς απόδοση σελίδας και μόνο η ροή του Pro ανακτά αποδιδόμενο HTML και επικυρώνει κανονικούς προορισμούς μέσω δικτύου. Φιλτράρετε το μητρώο ανά κλάση με IssueRegistry::byClass(IssueRegistry::EXEC_METADATA).
Κωδικοί μεταδεδομένων
Εντοπίζονται από το μοντέλο + τον resolver μέσω του PageScanner. (Τα missing_title, missing_description και οι κωδικοί μήκους παράγονται επίσης από τη σάρωση του αποδιδόμενου URL, μετρώντας το σερβιρισμένο <head> — ίδιοι κωδικοί, ίδια σημασία.)
| Κωδικός | Σοβαρότητα | Πεδίο | Τεκμήρια | Σημασία |
|---|---|---|---|---|
missing_title | critical | title | — | Δεν υπάρχει τίτλος ούτε υπολογίσιμη εφεδρική τιμή. |
missing_description | warning | description | — | Δεν υπάρχει meta description ούτε υπολογίσιμη εφεδρική τιμή. |
missing_og_image | notice | og_image | — | Δεν υπάρχει εικόνα Open Graph ούτε υπολογίσιμη εφεδρική τιμή. |
missing_focus_keyword | notice | focus_keywords | — | Δεν έχει οριστεί λέξη-κλειδί εστίασης. |
duplicate_title | warning | title | title, duplicate_urls | Ο τίτλος επαναχρησιμοποιείται σε άλλες σελίδες της ίδιας τοπικής ρύθμισης. |
duplicate_description | warning | description | description, duplicate_urls | Η περιγραφή επαναχρησιμοποιείται σε άλλες σελίδες της ίδιας τοπικής ρύθμισης. |
title_too_long | warning | title | length, max, script | Ο τελικός τίτλος υπερβαίνει τη σύσταση για το σύστημα γραφής (60 για λατινική γραφή, περίπου 30 για CJK). |
title_too_short | notice | title | length, min, script | Ο τελικός τίτλος είναι κάτω από το κατώτερο όριο του συστήματος γραφής (30 για λατινική γραφή, περίπου 15 για CJK). |
description_too_long | warning | description | length, max, script | Η τελική περιγραφή υπερβαίνει τη σύσταση για το σύστημα γραφής (160 / περίπου 80). |
description_too_short | notice | description | length, min, script | Η τελική περιγραφή είναι κάτω από το κατώτερο όριο του συστήματος γραφής (70 / περίπου 35). |
robots_conflict_indexing | critical | robots | robots | Η οδηγία robots περιέχει και index και noindex. |
robots_conflict_following | warning | robots | robots | Η οδηγία robots περιέχει και follow και nofollow. |
noindex_warning | warning | robots | robots, canonical, page_url, shipping_signal | Μια σελίδα με κανονική διεύθυνση URL τον εαυτό της είναι noindex: ευρετική ένδειξη προς εξέταση, όχι απόδειξη ότι η σελίδα πρέπει να ευρετηριαστεί. Παράγεται τόσο στη σάρωση μοντέλου όσο και στη σάρωση αποδιδόμενου URL. |
invalid_canonical | critical | canonical | canonical | Η τιμή canonical δεν είναι έγκυρη διεύθυνση URL. |
cross_domain_canonical | warning | canonical | canonical, page_url | Η κανονική διεύθυνση URL δείχνει σε διαφορετικό host από τη σελίδα. |
shared_canonical | notice | canonical | canonical | Αρκετές σελίδες δηλώνουν την ίδια κανονική διεύθυνση URL. |
insecure_canonical | warning | canonical | canonical | Κανονική διεύθυνση URL http:// σε ιστότοπο https. |
hreflang_invalid_code | warning | alternates | invalid_codes | Μια εναλλακτική hreflang χρησιμοποιεί τιμή που δεν είναι ούτε x-default ούτε έγκυρος γλωσσικός κωδικός BCP-47. |
hreflang_missing_self_reference | warning | alternates | locale, page_url | Δηλώνονται εναλλακτικές εκδόσεις, αλλά καμία δεν αναφέρεται στην τοπική ρύθμιση της ίδιας της σελίδας (αυτοαναφορικό hreflang). |
hreflang_duplicate_code | warning | alternates | duplicate_codes | Ο ίδιος κωδικός hreflang αντιστοιχεί σε περισσότερες από μία διευθύνσεις URL (ασαφής συστάδα). |
hreflang_missing_x_default | notice | alternates | languages | Μια πολύγλωσση συστάδα hreflang δεν έχει εφεδρικό x-default. |
aeo_missing_author | notice | schema | — | Ένα άρθρο στα δομημένα δεδομένα της σελίδας δεν έχει οντότητα συγγραφέα (η συγγραφή / προέλευση δεν δηλώνεται ρητά στα δομημένα δεδομένα). |
aeo_article_missing_date | notice | schema | — | Ένα άρθρο στα δομημένα δεδομένα της σελίδας δεν έχει ημερομηνία δημοσίευσης/τροποποίησης (το χρονολόγιο του άρθρου δεν δηλώνεται ρητά στα δομημένα δεδομένα). |
Τα όρια μήκους προέρχονται από την πολιτική μήκους του Core, που λαμβάνει υπόψη το σύστημα γραφής (Pro 2.33): 60/160 για λατινικό κείμενο, περίπου 30/80 για CJK, με καταμέτρηση γραφημάτων, ώστε η σάρωση να μην έρχεται ποτέ σε αντίθεση με τους μετρητές χαρακτήρων του επεξεργαστή. Τα κατώτερα όρια (τίτλος 30, περιγραφή 70 για λατινική γραφή, περίπου τα μισά για CJK) είναι το όριο που χρησιμοποιεί η σάρωση για ανεπαρκή βελτιστοποίηση, και το κλειδί συμφραζομένων script ονομάζει την κατηγορία που εφαρμόστηκε. Το μήκος μετριέται στον τελικό τίτλο/περιγραφή — την τιμή που πράγματι αποδίδεται, μαζί με κάθε εφεδρική τιμή και επίθημα τίτλου.
Οι κωδικοί hreflang_* επικυρώνουν τις δηλωμένες εναλλακτικές hreflang μιας σελίδας (από το alternates του resolver): μη έγκυρους/διπλότυπους κωδικούς, ελλιπή αυτοαναφορά και έλλειψη x-default σε πολύγλωσση συστάδα. Εκτελούνται μόνο όταν η σελίδα δηλώνει εναλλακτικές εκδόσεις. Η αμοιβαιότητα μεταξύ σελίδων («ετικέτες επιστροφής») δεν ελέγχεται από αυτούς τους ελέγχους μεταδεδομένων· ο προαιρετικός έλεγχος δικτύου παρακάτω ανακτά την άλλη σελίδα.
Οι κωδικοί aeo_* είναι ενδείξεις ετοιμότητας για απαντήσεις (AEO) — είναι το περιεχόμενο του άρθρου της σελίδας αναγνωρίσιμο στα δομημένα δεδομένα της; Διαβάζουν τον τελικό γράφο JSON-LD και ενεργοποιούνται μόνο όταν αυτός δηλώνει δομημένα δεδομένα τύπου άρθρου (Article, BlogPosting, NewsArticle, …) από τα οποία λείπει οντότητα author (ρητή συγγραφή / προέλευση) ή datePublished / dateModified (ρητό χρονολόγιο). Μια σελίδα χωρίς άρθρο δεν επισημαίνεται ποτέ. Ελέγχονται από το seo-pro.scan.checks.aeo (ενεργό από προεπιλογή) και αντιστοιχούν στο δωρεάν seo:audit.
Το missing_focus_keyword εξαρτάται από ρύθμιση
Η ειδοποίηση λέξης-κλειδιού εστίασης ενεργοποιείται μόνο όταν είναι ενεργή η ροή λέξεων-κλειδιών εστίασης του Core (seo.keywords.enabled, προεπιλογή false). Όσο είναι απενεργοποιημένη, η σάρωση δεν επισημαίνει μια σελίδα επειδή δεν έχει λέξη-κλειδί εστίασης. Η δωρεάν εντολή seo:audit και ο επεξεργαστής Filament διαβάζουν την ίδια ρύθμιση του Core, οπότε η σάρωση, ο έλεγχος και η υπενθύμιση του επεξεργαστή συμφωνούν πάντα — υπάρχει μόνο ένας διακόπτης.
Κωδικοί αποδιδόμενης σελίδας
Εντοπίζονται από το UrlScanner στο σερβιρισμένο HTML — για στόχους του ίδιου host μέσω αιτήματος kernel μέσα στη διεργασία (χωρίς εξερχόμενη κίνηση), για εξωτερικούς στόχους μέσω προστατευμένης ανάκτησης.
| Κωδικός | Σοβαρότητα | Πεδίο | Τεκμήρια | Σημασία |
|---|---|---|---|---|
http_error | critical | page | status | Η διεύθυνση URL απάντησε με κατάσταση 4xx/5xx. |
empty_response | critical | page | — | Η διεύθυνση URL επέστρεψε κενό σώμα. |
missing_canonical | notice | canonical | — | Δεν υπάρχει <link rel="canonical"> στο αποδιδόμενο head. |
noindex_page | notice | robots | robots | Η αποδιδόμενη σελίδα είναι noindex (πληροφοριακό). Μια σελίδα noindex που δηλώνει επίσης τον εαυτό της ως κανονική αναβαθμίζεται αντί αυτού στο βαθμολογούμενο noindex_warning. |
missing_h1 | notice | page | — | Δεν υπάρχει επικεφαλίδα <h1>. |
multiple_h1 | notice | page | count | Περισσότερες από μία <h1> (πληροφοριακό). |
missing_image_alt | warning | page | count, total, sample | Από εικόνες περιεχομένου λείπει το χαρακτηριστικό alt (ένα ρητό alt="" θεωρείται διακοσμητικό και δεν επισημαίνεται). |
thin_content | notice | page | word_count, threshold, segmenter | Το κείμενο του σώματος είναι κάτω από το ρυθμισμένο πλήθος λέξεων. Οι λέξεις μετριούνται με τον tokenizer της λίστας ελέγχου: κενά για συστήματα γραφής με διαστήματα, τμηματοποίηση βάσει λεξικού ICU (segmenter: intl, απαιτεί ext-intl) για κινεζικά, ιαπωνικά και ταϊλανδικά — έτσι ένα ιαπωνικό άρθρο 400 λέξεων δεν θεωρείται μία «λέξη». |
mixed_content | warning | page | count, sample | Υποπόροι http:// σε σελίδα https. |
html_lang_missing | notice | page | — | Δεν υπάρχει <html lang> (ή είναι κενό). Η υποστηρικτική τεχνολογία μπορεί να επιλέξει ακατάλληλη φωνή. |
html_lang_invalid | notice | page | declared | Η τιμή lang δεν είναι ετικέτα BCP-47 (english, en_US με κάτω παύλα, jp). |
html_lang_mismatch | warning | page | declared, declared_script, detected_script | Το ορατό κείμενο σώματος είναι γραμμένο σε σύστημα γραφής διαφορετικό από εκείνο της δηλωμένης γλώσσας — lang="en" σε ιαπωνική σελίδα, lang="ru" σε λατινικό κείμενο. Μόνο σε επίπεδο συστήματος γραφής (μια λατινική σελίδα που δηλώνει λανθασμένη λατινική γλώσσα θα απαιτούσε εικασία, και η σάρωση δεν εικάζει)· απαιτούνται ≥ 40 γράμματα κειμένου σώματος. |
Κωδικοί δικτύου
Εντοπίζονται από το UrlScanner μόνο όταν είναι ενεργή η αντίστοιχη προαιρετική ρύθμιση: seo-pro.scan.url_checks.check_canonical_target για τον κανονικό προορισμό, check_hreflang_reciprocity για τις εναλλακτικές hreflang. Κάθε στόχος ανακτάται μέσω του SsrfGuard (λίστα επιτρεπόμενων σχημάτων, πεδίο hosts, απόρριψη ιδιωτικών IP, όρια ανακατευθύνσεων/χρόνου/μεγέθους) και δεν ακολουθούνται οι ανακατευθύνσεις, ώστε να φαίνεται ένας κανονικός προορισμός που ανακατευθύνει. Μια αυτοαναφορική κανονική ή εναλλακτική διεύθυνση URL παραλείπεται — η ίδια η σελίδα μόλις ανακτήθηκε.
| Κωδικός | Σοβαρότητα | Πεδίο | Τεκμήρια | Σημασία |
|---|---|---|---|---|
blocked_url | notice | page | reason | Ένας στόχος απορρίφθηκε από το SsrfGuard πριν γίνει οποιοδήποτε αίτημα HTTP. |
canonical_target_broken | critical | canonical | canonical, status | Η κανονική διεύθυνση URL δείχνει σε σελίδα που επιστρέφει σφάλμα HTTP. |
canonical_target_redirect | warning | canonical | canonical, status, location | Η κανονική διεύθυνση URL δείχνει σε σελίδα που ανακατευθύνει· ορίστε την τελική διεύθυνση URL. |
canonical_target_noindex | warning | canonical | canonical | Η κανονική διεύθυνση URL δείχνει σε σελίδα που είναι η ίδια noindex. |
canonical_target_blocked | notice | canonical | canonical, reason | Ο κανονικός προορισμός δεν μπόρεσε να επαληθευτεί (απόρριψη από την προστασία / αδυναμία επίλυσης). |
hreflang_not_reciprocal | warning | alternates | hreflang, href, status | Μια εναλλακτική έκδοση που δηλώνει η σελίδα δεν δηλώνει τη σελίδα ως επιστροφή. Το ζεύγος hreflang μπορεί να αγνοηθεί· αυτό από μόνο του δεν καθιστά τη μετάφραση μη ευρετηριάσιμη. |
hreflang_target_unverified | notice | alternates | hreflang, href, reason | Η εναλλακτική έκδοση δεν μπόρεσε να ανακτηθεί (απόρριψη από την προστασία, κατάσταση σφάλματος, ανακατεύθυνση, υπέρβαση ορίου μεγέθους), οπότε η αμοιβαιότητα δεν ελέγχθηκε ποτέ. Απουσία τεκμηρίων, όχι ελάττωμα. |
Ο έλεγχος αμοιβαιότητας ανακτά το πολύ hreflang_max_alternates (προεπιλογή 10) στόχους ανά σελίδα, συμπεριλαμβανομένου του x-default, παραλείποντας διπλότυπα και την ίδια τη σελίδα. Οι παραπάνω κωδικοί μεταδεδομένων hreflang_* σε επίπεδο μοντέλου επικυρώνουν τη δηλωμένη λίστα· αυτή η ανίχνευση είναι ο έλεγχος που χρειάζεται την άλλη σελίδα.
Κάθε διαδρομή δικτύου εδώ επαναχρησιμοποιεί το κοινό SsrfGuard· δείτε το SECURITY.md για το μοντέλο απειλών και τη σημείωση για τον υπολειπόμενο κίνδυνο TOCTOU.
Πώς οι κωδικοί τροφοδοτούν τη βαθμολογία
Η βαθμολογία SEO του Pro υπολογίζεται ως 100 − μια σταθερή ποινή ανά βαθμολογούμενο πρόβλημα, σταθμισμένη με τις παραπάνω σοβαρότητες. Οι περισσότεροι κωδικοί μετρούν· ορισμένοι εξαιρούνται σκόπιμα — το missing_focus_keyword (συμβουλευτικό), τα noindex_page και multiple_h1 (πληροφοριακά), τα blocked_url / canonical_target_blocked / hreflang_target_unverified («δεν μπορέσαμε να ελέγξουμε» ≠ ελάττωμα), και οι κωδικοί hreflang_*, html_lang_* και aeo_* (συμβουλευτικές ενδείξεις που προς το παρόν μένουν εκτός βαθμολογίας). Η σελίδα βαθμολόγησης περιέχει την πλήρη λίστα και την ποινή για κάθε κωδικό.
Κύκλος ζωής προβλήματος
Ένα πρόβλημα δεν είναι απλώς μια εγγραφή που υπάρχει όσο υπάρχει το πρόβλημα — έχει κύκλο ζωής, και η σάρωση αντιπαραβάλλει και ενημερώνει τα προβλήματα του στόχου αντί να τα διαγράφει και να τα δημιουργεί ξανά. Κάθε πρόβλημα έχει σταθερή ταυτότητα: ο στόχος (scannable_type + scannable_id για μοντέλο ή το url για στόχο διαδρομής/χάρτη ιστοτόπου) συν το issue_type του. Κάθε κωδικός παράγεται το πολύ μία φορά ανά στόχο ανά σάρωση — οι κωδικοί «N παραβάσεις» (missing_image_alt, mixed_content, hreflang_*, …) συγκεντρώνουν τις εμφανίσεις τους σε μία εγγραφή με count / sample — οπότε αυτή η ταυτότητα είναι μοναδική.
Σε κάθε σάρωση, για κάθε στόχο:
- ένα εύρημα χωρίς υπάρχουσα εγγραφή δημιουργείται ως
open, με χρονική σήμανσηdetected_at· - ένα εύρημα που αντιστοιχεί σε υπάρχουσα ανοιχτή εγγραφή ανανεώνει τα τεκμήριά του και κρατά το αρχικό
detected_at— σταθερή πρώτη εμφάνιση, που δεν μηδενίζεται πλέον σε κάθε σάρωση· - ένα ανοιχτό πρόβλημα που ένας ολοκληρωμένος έλεγχος δεν εντοπίζει πλέον σημειώνεται ως
fixed(με χρονική σήμανσηresolved_at) — η εγγραφή διατηρείται, δεν διαγράφεται, ώστε να καταγράφεται μια πραγματική διόρθωση· - ένα πρόβλημα
fixedπου επανεμφανίζεται ανοίγει ξανά στην ίδια εγγραφή (επανεμφάνιση), με νέα χρονική σήμανσηdetected_at· - ένα πρόβλημα που ο χρήστης σημείωσε ως
ignoredστον πίνακα ελέγχου παραμένει ανέπαφο.
| Κατάσταση | Σημασία | Ορίζεται από |
|---|---|---|
open | Υπάρχει αυτή τη στιγμή. | τη σάρωση (νέο ή εξακολουθεί να εντοπίζεται) |
fixed | Υπήρχε, δεν εντοπίζεται πλέον. | τη σάρωση (αυτόματα), στην επόμενη εκτέλεση που δεν το εντοπίζει ξανά |
ignored | Αγνοήθηκε από χρήστη· εξαιρείται από τα πλήθη ανοιχτών προβλημάτων και τη βαθμολογία. | την ενέργεια Παράβλεψη του πίνακα ελέγχου |
Επειδή οι διορθώσεις πλέον καταγράφονται αντί να απορρίπτονται, η αναφορά με δική σας επωνυμία μπορεί να δείξει πραγματικά πλήθη διορθωμένων / νέων προβλημάτων σε μια περίοδο, αντί για διαφορά στιγμιότυπων μεταξύ αναφορών. Όλοι οι καταναλωτές πλήθους ανοιχτών προβλημάτων — ο πίνακας ελέγχου, η εντολή seo-pro:scan-status, η βαθμολογία — φιλτράρουν στο open, οπότε οι αποθηκευμένες εγγραφές fixed δεν αυξάνουν ποτέ τα πλήθη τους. Οι διορθωμένες εγγραφές αποδίδονται στην εκτέλεση που τις επίλυσε και διαγράφονται όταν παρέλθει το κανονικό διάστημα διατήρησης εκτελέσεων σάρωσης.
Ρυθμίσεις
// 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
],Το όριο μεγέθους απόκρισης για προστατευμένες ανακτήσεις είναι το seo-pro.http.max_response_bytes (προεπιλογή 2 MB)· η σάρωση στον ίδιο host μέσα στη διεργασία δεν έχει όριο μεγέθους.
Σημείωση συμβατότητας (μετονομασία κωδικού προβλήματος)
Ο προηγούμενος ενιαίος κωδικός robots_conflict (που είχε δύο σοβαρότητες) χωρίστηκε, ώστε κάθε κωδικός να αντιστοιχεί σε ακριβώς μία σοβαρότητα:
| Παλιός κωδικός | Νέος κωδικός | Σοβαρότητα |
|---|---|---|
robots_conflict (index + noindex) | robots_conflict_indexing | critical |
robots_conflict (follow + nofollow) | robots_conflict_following | warning |
Αν αποθηκεύατε ή φιλτράρατε με βάση το robots_conflict, ενημερώστε τη χρήση σας στους δύο νέους κωδικούς.