Sylius SEO Suite Pro: Redirects
Redirects in Sylius SEO Suite Pro: 301/302, Ketten und Schleifen, automatische Redirects bei Slug-Änderung, 404-Monitoring, CSV-Import und -Export, Konsolenbefehle und Einstellungen.
Sylius SEO Suite Pro: Redirects
Redirects erhalten Rankings und Backlinks, wenn sich eine URL ändert. Ein Redirect beantwortet die Anfrage nach einem alten Pfad mit einem 301 oder 302 auf den neuen. Du pflegst sie von Hand, sie entstehen automatisch bei einer Slug-Änderung, und Du kannst sie per CSV importieren und exportieren. Zusätzlich zählt das 404-Monitoring, welche Pfade ins Leere laufen.
Überblick
- Ein Redirect wird nur ausgeliefert, wenn der Shop für den Pfad keine eigene Seite hat. Bestehende Seiten kosten nichts.
- Pro Anfrage gibt es höchstens einen Sprung (One Hop). Ketten werden deshalb beim Speichern geglättet.
- Pfade werden ohne Beachtung der Groß- und Kleinschreibung verglichen.
- Redirects gelten für den Storefront. Es gibt keine API-Ressource dafür (siehe Abschnitt Shop API / Headless weiter unten).
Ein Redirect im Detail
| Feld | Beschreibung |
|---|---|
Alter URL-Pfad (source) |
Der angefragte Pfad inklusive Locale-Präfix des Shops, zum Beispiel /en_US/products/old-name. Beim Speichern normalisiert: führender Slash, kein Host, kein Query-String, kein Fragment, kein abschließender Slash (außer beim Root /). Eine eingefügte vollständige URL wird auf ihren Pfad gekürzt. Maximal 255 Zeichen. |
Ziel (target) |
Ein Pfad im Shop (beginnt mit genau einem /) oder eine absolute http(s)://-URL. Mehr nicht. Maximal 2048 Zeichen. |
Redirect-Typ (status) |
301 (Standard) oder 302. Andere Werte werden abgelehnt. |
| Channel | Ein einzelner Channel oder leer für alle Channels. |
| Aktiv | Ein deaktivierter Redirect bleibt gespeichert, wird aber nicht ausgeliefert und nimmt an keiner Schleifenprüfung teil. |
Pro Pfad und Channel gibt es genau einen Redirect. Ein Redirect für den Channel des Besuchers hat Vorrang vor einem Redirect für alle Channels.
Pfade sind nicht case-sensitiv:
/Sofaund/sofasind derselbe Pfad. Sonst wird nichts zusammengefasst,/überund/uberoder/straßeund/strassebleiben verschiedene Pfade.
Die Liste zeigt zusätzlich Trefferzähler, Zeitpunkt des letzten Treffers und die Herkunft (Manuell, Automatisch bei Slug-Änderung, Import).
Wann ein Redirect greift
graph TD
A["Anfrage an den Storefront"] --> B{"Shop hat eine Seite?"}
B -->|"Ja"| C["Seite wird normal ausgeliefert"]
B -->|"Nein, 404"| D{"GET oder HEAD, kein Admin, keine API, kein Pfad mit Unterstrich?"}
D -->|"Nein"| E["Normale 404-Seite, nichts wird gezählt"]
D -->|"Ja"| F{"Aktiver Redirect für Pfad und Channel gefunden?"}
F -->|"Ja"| G["Trefferzähler erhöhen"]
G --> H["301 oder 302 auf das Ziel, Query-String wird angehängt"]
F -->|"Nein"| I{"404-Log aktiv?"}
I -->|"Ja"| J["Pfad im 404-Log zählen, dann normale 404-Seite"]
I -->|"Nein"| K["Normale 404-Seite"]
Behandelt werden nur GET- und HEAD-Anfragen des Storefronts. Ausgenommen sind:
- der Admin-Bereich (Pfad aus
sylius_admin.path_name, standardmäßig/admin) - die API (
/api) - interne Symfony-Routen, also alles, was mit
/_beginnt (Profiler, Web-Debug-Toolbar, Fragmente)
Kosten pro Anfrage:
| Fall | Datenbankzugriffe |
|---|---|
| Normale, existierende Seite | keine |
| 404 mit Redirect | ein Lookup und ein UPDATE (Trefferzähler, letzter Treffer) |
| 404 ohne Redirect | ein Lookup, plus Zählung im 404-Log |
Fehlt die Redirect-Tabelle, schlägt der Lookup fehl oder ist ein gespeichertes Ziel ungültig, sieht der Besucher die normale 404-Seite. Der Fehler wird geloggt, es gibt nie einen 500er.
Query-String
Der Query-String der Anfrage wird so angehängt, wie der Besucher ihn gesendet hat, wenn das Ziel ein Pfad ohne eigenen Query-String ist. Kampagnenparameter überleben den Redirect:
| Anfrage | Ziel | Weiterleitung nach |
|---|---|---|
/en_US/old?utm_source=mail |
/en_US/new |
/en_US/new?utm_source=mail |
/en_US/old?utm_source=mail |
/en_US/new?ref=1 |
/en_US/new?ref=1 (eigener Query bleibt) |
/en_US/old?utm_source=mail |
https://example.com/new |
https://example.com/new (absolutes Ziel erhält nichts) |
Nicht-ASCII-Zeichen im Ziel (Umlaute, ein verirrtes Leerzeichen) werden im Location-Header prozentkodiert.
301 wird von Browsern zwischengespeichert und von Suchmaschinen übernommen. Nimm 302 für alles, was nur vorübergehend gilt.
Ketten und Schleifen
Beim Speichern im Admin und beim Import wird geprüft und geglättet:
- Das Ziel darf nicht der Quellpfad sein. Folgt man den vorhandenen aktiven Redirects vom Ziel aus und landet wieder bei der Quelle (A nach B und B nach A, oder ein längerer Kreis), erscheint ein Formularfehler und nichts wird gespeichert. Nach zehn Sprüngen gilt eine Kette ebenfalls als Zyklus.
- Neuer Redirect X nach Y, während Y nach Z existiert: X zeigt direkt auf Z.
- Existiert W nach X und Du legst X nach Y an, wird W auf Y umgebogen.
- Ist ein Redirect auf dem Weg ein 302, wird der resultierende Redirect ebenfalls ein 302.
- Es zählen nur aktive Redirects im selben Channel. Ein Redirect für alle Channels deckt jeden Channel ab, einer für einen Channel nur diesen.
graph LR
A["Vorher: /a"] -->|"301"| B["/b"]
C["Nachher: /a"] -->|"301"| E["/c"]
D["Nachher: /b"] -->|"301"| E
Das Beispiel zeigt einen neuen Redirect von /b nach /c, während /a schon auf /b zeigt: /b zeigt künftig auf /c, und der vorhandene Redirect von /a wird ebenfalls auf /c umgebogen. Der Besucher braucht immer nur einen Sprung.
Die Glättung ist eine Momentaufnahme beim Speichern. Änderst Du später das Ziel eines Redirects, behalten Redirects, die darauf zeigen, das alte Ziel. Ein Redirect für alle Channels wird nur über andere Redirects für alle Channels geglättet. Zeigt er auf einen Pfad, den ein einzelner Channel anderswohin umleitet, macht der Besucher in diesem Channel zwei Sprünge.
Ein Redirect für alle Channels wird gegen die Redirects jedes Channels auf Schleifen geprüft. Gibt es in einem Channel
/bnach/a, ist/anach/bfür alle Channels ein Formularfehler.
Automatische Redirects bei Slug-Änderung
Ändert sich der Slug einer Produkt- oder Kategorie-Übersetzung, legt das Plugin automatisch einen 301 von der alten auf die neue URL an (Herkunft Automatisch). Das gilt für jede geänderte Locale und jeden Channel, in dem die Seite angezeigt wird und der die Locale anbietet. Ein Produkt zählt in seinen eigenen Channels, eine Kategorie in allen Channels. Die Pfade baut der Shop-Router aus den Routen sylius_shop_product_show und sylius_shop_product_index, das Locale-Präfix Deiner Routen wird also übernommen.
Beispiel: Du änderst den Slug eines Produkts von old auf new. Es wird in den Channels web und outlet verkauft, beide bieten en_US an. Danach existieren zwei automatische Redirects:
| Quelle | Ziel | Status | Channel | Herkunft |
|---|---|---|---|---|
/en_US/products/old |
/en_US/products/new |
301 | web |
Automatisch |
/en_US/products/old |
/en_US/products/new |
301 | outlet |
Automatisch |
Die Schreibweise der Pfade hängt von den Routen Deines Shops ab. Zeigte vorher bereits ein Redirect von /en_US/products/older auf /en_US/products/old, wird er auf /en_US/products/new umgebogen, damit der Besucher bei einem Sprung bleibt.
Abschalten:
# config/packages/mmd_sylius_seo_suite_pro.yaml
mmd_sylius_seo_suite_pro:
redirects:
auto_on_slug_change: false
Das Verhalten im Einzelnen:
- Benennst Du zurück (
anachbund späterbnacha), wird der Redirect mit der neuen URL als Quelle entfernt, statt eine Schleife zu bauen. Ein Redirect, der die alte URL schon als Quelle hat, wird überschrieben. Redirects, die auf die alte URL zeigten, folgen der neuen. So bleiben wiederholte Umbenennungen bei einem Sprung. - Eine Änderung, die sich nur in der Groß- und Kleinschreibung unterscheidet, erzeugt nichts.
- Deaktivierte Produkte und Kategorien bekommen den Redirect ebenfalls. Er greift, sobald sie wieder aktiv sind.
- Der Listener sammelt die Änderung beim Flush von Doctrine und schreibt den Redirect danach. Jeder Fehler wird geloggt und verschluckt, das Speichern des Produkts oder der Kategorie wird nie verhindert. Wird der Flush zurückgerollt, entsteht kein Redirect.
- Kinder einer Kategorie brauchen nichts: Sylius speichert den vollständigen Permalink in jeder Taxon-Übersetzung und schreibt die Kinder bei einer Änderung des Eltern-Slugs nicht um. Schreibt Dein Shop sie selbst über die ORM um, ist jede geänderte Übersetzung eine eigene Slug-Änderung und bekommt ihren Redirect.
Slugs, die per DQL-/SQL-Bulk-Update oder direktes SQL geändert werden, lösen keine Doctrine-Listener aus und erzeugen keinen Redirect. Das Umbenennen tausender Produkte in einem Flush schreibt entsprechend viele Zeilen. Das ist ein einmaliger Aufwand der Änderung, kein Aufwand für Seitenaufrufe.
404-Monitoring
Ein 404 ohne passenden Redirect wird pro Pfad und Channel gezählt: Pfad, Anzahl der Anfragen, erster und letzter Zeitpunkt und der letzte Referrer (auf 255 Zeichen gekürzt). Die Seite 404-Log listet die Pfade, meistgefragte zuerst.
Das Wachstum ist begrenzt:
- Asset-ähnliche Pfade werden nicht gezählt, nämlich Dateiendungen wie
css,js,json,xml,txt, Bilder (png,jpg,webp,svg,icound weitere), Schriften, Video und Audio,pdf,zipsowie Sondierungs-Endungenphp,asp,aspx,jspundcgi. - Pfade über 255 Zeichen, ungültiges UTF-8 und Pfade mit Steuerzeichen werden nicht gezählt.
- Das Log hält etwa
redirects.not_found_log_limitZeilen (Standard 5000). Ist es voll, ersetzt ein neuer Pfad die Zeile, die am längsten nicht mehr gesehen wurde. So zeigt das Log immer, was gerade angefragt wird. Zählen und Einfügen sind nicht atomar, parallele Anfragen können das Limit um ein paar Zeilen überschreiten.
Alte Zeilen entfernst Du per Cronjob:
bin/console mmd:seo-suite-pro:redirects:prune-log # seit 90 Tagen nicht gesehen
bin/console mmd:seo-suite-pro:redirects:prune-log --days=30
# Crontab: täglich um 03:30 Uhr
30 3 * * * cd /var/www/shop && bin/console mmd:seo-suite-pro:redirects:prune-log --days=60
--days muss eine ganze Zahl von 0 aufwärts sein. Das Zählen schaltest Du mit redirects.log_not_found: false ab. Ist die Tabelle noch nicht migriert, wird das Zählen stillschweigend übersprungen.
Aus dem 404-Log heraus legst Du mit der Zeilenaktion Create redirect direkt einen Redirect an: Das Formular öffnet sich mit Pfad und Channel vorausgefüllt. Sobald Du einen Redirect für den Pfad speicherst, verschwindet die Zeile aus dem Log. Das Audit-Dashboard zeigt zusätzlich die zehn meistgefragten 404-Pfade ohne Redirect, siehe SEO-Audit.
CSV-Import und -Export
Das Format hat vier Spalten, die erste Zeile nennt die Spaltennamen:
source,target,status,channel
/en_US/products/old-name,/en_US/products/new-name,301,
/en_US/old-page,https://example.com/new-page,302,shop
/en_US/summer-sale,/en_US/sale,,outlet
| Spalte | Pflicht | Beschreibung |
|---|---|---|
source |
ja | Alter Pfad, wird wie im Formular normalisiert |
target |
ja | Zielpfad oder absolute http(s)-URL |
status |
nein | 301 oder 302. Leer bedeutet 301. Alles andere ist ein Zeilenfehler. |
channel |
nein | Channel-Code. Leer bedeutet alle Channels. Ein unbekannter Code ist ein Zeilenfehler. |
Der Import ist tolerant gegenüber dem, was Tabellenkalkulationen erzeugen:
- UTF-8 mit oder ohne Byte Order Mark. Ist die Datei kein gültiges UTF-8, wird sie als Windows-1252 gelesen.
- Komma, Semikolon oder Tab als Trennzeichen, erkannt an der Kopfzeile.
- Beliebige Reihenfolge der Spalten, Groß- oder Kleinschreibung der Spaltennamen egal, Leerzeilen werden übersprungen.
Jede Zeile durchläuft dieselbe Prüfung wie das Admin-Formular, einschließlich Ketten- und Schleifenregeln, und wird einzeln gespeichert. Eine spätere Zeile sieht also die früheren, und eine fehlerhafte Zeile kostet nicht die übrigen. Fehlerhafte Zeilen werden mit Zeilennummer gemeldet und übersprungen. Importierte Redirects haben die Herkunft Import.
Bestehende Redirects werden nicht überschrieben. Eine Zeile für einen Pfad und Channel, den es schon gibt, ist ein Fehler. Lösche oder bearbeite den vorhandenen Redirect vorher.
Grenzen: 1 MB Dateigröße und 2000 Datenzeilen. Eine größere Datei wird ganz abgelehnt. Ab Zeile 2001 bricht der Import mit einer Meldung ab, die bis dahin gelesenen Zeilen bleiben gespeichert. Fehlt in der Kopfzeile source oder target, wird nichts importiert.
Import und Export bedienen
Admin
- Öffne SEO Suite Pro > Redirects.
- Klicke auf Import und wähle die CSV-Datei.
- Nach dem Absenden zeigt der Bildschirm die Zahl der importierten Redirects und eine Liste der abgelehnten Zeilen mit Zeilennummer.
- Der Export lädt über die Schaltfläche Export die Datei
redirects.csvherunter.
Konsole
bin/console mmd:seo-suite-pro:redirects:import redirects.csv
bin/console mmd:seo-suite-pro:redirects:export redirects.csv
bin/console mmd:seo-suite-pro:redirects:export > redirects.csv
Der Import gibt jede abgelehnte Zeile als line N: ... aus und meldet am Ende, wie viele Redirects importiert und wie viele Zeilen abgelehnt wurden. Gab es mindestens einen Zeilenfehler, endet der Befehl mit einem Fehlercode, die gültigen Zeilen sind trotzdem gespeichert. Der Export schreibt ohne Dateiargument auf die Standardausgabe.
Der Export enthält nur
source,target,statusundchannel, und zwar alle Redirects, auch deaktivierte. Der Aktiv-Schalter, die Herkunft und der Trefferzähler werden nicht mitexportiert. Ein Reimport setzt alle Redirects auf aktiv.
Admin-Bereich
Das Plugin hat einen einzigen Seitenleisten-Eintrag (Gruppe MMKreativ Plugins > SEO Suite Pro). Alle weiteren Bildschirme erreichst Du über Schaltflächen:
| Bildschirm | Erreichbar über | Aktionen |
|---|---|---|
| Redirects | SEO Suite Pro > Schaltfläche Redirects | Anlegen, Bearbeiten, Löschen, Sammellöschen |
| 404-Log | Redirects > Schaltfläche 404 log | Redirect erstellen (vorausgefüllt), Löschen, Sammellöschen. Kein Anlegen oder Bearbeiten. |
| Import | Redirects > Schaltfläche Import | CSV hochladen |
| Export | Redirects > Schaltfläche Export | CSV herunterladen |
Die Redirect-Liste lässt sich nach Quelle und Ziel durchsuchen und nach Channel (einschließlich der Zeilen für alle Channels), Herkunft und Aktiv filtern. Sortieren kannst Du unter anderem nach Treffern und letztem Treffer. Das 404-Log durchsuchst Du nach Pfad und Referrer und filterst es nach Channel. Das 404-Log ist standardmäßig nach Anzahl der Anfragen absteigend sortiert.
Die Listen sind Sylius-Grids (mmd_sylius_seo_suite_pro_plugin_admin_seo_redirect und mmd_sylius_seo_suite_pro_plugin_admin_seo_not_found_log).
Konsolenbefehle
| Befehl | Zweck | Optionen |
|---|---|---|
mmd:seo-suite-pro:redirects:export [file] |
Alle Redirects als CSV | file optional, sonst Standardausgabe |
mmd:seo-suite-pro:redirects:import file |
CSV importieren, gleiche Prüfung wie im Admin | file Pflicht |
mmd:seo-suite-pro:redirects:prune-log |
Alte Zeilen aus dem 404-Log löschen | --days / -d, Standard 90 |
Der Befehl prune-log gehört in einen Cronjob, Export und Import sind manuelle Werkzeuge.
Einstellungen
Alle Schlüssel liegen unter mmd_sylius_seo_suite_pro.redirects. Mehr zur Konfiguration findest Du unter Konfiguration.
| Einstellung | Standard | Beschreibung |
|---|---|---|
redirects.auto_on_slug_change |
true |
Legt bei einer Slug-Änderung an Produkt oder Kategorie automatisch einen 301 an |
redirects.log_not_found |
true |
Zählt Pfade, die mit 404 enden und keinen Redirect haben |
redirects.not_found_log_limit |
5000 |
Obergrenze der Zeilen im 404-Log (mindestens 1) |
# config/packages/mmd_sylius_seo_suite_pro.yaml
mmd_sylius_seo_suite_pro:
redirects:
auto_on_slug_change: true
log_not_found: true
not_found_log_limit: 5000
Sicherheit
- Ziele und Quellen werden validiert: Das Ziel ist ein Pfad mit genau einem führenden
/oder einehttp(s)://-URL mit Host und ohne Zugangsdaten. Kein anderes Schema (javascript:,data:,ftp:), kein//host, kein Leerraum, kein Steuerzeichen, kein Backslash. Dadurch kann ein Zeilenumbruch nie einen Header aufspalten. - Die Bildschirme liegen hinter dem Admin-Login. Anlegen, Bearbeiten, Löschen und Sammellöschen tragen das CSRF-Token von Sylius, das Import-Formular ein eigenes. Der Export ist ein schreibgeschütztes
GET. - Die hochgeladene Datei wird nur aus dem temporären PHP-Upload gelesen und nie verschoben, gespeichert oder ausgeführt.
- Beim Export werden Zellen, die eine Tabellenkalkulation als Formel lesen würde, mit einem Hochkomma geschützt.
Shop API / Headless
Redirects sind eine Sache der HTTP-Ebene, wie die robots.txt: Sie beantworten die Anfrage, bevor eine Seite gerendert wird. Der Listener behandelt nur Storefront-Anfragen, die API (/api) ist ausgenommen, und es gibt keine API-Ressource für Redirects. Ein Headless-Frontend auf einem anderen Host muss seine 404-Seiten selbst behandeln, denn Redirects werden nur auf dem Pfad des Shop-Hosts gesucht. Sie lassen sich aber per CSV-Export auslesen und in das Frontend übernehmen.
Fehlerbilder
| Symptom | Ursache und Lösung |
|---|---|
| Der Redirect greift nicht | Der Pfad existiert im Shop als echte Seite, Redirects greifen nur bei 404. Prüfe außerdem Aktiv, Channel und die Schreibweise samt Locale-Präfix. |
| Zeile im Import abgelehnt, bereits vorhanden | Pfad und Channel existieren schon, vorhandene Redirects werden nicht überschrieben. |
| Formularfehler zur Schleife | Die Kette führt zurück zur Quelle, siehe Ketten und Schleifen. |
| Nach Slug-Änderung kein Redirect | Auto-Redirect abgeschaltet, der Channel bietet die Locale nicht an, oder der Slug wurde per SQL-Bulk-Update geändert. |
| Das Log füllt sich nicht | redirects.log_not_found ist aus, der Pfad ist Asset-ähnlich, oder die Migration fehlt (mmd:seo-suite-pro:setup). |
Weitere Hilfe: Fehlerbehebung und Technische Details.