Shopware 6 Flow Builder erweitern: Custom Actions und Trigger entwickeln
Der Flow Builder ist eines der unterschätzten Werkzeuge in Shopware 6. Aus dem Backend lassen sich klickbare Automatisierungen bauen, für die in Shopware 5 noch ein Plugin nötig war. Aber sobald die Anforderung über „Tag setzen" oder „Mail verschicken" hinausgeht, stößt der Standard an seine Grenzen. Wie du Custom Actions und Custom Trigger sauber registrierst, welche Rolle die Aware-Interfaces spielen und an welchen Stellen man sich technische Schulden einkaufen kann.
1. Was der Flow Builder wirklich ist — und wo seine Grenzen liegen
Der Flow Builder hängt zwischen Symfony Events und der Business-Logik des Shops. Wenn in Shopware ein Event wie checkout.order.placed oder customer.register ausgelöst wird, prüft Shopware, ob ein Flow auf dieses Event registriert ist — und führt die konfigurierten Actions aus. Im Open-Source-Standard liefert Shopware Actions wie „Tag setzen / entfernen", „E-Mail verschicken", „Bestellstatus / Zahlungsstatus / Versandstatus ändern", „Affiliate- und Kampagnencode setzen" oder „Flow stoppen" mit. Für klassische CRM-Logik reicht das überraschend weit. Die Webhook-Action ist nicht Teil des Open-Source-Cores, sondern Teil der Shopware Commercial Extension (Evolve/Beyond) — wer einen Webhook ohne Commercial-Plan auslösen will, baut sich die Action selbst.
Grenzen erreicht man trotzdem schnell. Sobald eine Action externe APIs aufrufen muss (ERP, Kundenservice-Tools, Buchhaltung), kundenspezifische Berechnungen auslöst oder Daten aus mehreren Aggregaten kombiniert, kommt man am eigenen Code nicht vorbei. Genau dafür gibt es zwei Erweiterungspunkte, die viele Plugins ignorieren und stattdessen Subscriber bauen — was funktional ähnlich aussieht, aber dem Shop-Betreiber jede Konfigurationsmöglichkeit nimmt.
2. Trigger vs. Action: Die zwei Erweiterungspunkte
Im Flow Builder gibt es genau zwei Stellen, an denen ein Plugin sich einklinken kann. Ein Trigger ist das Ereignis, das einen Flow überhaupt startet — typischerweise ein Symfony Event, das ein Aware-Interface implementiert. Eine Action ist das, was im Flow ausgeführt wird, nachdem die Bedingungen ausgewertet wurden. Beide werden separat registriert und sind unabhängig voneinander einsetzbar.
Die Faustregel aus der Praxis: Trigger schreibt man, wenn Shopware das passende Event nicht von Haus aus wirft (zum Beispiel ein eigenes Event aus einem B2B-Freigabe-Workflow). Actions schreibt man, wenn die Aufgabe in vorhandenen Flows landen soll, aber kein Standard-Block sie abdeckt — etwa „Datensatz an SAP übergeben" oder „Webhook mit signierter Payload an unser ERP schicken". Wer beides braucht (eigener Trigger plus eigene Action), baut beides — die Schnittstelle dazwischen ist sauber und sollte nicht in einer Klasse gemixt werden.
3. Eigene Action: Vom Service zum sichtbaren Block
Eine Custom Action ist eine PHP-Klasse, die FlowAction erweitert. Sie wird im DI-Container als Service registriert und bekommt den Tag flow.action mit einem eindeutigen key. Damit landet sie automatisch in der Antwort von /api/_info/flow-actions.json und steht im Backend zur Auswahl. Die offizielle Doku zeigt die XML-Struktur im Detail.
Zwei Methoden sind Pflicht: getName() liefert den Action-Key (Konvention: action.acme.send.to.crm) und requirements() definiert die Aware-Interfaces, ohne die diese Action nicht laufen kann. Wer [OrderAware::class] zurückgibt, sagt Shopware: „Zeig mich nur in Flows, deren Trigger eine Bestellung mitbringt." Ein leeres Array macht die Action für alle Trigger sichtbar — was praktisch klingt, aber meist ein Bug-Magnet ist, weil im Action-Code dann doch eine OrderId vorausgesetzt wird, die manche Trigger nicht liefern.
Über $flow->getData($key) kommt die Action an die Daten aus dem ursprünglichen Event und zusätzliche Storer-Daten (Tag, Kunde, Kontaktformular). Das ist der entscheidende Punkt: Eine Action greift nie direkt auf das Event-Objekt zu, sondern auf einen entkoppelten Flow-State. Das ermöglicht, dass Actions später auch asynchron über die Message Queue laufen können, ohne dass die Originalobjekte serialisiert werden müssen.
4. Custom Trigger: Wenn Shopware das Event nicht liefert
Custom Trigger sind in der Praxis seltener als Custom Actions, aber genauso wichtig, wenn der eigene Workflow das Standard-Event-Repertoire sprengt. Ein Custom Trigger ist im Kern ein Symfony Event, das FlowEventAware implementiert und je nach Kontext weitere Aware-Interfaces — etwa CustomerAware oder SalesChannelAware. Sobald Shopware das Event registriert, taucht es in der Trigger-Liste im Backend auf. Patrick Königs Guide zum Event-System in Shopware 6 ist eine gute Grundlage, falls du dort noch nicht heimisch bist.
Ein typisches Beispiel: Ein B2B-Shop hat einen mehrstufigen Bestellfreigabe-Prozess. Sobald ein Vorgesetzter eine Bestellung freigibt, soll ein Flow starten, der den Vertrieb informiert. Shopware liefert dafür kein Event mit — also wirft das Plugin ein eigenes B2BOrderApprovedEvent, das FlowEventAware, OrderAware und CustomerAware implementiert. Im Backend können die Kunden des Shops dann beliebige Standard-Actions an dieses Event hängen — ohne dass der Plugin-Entwickler je wissen muss, was sie damit machen wollen.
5. Aware-Interfaces und FlowStorer: Daten, die Actions sehen dürfen
Aware-Interfaces sind das Bindeglied zwischen Trigger und Action. OrderAware verspricht eine orderId, CustomerAware eine customerId, MailAware die nötigen Daten zum Mailversand. Ein Aware-Interface ist ein Vertrag — und Actions dürfen ihre requirements() nur auf Interfaces aufbauen, die der Trigger tatsächlich erfüllt. Andernfalls landet die Action gar nicht in der Auswahl.
Wenn die eigene Action Daten braucht, die kein Standard-Aware-Interface liefert (zum Beispiel die ID eines internen Lieferanten), reicht das vorhandene System nicht. Dafür gibt es das FlowStorer-Konzept. Ein FlowStorer ist eine Klasse mit zwei Methoden: store() speichert die zusätzlichen Daten beim Trigger im Flow-State, restore() macht sie für die Action wieder verfügbar. Gepaart mit einem eigenen Aware-Interface (SupplierAware) hat man damit das volle Bild: Custom Trigger wirft Event mit eigenen Daten, FlowStorer sichert sie in der Flow-Pipeline, Custom Action liest sie wieder aus.
6. Stolperfallen: Synchron, asynchron und die Queue
Flows laufen seit Shopware 6.4.11 standardmäßig asynchron über die Symfony Messenger Queue. Das ist großartig für die Performance des Checkouts (eine Bestellung muss nicht warten, bis fünf Drittsysteme bestätigt haben), aber es bestraft jeden Code, der davon ausgeht, sofort eine Antwort zu sehen. Wer eine Custom Action schreibt, die einen Beleg in der Datenbank ablegt und gleich danach im Storefront-Code wieder lesen will, baut sich eine Race Condition, die in Tests nie auftritt und in Produktion regelmäßig zuschlägt.
Zwei Konsequenzen: Custom Actions müssen idempotent sein, weil die Queue sie im Fehlerfall wiederholt. Und sie sollten nie davon ausgehen, dass eine bestimmte Reihenfolge mit anderen Actions im selben Flow garantiert ist — Shopware sortiert sie zwar nach Reihenfolge, aber Retry-Verhalten und Parallelität können diese Ordnung im Worker-Setup brechen. Wer das im Hinterkopf hat, baut Actions, die auch unter Last sauber durchlaufen. Wer es ignoriert, debuggt später Ghosts in den Logs.
7. Fazit: Wann Flow Builder, wann eigenes Plugin
Der Flow Builder ist erste Wahl, wenn Shop-Betreiber oder Agentur-Kunden ihre Automatisierungen selbst pflegen sollen. Eine Custom Action gibt ihnen einen wiederverwendbaren Baustein, den sie mit Bedingungen, Verzweigungen und anderen Actions kombinieren können — ohne dass jeder neue Use Case einen Plugin-Update-Zyklus auslöst. Ein direkter Subscriber ist die richtige Wahl, wenn die Logik niemals optional sein darf oder Performance-kritisch im Hauptthread laufen muss.
In der Praxis ist die Antwort fast immer ein Mix: Subscriber für die harten technischen Pflichten (Cache-Invalidation, Index-Updates), Custom Actions für die fachlichen Optionen (CRM-Sync, Reporting-Hooks, Webhook-Signaturen). Wer diese Trennung sauber zieht, baut Plugins, mit denen Agentur-Kunden tatsächlich arbeiten können — statt nur Tickets für jede neue Anforderung zu schreiben.
Du brauchst eine Custom Action, die mehr macht als „Tag setzen"?
Lass uns in 30 Minuten gemeinsam auf deinen Flow schauen — wo Standard-Actions reichen, wo ein eigener Trigger sauberer ist und wie wir das deployment-stabil bauen. Kein Sales-Call.