Shopware 6: SEO-URLs reparieren, wenn plötzlich eine UUID/„Hash“ am Ende hängt
Wenn Shopware Produkt-URLs plötzlich so aussehen wie …-019c98ab028c71ca92b1dba1225b3fd0, ist das fast immer ein Eindeutigkeits-Problem in der Tabelle seo_url. Diese Anleitung zeigt einen sicheren Diagnose- und Cleanup-Workflow: erst messen, dann nur „Leichen“ entfernen, anschließend neu indizieren und verifizieren.
Typische Symptome
- Produkt-URLs enden auf -32hex (wirkt wie „Hash“/UUID).
- Nach „Produkt gelöscht & neu angelegt“ werden „schöne“ Slugs nicht mehr vergeben.
- SEO-URL-Regeneration im Admin wirkt, als ob „nichts passiert“ (Queue/Worker fehlt).
- Im Zweifel ist es nicht Frontend-JS (kein #), sondern Backend-SEO-URL-Persistenz.
Ein echtes # in der URL ist ein Fragment (Frontend/JS/Anchor). Das hier ist meist ein 32-stelliger Hex-Suffix (UUID-ähnlich) aus der SEO-URL-Generierung.
Die Ursache in einem Satz
In Shopware 6 bleiben SEO-URLs in seo_url oft bestehen, auch wenn Produkte gelöscht wurden. Wenn ein neuer Artikel denselben Slug braucht, ist dieser „belegt“ – Shopware erzwingt dann Eindeutigkeit und hängt einen UUID/Hex-Suffix an.
Das ist in der Regel kein „Shop kaputt“, sondern ein Daten-/Index-Zustand. Mit einem kontrollierten Cleanup lässt es sich stabil und nachvollziehbar beheben.
Diagnose: erst messen, dann handeln
Die folgenden Abfragen sind read-only und zeigen dir, ob du „Leichen“ in seo_url hast und wie viele Canonicals noch auf UUID/Hex enden.
1) Orphans zählen: verwaiste Produkt-SEO-URLs (Leichen)
SELECT COUNT(*) AS orphan_cnt
FROM seo_url su
LEFT JOIN product p ON p.id = su.foreign_key
WHERE su.route_name = 'frontend.detail.page'
AND p.id IS NULL;
2) UUID-Canonicals zählen: wie viele Produkt-URLs enden auf -32hex?
SELECT COUNT(*) AS uuid_canonicals
FROM seo_url
WHERE route_name='frontend.detail.page'
AND is_canonical = 1
AND seo_path_info REGEXP '-[0-9a-f]{32}$';
3) Safety-Signal: wie viele saubere Canonicals existieren bereits?
SELECT COUNT(*) AS clean_slug_exists
FROM seo_url
WHERE route_name='frontend.detail.page'
AND is_canonical = 1
AND seo_path_info NOT REGEXP '-[0-9a-f]{32}$';
Cleanup: nur „Leichen“ entfernen (mit Backup)
Ziel: nicht blind alles löschen, sondern gezielt nur verwaiste Produkt-SEO-URLs entfernen, die keinen zugehörigen Datensatz in product mehr haben.
0) Backup der Tabelle (einmalig, schnell)
CREATE TABLE IF NOT EXISTS seo_url_backup_fix AS
SELECT * FROM seo_url;
1) Verwaiste Produkt-SEO-URLs löschen (nur Orphans)
Das ist der Schritt, der den „Slug-Blocker“ entfernt. Er betrifft nur Datensätze, deren Produkt nicht mehr existiert (p.id IS NULL).
DELETE su
FROM seo_url su
LEFT JOIN product p ON p.id = su.foreign_key
WHERE su.route_name='frontend.detail.page'
AND p.id IS NULL;
2) Optional: UUID-Canonicals entfernen, wenn nur wenige übrig bleiben
Wenn nach dem Orphan-Cleanup und Indexing noch eine kleine Restmenge übrig bleibt, kann man gezielt nur Canonicals mit -32hex entfernen und anschließend neu indizieren.
DELETE FROM seo_url
WHERE route_name='frontend.detail.page'
AND is_canonical = 1
AND seo_path_info REGEXP '-[0-9a-f]{32}$';
Neu indizieren: warum „im Admin passiert nix“
Moderne Shopware-Setups arbeiten stark über die Queue. Wenn kein Worker läuft, werden Jobs zwar erzeugt, aber nicht verarbeitet – dann wirkt es, als ob der Indexer „nur blinkt“.
1) Index refresh (CLI, zuverlässig)
bin/console dal:refresh:index
bin/console cache:clear
2) Queue verarbeiten (falls du async nutzt)
Wenn dein System die Indizes über Queue abarbeitet, muss ein Worker laufen. Receiver-Namen können je Setup variieren.
bin/console messenger:consume async low_priority -vv
Wenn du kurzfristig “einfach fertig werden” willst, ist dal:refresh:index (CLI) oft der robusteste Weg. Danach Cache leeren und in einem privaten Browserfenster testen.
Test-Checkliste (5 Minuten)
- Orphans: orphan_cnt sollte 0 sein.
- UUID-Canonicals: uuid_canonicals sollte gegen 0 laufen (oder stark sinken).
- Cache: Nach cache:clear im Inkognito testen (kein Browser-Cache).
- Produkt-URLs: mehrere betroffene Produkte öffnen (inkl. Varianten).
- Admin/Indexer: Wenn der Admin „nur blinkt“, Worker prüfen oder CLI-Index refresh nutzen.
Verlass dich nicht auf „es wirkt so“: Zähle die Datensätze. Wenn orphan_cnt = 0 und uuid_canonicals sinkt, bist du objektiv auf Kurs.
FAQ
Ist der Hex-Suffix wirklich ein „Hash“?
Im Alltag wird er oft „Hash“ genannt, technisch ist es meist ein UUID/Hex-Suffix, den das System zur Eindeutigkeit nutzt. Ein echtes # ist ein Fragment (Frontend).
Ist das Löschen der Orphans SEO-gefährlich?
Du entfernst damit nur SEO-URL-Einträge ohne zugehöriges Produkt. Das verhindert Slug-Blockaden. Wenn du Redirect-Historie auf gelöschte Produkte behalten willst, solltest du ein Redirect-Konzept separat pflegen. Für die reine Funktionsfähigkeit und Slug-Eindeutigkeit ist der Orphan-Cleanup der präziseste Schritt.
Warum ändert sich die URL nicht sofort?
SEO-URLs sind persistent. Wenn der canonical-Eintrag bereits existiert, bleibt er bis zur Neugenerierung/Indexing bestehen. Zusätzlich können HTTP-Cache und Browser-Cache alte URLs ausliefern.
Warum „passiert im Admin nichts“?
Wenn das System Jobs über die Queue abarbeitet, braucht es einen laufenden Worker. Ohne Worker sieht man oft nur „Indizes werden aufgebaut“, aber es wird nichts abgearbeitet. CLI-Indexing ist dann der schnellste sichere Weg.
Ich habe ein SEO-Plugin. Ist das immer schuld?
Nicht zwangsläufig. Auch ohne Plugin kann Shopware URL-Suffixe erzeugen, wenn Eindeutigkeit/Canonical-Zustand nicht sauber ist. Der Diagnose-Workflow oben trennt Plugin-Effekte von Datenbank-/Index-Zustand.
Transparenz & Einordnung
Diese Anleitung ist ein praxisorientierter Workflow aus realen Shopware-6 Debug-Sessions: Diagnose über Zähl-Queries, kontrolliertes Entfernen verwaister SEO-URLs, anschließend Indexing und messbare Verifikation. Der Kern ist nicht „ein Geheim-Command“, sondern das Prinzip: erst messen, dann minimal-invasiv handeln.
Datenbank-Operationen sollten nur mit Backup ausgeführt werden. Wenn du unsicher bist, starte mit den read-only Abfragen und dokumentiere die Counts (orphan_cnt/uuid_canonicals), bevor du löschst.