Sylius SEO Suite Pro: Fehlerbehebung
Fehlerbehebung für Sylius SEO Suite Pro: robots.txt, SEO-Felder, Setup, hreflang, JSON-LD, OG-Bilder, Audit, Redirects und 404-Log mit Symptom, Prüfen, Lösung, dazu Einschränkungen und FAQ.
Sylius SEO Suite Pro: Fehlerbehebung
Diese Seite führt typische Probleme nach dem Muster Symptom, Prüfen, Lösung auf. Alle Aussagen stammen aus dem Verhalten des Plugin-Codes. Die Grundlagen stehen in der Installation und der Konfiguration.
Fast alle Plugin-Funktionen fallen bei fehlenden Tabellen oder Fehlern still auf das Standardverhalten zurück und schreiben eine Warnung ins Log. Schau bei jedem Problem zuerst in das Log Deiner Umgebung und suche nach
mmd/sylius-seo-suite-pro-plugin.
/robots.txt liefert 404 oder nicht den erwarteten Inhalt
Symptom: /robots.txt antwortet mit 404, mit einer Datei aus dem Webroot oder mit User-agent: * und Allow: /, obwohl Du im Admin einen eigenen Inhalt gepflegt hast.
Prüfen:
- Die Shop-Routen müssen auf oberster Ebene importiert sein und nicht unter dem Präfix
/{_locale}. Sonst existiert die Route nur als/{_locale}/robots.txt. - Die Routen müssen im Router vorhanden sein:
bin/console debug:router mmd_sylius_seo_suite_pro_robots_txtmuss den Pfad/robots.txtzeigen. - Liegt im Webroot eine physische Datei
public/robots.txt? Der Webserver liefert sie aus, bevor Symfony die Anfrage sieht. - Für den Channel der aufgerufenen Domain muss ein Eintrag in den Channel-Einstellungen mit einem robots.txt-Inhalt existieren. Ohne Eintrag oder bei nicht auflösbarer Domain antwortet das Plugin bewusst mit dem erlaubenden Standard
User-agent: *undAllow: /. - Die Antwort ist öffentlich cachebar (
max-age3600 Sekunden), solange keine Session gestartet wurde. Ein vorgeschalteter Cache kann alte Inhalte ausliefern.
Lösung: Importiere @MmdSyliusSeoSuiteProPlugin/config/routes/shop.yaml auf oberster Ebene (siehe Installation), entferne eine statische public/robots.txt, pflege den Inhalt in den Channel-Einstellungen (siehe Konfiguration) und leere bei Bedarf den vorgeschalteten Cache.
SEO-Felder fehlen im Produkt- oder Kategorieformular
Symptom: Im Admin gibt es bei Produkten und Kategorien keine Felder für Meta-Titel, Canonical-Override und Robots. Bei Kategorien fehlt zusätzlich die Meta-Beschreibung.
Prüfen:
- Die Felder sind optional zuschaltbar. Sie erscheinen nur, wenn die Übersetzungsklasse des Shops
SeoAwareTranslationInterfaceimplementiert (mitSeoAwareTranslationTrait). - Für die Meta-Beschreibung einer Kategorie muss die Taxon-Übersetzung zusätzlich
MetaDescriptionAwareTranslationInterfacemit dem passenden Trait implementieren. Bei Produkten nutzt das Plugin das Core-Feld der Meta-Beschreibung. - Die eigenen Spalten brauchen eine Migration des Shops. Das Plugin ändert keine Core-Klassen.
Lösung: Folge der Anleitung zum Zuschalten der Felder in der Installation, erstelle die Migration für Deine Übersetzungstabellen und leere danach den Cache (bin/console cache:clear).
Der Setup-Befehl bricht ab
Symptom: bin/console mmd:seo-suite-pro:setup endet mit einer Fehlermeldung, oder die Plugin-Tabellen sind danach nicht vorhanden.
Prüfen:
- Meldung
Migrations this plugin builds on are still open. Run "bin/console doctrine:migrations:migrate" first...: Migrationen von Sylius selbst sind noch offen. Der Befehl führt dann nichts aus. - Meldung
The migrations of this plugin are not registered with Doctrine...: Das Bundle ist nicht aktiviert odersylius_core.prepend_doctrine_migrationssteht auffalse. - Hinweis
The routes of this plugin are not imported yet: Das ist nur eine Warnung mit einem YAML-Snippet zum Kopieren. Der Befehl bricht dafür nicht ab und schreibt nie in Deineconfig/. - Läuft die Datenbank nicht auf MySQL oder MariaDB, überspringen alle Plugin-Migrationen sich selbst und werden als ausgeführt vermerkt. Die Tabellen existieren dann nicht.
Lösung: Führe zuerst bin/console doctrine:migrations:migrate aus und danach erneut den Setup-Befehl. Aktiviere das Bundle in config/bundles.php. Auf anderen Datenbankplattformen als MySQL oder MariaDB ist das Plugin nicht lauffähig (siehe Bekannte Einschränkungen). Zeigt ein Admin-Bildschirm nach einem Update einen Fehler, fehlt meist eine Tabelle: Führe den Setup-Befehl nach jedem Plugin-Update aus.
Der Eintrag in der Admin-Sidebar fehlt
Symptom: In der Admin-Navigation erscheint die Gruppe MMKreativ Plugins nicht oder ohne den Eintrag SEO Suite Pro.
Prüfen:
- Sind die Admin-Routen importiert (
@MmdSyliusSeoSuiteProPlugin/config/routes/admin.yaml)? Fehlen sie, lässt das Plugin den Menüeintrag still weg, damit nicht jede Admin-Seite fehlschlägt. - Hat das Admin-Konto Zugriff und wurde der Cache nach der Installation geleert?
Lösung: Importiere die Admin-Routen, leere den Cache und lade das Admin neu. Alle weiteren Bildschirme (Templates, Redirects, hreflang, Schema, Audit, OG-Bilder) erreichst Du über die Buttons der Channel-Einstellungen, nicht über eigene Menüpunkte.
Es werden keine hreflang-Links ausgegeben
Symptom: Im Head einer Produkt-, Kategorie- oder Startseite fehlen die <link rel="alternate" hreflang>-Tags.
Prüfen:
- Es gelten nur Produkt-, Kategorie- und Startseiten. Eigene Routen brauchen einen eigenen Provider (siehe Erweiterbarkeit).
- Mindestanzahl: Ohne mindestens
hreflang.min_alternatesAlternativen (Standard 2,x-defaultzählt nicht mit) mit unterschiedlichen URLs wird nichts ausgegeben. Ein Channel mit nur einer Sprache liefert daher keine Tags. - Selbstreferenz: Die aktuelle Seite muss selbst Teil der Menge sein, sonst entfällt die ganze Ausgabe. Ein deaktiviertes Produkt, ein Produkt ohne diesen Channel oder eine fehlende Übersetzung kann das auslösen.
- Hreflang-Einstellungen des Channels: Ist
enabledabgeschaltet, gibt es keine Ausgabe. - Gruppen: Alle Channels einer Gruppe (
group_code) brauchen einen Hostnamen. Ein Channel ohne Hostname wird aus den Alternativen der anderen weggelassen (Warnung im Log). Deaktivierte Channels und Einstellungen mitenabledaus werden ebenfalls übersprungen. - Doppelte Werte: Beanspruchen zwei Channels derselben Gruppe denselben hreflang-Wert, gewinnt die Einstellung mit der niedrigeren ID, die andere wird mit Warnung weggelassen.
- Gefilterte oder sortierte Listings, Seiten ab Seite 2 und
noindex-Seiten bekommen bewusst keine hreflang-Links.
Lösung: Pflege Hostnamen und Sprachen der Channels, passe hreflang.min_alternates und das Format an oder vergib verschiedene Sprachen je Channel. Details stehen unter hreflang.
Im JSON-LD fehlen GTIN, MPN oder Marke
Symptom: Der Product-Knoten enthält keine gtin8/gtin12/gtin13/gtin14, kein mpn oder keine brand.
Prüfen:
- Das Attribut für GTIN und MPN muss vom Typ Text sein. Ein Attribut vom Typ Integer wird bei der Validierung abgelehnt, weil 32-Bit-Zahlen lange Codes verfälschen würden. Die Marke darf Text oder Auswahl sein.
- Der Attributcode in den Schema-Einstellungen des Channels oder in
brand_attribute_code(Standardbrand) muss exakt dem Code des Produktattributs entsprechen, und das Produkt muss einen Wert für die aktuelle Sprache oder einen sprachunabhängigen Wert haben. - Eine GTIN wird nur mit 8, 12, 13 oder 14 Ziffern und gültiger Prüfziffer ausgegeben. Andernfalls entfällt sie und das Plugin loggt eine Warnung mit dem Produktcode. Leerzeichen und Bindestriche werden vorher entfernt.
- Eine MPN mit mehr als 70 Zeichen wird nicht ausgegeben.
- Im Modus
selectedder zusätzlichen Eigenschaften muss mindestens ein Attributcode gewählt sein. Es werden höchstensschema.max_additional_properties(Standard 25) Eigenschaften ausgegeben.
Lösung: Lege das Attribut als Text an, korrigiere Code und Wert und prüfe das Ergebnis in der Shop API unter structuredData. Mehr dazu unter Strukturierte Daten.
OG-Bilder: 503, Platzhalter oder normales Produktbild
Symptom: Die Karten-URL unter /seo/og/... antwortet mit 503 oder 404, leitet auf das normale Produktbild um, oder die Karte erscheint ohne das Produktbild.
Prüfen:
- Karten sind pro Channel standardmäßig abgeschaltet. In den OG-Bild-Einstellungen müssen die Karten und der Typ (Produkte, Kategorien) aktiv sein. Für einen abgeschalteten Channel oder Typ antwortet die Route mit 404, ebenso bei ungültigen Parametern.
- GD mit FreeType: Fehlt die Erweiterung
ext-gdoder FreeType, kann keine Karte gezeichnet werden. Der Besucher wird mit 302 auf das normale Bild umgeleitet, die Ursache steht als Warnung im Log. - Format:
og_image.format: webperzwingt WebP. Unterstützt GD kein WebP, ist das ein harter Fehler beim Zeichnen. Mitautowählt das Plugin WebP oder JPEG selbst. - Schriftdateien:
og_image.font_regularundog_image.font_boldmüssen lesbar sein (Standard sind die mitgelieferten DejaVu-Schriften). - Fremde Bildquellen: Ist
og_image.remote_hostsgesetzt, werden nur diese Hosts geladen. Loopback-, private und reservierte Adressen werden immer abgelehnt, auch bei lokalen CDN-Setups im Docker-Netz. Die Karte entsteht dann ohne Bild. - Zeitbudget: Überschreiten Bild und Logo zusammen
og_image.render_budget(Standard 15 Sekunden), entsteht eine abgespeckte Karte. Sie wird nur 300 Sekunden gecacht und nicht gespeichert, die nächste Anfrage zeichnet erneut. - 503 mit
Retry-After: 5bedeutet, dass gerade ein anderer Prozess dieselbe Karte zeichnet. Das legt sich von selbst. - Ein ersetztes Bild unter unverändertem Pfad oder unveränderter URL wird nicht bemerkt.
Lösung: Installiere GD mit FreeType (und WebP oder stelle format auf auto bzw. jpeg), erlaube den Bild-Host in remote_hosts oder lasse die Bilder von einer öffentlichen Adresse laden, und rendere Karten nach Importen oder Bildwechseln mit bin/console mmd:seo-suite-pro:og-image:generate vor. Alte oder verwaiste Dateien räumt mmd:seo-suite-pro:og-image:prune auf. Siehe OG-Bilder.
Das SEO-Audit hängt oder bricht ab
Symptom: Ein Audit meldet An audit of the channel "…" is already running., bleibt im Dashboard auf Running stehen oder endet mit einem Hinweis auf das Limit.
Prüfen:
- Pro Channel läuft höchstens ein Audit (Sperre über den eindeutigen
lock_key). Ein abgebrochener Lauf blockiert nur, bis sein Heartbeat älter alsaudit.stale_after_minutesist (Standard 10). Danach übernimmt der nächste Lauf ihn und schließt ihn ab. - Meldung
Stopped at the subject limit (audit.max_subjects): Der Kanal hat mehr Produkte oder Kategorien alsaudit.max_subjects(Standard 20000). Die Ergebnisse decken dann nur einen Teil des Katalogs ab, der Befehl endet mit Fehlercode. - Der Button Run audit now im Admin läuft synchron und hat ein Limit von 600 Sekunden. Große Kataloge gehören auf die Konsole.
- Meldung
The audit tables are missing: run doctrine:migrations:migrate.: Die Migration fehlt.
Lösung: Warte die Stale-Zeit ab oder verkürze sie, erhöhe audit.max_subjects und starte den Lauf per Cronjob mit bin/console mmd:seo-suite-pro:audit:run. Führe bei fehlenden Tabellen mmd:seo-suite-pro:setup aus. Siehe Audit.
Redirects greifen nicht
Symptom: Eine Weiterleitung ist angelegt, die Seite liefert aber weiter 404 oder eine falsche Zielseite.
Prüfen:
- Redirects greifen nur, wenn Symfony eine 404 auslöst (nur GET und HEAD). Eine URL, die noch eine Seite hat (zum Beispiel ein noch aktives Produkt), wird nicht umgeleitet.
- Der Vergleich nutzt den Pfad ohne Query-String und ohne Host. Groß- und Kleinschreibung sowie ein abschließender Schrägstrich spielen keine Rolle. Beachte das Locale-Präfix des Shops: Die Quelle muss den echten Pfad inklusive
/{_locale}-Teil enthalten. - Channel: Ein Redirect mit einem Channel gilt nur dort, einer ohne Channel für alle. Ist der Redirect deaktiviert, wird er ignoriert. Liegt der Redirect im falschen Channel, bleibt die 404.
- Ausgenommen sind der Admin-Pfad,
/apiund alle Pfade, die mit/_beginnen. - Ketten und Schleifen werden beim Speichern geprüft: die Meldung „Das würde eine Weiterleitungsschleife erzeugen“ verhindert Schleifen, Ketten werden auf einen Sprung abgeflacht. Das Ziel darf nicht der Quelle gleichen.
- Fehlt die Redirect-Tabelle, bleibt die 404 eine normale 404 und es wird eine Warnung geloggt.
- Beim Import prüft jede Zeile wie im Admin-Formular und wird einzeln gespeichert. Fehlerhafte Zeilen werden übersprungen.
Lösung: Lege die Quelle als echten Pfad im richtigen Channel an, prüfe Aktivierung und Meldungen beim Speichern, und führe bei fehlenden Tabellen mmd:seo-suite-pro:setup aus. Siehe Redirects.
Das 404-Log wächst
Symptom: Die Liste der 404-Pfade wird sehr lang oder enthält veraltete Einträge.
Prüfen:
- Das Log ist begrenzt: Bei
redirects.not_found_log_limit(Standard 5000) ersetzt ein neuer Pfad den am längsten nicht mehr gesehenen. Statische Dateien wie Bilder werden nicht gezählt. - Alte Zeilen entfernt nur der Befehl zum Aufräumen. Er läuft nicht von selbst.
Lösung: Plane bin/console mmd:seo-suite-pro:redirects:prune-log (Standard 90 Tage, anpassbar mit --days) als Cronjob, senke bei Bedarf das Limit oder schalte das Zählen mit redirects.log_not_found: false ab. Siehe Redirects.
Canonical oder noindex bei gefilterten Listings überrascht
Symptom: Gefilterte oder sortierte Kategorieseiten sind noindex, verweisen per Canonical auf die Grundseite, oder ein eigener Filter wird nicht erkannt.
Prüfen:
- Eine Listing-URL gilt als gefiltert, wenn mindestens ein Parameter aus
facet_parameters(Standardcriteria,sorting,limit) einen nicht leeren Wert hat.pagegehört nicht dazu. - Gefilterte Listings erhalten die Robots-Einstellung der Channel-Einstellungen (
facet_robots_index, Standard aus, undfacet_robots_follow, Standard an), also standardmäßignoindex,follow. Der Canonical zeigt auf die Grundseite, nur die Seitennummer bleibt erhalten. - Filter auf einem eigenen URL-Pfad statt im Query-String werden nicht erkannt.
Lösung: Ergänze Deine Parameter in facet_parameters (führe die Standardwerte, die Du behalten willst, mit auf) und stelle Index und Follow in den Channel-Einstellungen passend ein. Siehe Konfiguration.
Der Seitentitel bleibt unverändert
Symptom: Der <title> zeigt weiterhin den Standardtitel von Sylius.
Prüfen:
- Die Startseite behält absichtlich den Sylius-Titel (den Channel-Namen). Nur Produkt- und Kategorieseiten bekommen den Meta-Titel.
- Der Titel wird im fertigen HTML ersetzt. Das gelingt nur, wenn die Antwort
text/htmlist und das Layout genau ein<title>-Element enthält. - Ein manuell gepflegter Meta-Titel einer Übersetzung geht vor Templates. Ohne beides greift der Name des Produkts oder der Kategorie.
Lösung: Prüfe Layout und Antwort-Typ, und lege bei Bedarf ein SEO-Template an.
Bekannte Einschränkungen
- Sylius Core kennt keine CMS-Seiten, daher gibt es neben Produkten und Kategorien nichts, an dem ein Meta-Titel hängen könnte.
- Kategorieseiten bekommen eine
<meta name="description">nur, wenn das Feld der Taxon-Übersetzung gefüllt ist oder ein Beschreibungs-Template greift. Es gibt keinen automatischen Fallback auf die Kategoriebeschreibung. Nutze dafür{taxon.description}in einem Template. - Der Bildschirm für SEO-Templates braucht seine Tabelle. Ohne Migration antwortet er mit einem Fehler, Storefront und API fallen still auf den Zustand ohne Templates zurück.
- Das Sprachfeld im Template-Formular zeigt die Sprachen aller Channels. Die Prüfung gegen den gewählten Channel erfolgt erst beim Speichern.
- SEO-Templates: keine Vorschau im Formular, keine Template-Wahl je Produkt, keine bedingten Teile (ein Template mit leerem Platzhalter wird als Ganzes übersprungen). Der Hilfetext listet nur die eingebauten Platzhalter. Die Eindeutigkeit der Zeile für alle Sprachen prüft die Validierung, nicht ein Datenbankindex, weil MySQL zwei NULL-Werte in einem Unique-Index nicht als gleich behandelt.
- Eine gefilterte Liste wird am Query-String erkannt. Filter, die auf einem eigenen URL-Pfad liegen, erkennt das Plugin nicht.
- Der Titelersatz setzt voraus, dass das Layout genau ein
<title>-Element ausgibt. - Die Redirect-Bildschirme (Liste, Formular, Import, 404-Log) brauchen ihre Tabellen. Ohne Migration antworten sie mit einem Fehler, die Storefront liefert eine normale 404. Das Zählen der 404 nutzt
INSERT ... ON DUPLICATE KEY UPDATEund funktioniert nur mit MySQL oder MariaDB. - Redirects: Ketten werden beim Speichern abgeflacht, eine spätere Änderung am Kettenende wird nicht nachgezogen. Ein Redirect für alle Channels, der auf einen Redirect für nur einen Channel zeigt, bleibt zwei Sprünge lang (Schleifen werden trotzdem channelübergreifend erkannt). Es zählt nur der Pfad, nie Host oder Query-String. Slug-Änderungen per SQL- oder DQL-Massenupdate erzeugen keinen automatischen Redirect.
- hreflang: Channels werden nur verknüpft, wenn Du sie in eine Gruppe legst, das Plugin ordnet Produkte verschiedener Channels nie nach Namen zu. Produkte und Kategorien werden über ihren Code zugeordnet, eine Gruppe funktioniert also bei gemeinsamem Katalog. Die Startseite wird mit den Startseiten der Gruppen-Channels verknüpft. Der Einstellungsbildschirm braucht seine Tabelle, ohne sie gelten für Storefront und API die Standardwerte. Eine eigene Start- oder Listing-Route außer
sylius_shop_homepage,sylius_shop_product_showundsylius_shop_product_indexbraucht einen eigenen Provider. Eine Alternative ist eine absolute URL auf dem Hostnamen des Channels, ein Reverse Proxy, der das Schema ändert, muss es weiterreichen. - Audit: Es prüft Vorhandensein und Länge der Texte, Bilder nur nach Anzahl und die Robots-Einstellungen, nichts zu Alt-Texten oder Bildgrößen. Die Duplikat-Erkennung vergleicht die ausgelieferten Texte eines Typs und einer Sprache innerhalb eines Channels, nicht channelübergreifend. Sprachen ohne eigene Übersetzung eines Produkts oder einer Kategorie werden übersprungen. Ohne die Audit-Tabellen zeigt das Dashboard einen Hinweis, der Befehl meldet es und die Befundliste antwortet mit einem Fehler. Storefront und API bleiben unberührt.
- OG-Bilder: Eine Karte je Objekt und Channel in der Standardsprache des Channels. Ein Bild, das unter gleichem Pfad oder gleicher URL ersetzt wird, braucht die Neuerzeugung der Karten, weil eine Seitenanfrage das Bild nicht lesen darf. Keine Rechts-nach-links-Schriften oder komplexen Schriftsysteme und keine CJK-Zeichen in der mitgelieferten Schrift. Ohne die Tabelle der OG-Bild-Einstellungen antwortet der Bildschirm mit einem Fehler, Storefront, API und Kartenroute verhalten sich, als gäbe es keine Karte.
- Nur MySQL und MariaDB: Auf anderen Plattformen werden die Migrationen übersprungen und als ausgeführt vermerkt, die Tabellen existieren dann nicht.
FAQ
Allgemein
Erzeugt das Plugin eine Sitemap? Nein. Das Plugin enthält keinen Sitemap-Generator. Es bietet mit SitemapExclusionInterface nur die Ausschlusslogik (noindex oder Canonical auf eine andere URL) an, die ein Sitemap-Plugin aufrufen kann. Das optionale mmd/sylius-sitemap-plugin ist in der composer.json nur als Vorschlag eingetragen.
Wie viele Installationen deckt eine Lizenz ab? Eine Sylius-Installation mit allen Channels, dazu deren Entwicklungs- und Staging-Umgebung. Weitergabe ist nicht erlaubt, Updates gibt es 12 Monate ab Kauf. Maßgeblich ist die Datei LICENSE.
Ist das Plugin öffentlich? Nein, es ist ein privates Repository mit kommerzieller Lizenz.
Wo finde ich die Einstellungen? Unter MMKreativ Plugins in der Admin-Sidebar. Alle weiteren Bildschirme erreichst Du über die Buttons der Channel-Einstellungen.
Konfiguration
Wo liegt die Konfiguration? Globale Optionen stehen unter dem Schlüssel mmd_sylius_seo_suite_pro in config/packages/mmd_sylius_seo_suite_pro.yaml, alle sind optional. Einstellungen pro Channel pflegst Du im Admin und sie liegen in der Datenbank. Details in der Konfiguration.
Liest das Plugin Umgebungsvariablen? Nein. Alle Optionen kommen aus der Symfony-Konfiguration und der Datenbank.
Wie wird der Cache behandelt? Das Plugin hält Einstellungen und Templates pro Request im Speicher und setzt sie zwischen Requests zurück. Die robots.txt ist eine Stunde öffentlich cachebar, Kartenbilder ein Jahr mit immutable und einem ETag aus dem Inhalts-Hash. Nach einem Plugin-Update solltest Du mit bin/console cache:clear den Symfony-Cache leeren, weil der Serializer seine Metadaten dort ablegt.
Welche Cronjobs brauche ich? mmd:seo-suite-pro:audit:run (nächtlich), mmd:seo-suite-pro:redirects:prune-log und mmd:seo-suite-pro:og-image:prune, bei OG-Bildern zusätzlich mmd:seo-suite-pro:og-image:generate nach Importen. Den Setup-Befehl führst Du nach Installation und Updates aus, nicht per Cronjob.
Kompatibilität
Welche Sylius-Versionen werden unterstützt? Die composer.json verlangt Sylius ^2.2, PHP ^8.3 und Symfony ^7.4. Die CI baut gegen Sylius 2.2 und 2.3.
Welche API-Platform-Versionen? Die composer.json erlaubt API Platform ^4.2.1 || ^5.0. Die CI deckt Sylius 2.2 mit API Platform 4.2 sowie Sylius 2.3 mit API Platform 4.3 und 5 ab.
Welche Datenbanken? Nur MySQL 8 und MariaDB. Die CI läuft gegen MySQL 8.4.
Funktioniert das Plugin mit einem Headless-Frontend? Ja. Storefront und Shop API nutzen dieselbe SeoDataProviderInterface, sodass beide nicht auseinanderlaufen. Siehe Shop API.
Brauche ich GD für das Plugin? Nur für die optionalen OG-Bilder, mit FreeType (für WebP zusätzlich WebP-Unterstützung). Ohne GD funktioniert alles andere.