Benutzerdefinierte Trigger
Erstellen Sie eigene Shopify Flow-Trigger mit JavaScript: Vorher-Nachher-Werte prüfen und nur bei echten Zustandsübergängen auslösen.
Die integrierten Trigger decken die Änderungen ab, die für die meisten Shops von Bedeutung sind. Ein benutzerdefinierter Trigger deckt den Rest ab: Sie wählen ein Ereignis aus Shopify aus, schreiben ein paar Zeilen JavaScript, um zu entscheiden, ob es relevant ist und welche Daten gesendet werden sollen, und schon wird daraus ein Trigger, den Sie in Shopify Flow verwenden können.
Drei Probleme, die damit gelöst werden können, die ein integrierter Trigger jedoch nicht bewältigen kann:
- Führen Sie die Aktion nur unter Ihren Bedingungen aus. „Nur wenn eine Bestellung über 500 EUR das Tag
viperhält“ ist eine einzige Codezeile - anstelle eines Workflows, der bei jeder Bestellung ausgeführt wird und anschließend filtert. - Wenden Sie die „Fire on a transition“-Regel an, nicht die „Fire on a state“-Regel. Ihr Code erkennt den Wert vor und nach der Änderung, sodass Aussagen wie „Der Status hat sich von ‚Entwurf‘ zu ‚aktiv‘ geändert“ oder „Der Lagerbestand ist unter 5 gefallen“ möglich sind. Eine Bedingung, die auf dem aktuellen Wert basiert, kann dies nicht ausdrücken.
- Senden Sie genau die Felder, die Sie benötigen. Passen Sie das Ereignis an die Werte an, die Ihr Workflow tatsächlich verwendet, anstatt diese einzeln wieder auszulesen.
Ein benutzerdefinierter Trigger benötigt nicht einmal ein Shopify-Ereignis: Er kann auch nach einem Zeitplan ausgeführt werden und selbst entscheiden, was sich geändert hat.
So funktioniert es
- Wählen Sie aus, wodurch der Vorgang ausgelöst werden soll: ein einzelnes Shopify-Ereignis oder ein Zeitplan.
- Wählen Sie für ein Ereignis das Ereignis aus, auf das es reagiert - jedes Shopify-Ereignis, das die App bereits empfängt - oder beginnen Sie mit einer Vorlage, die das Ereignis auswählt und den Code ausfüllt.
- Erfassen Sie eine echte Payload. Nehmen Sie diese Änderung in Ihrem Shop vor, und die App erfasst den genauen Ereignisinhalt.
- Schreiben Sie eine Transformation - geben Sie ein Objekt zurück, um den Vorgang auszulösen, und geben Sie
nullzurück, um ihn zu überspringen. - Testen Sie dies anhand des erfassten Ereignisses und sehen Sie genau, welche Daten Ihr Workflow erhalten würde.
- Schalten Sie es ein.

Die Transformation schreiben
Ihr Trigger ist ein JavaScript-Modul, das eine Funktion namens transform exportiert. Diese Funktion nimmt vier Argumente entgegen:
payload- der Rohtext des Ereignis-Shopify-Körpers, genau so, wie er eingeht.topic- welches Ereignis ausgelöst wurde, zum BeispielPRODUCTS_UPDATE.shop- Ihre MyShopify-Domain.ctx-ctx.log(...)gibt eine Meldung im Protokollbereich neben dem Editor aus,ctx.shopify(...)führt eine Admin-GraphQL-Abfrage aus undctx.fetch(...)ruft eine URL im öffentlichen Internet auf.
Was Sie zurückgeben, entscheidet darüber, was geschieht:
- Geben Sie ein Objekt zurück, woraufhin der Trigger ausgelöst wird und dieses Objekt übergibt.
- Geben Sie
nullzurück, und das Ereignis wird übersprungen. So funktioniert die Filterung - es muss keine separate Filtersprache erlernt werden. - Lassen Sie die Datei leer, dann wird sie bei jedem Ereignis dieses Typs ausgelöst.
/**
* Only fire for high-value orders carrying the vip tag.
*/
export async function transform(payload, topic, shop, ctx) {
const total = parseFloat(payload.total_price || "0");
const tags = (payload.tags || "").split(",").map(t => t.trim());
if (total < 500) return null;
if (!tags.includes("vip")) return null;
ctx.log("firing for", payload.name, total);
return {
orderId: payload.admin_graphql_api_id,
orderNumber: payload.name,
total,
currency: payload.currency,
customerEmail: payload.email,
};
}Der Wert vor der Änderung
Shopify
Bei Produkt-, Bestell- und Kundenaktualisierungen listet payload._changes alle nachverfolgten Felder auf, die durch diese Aktualisierung geändert wurden, jeweils mit den Angaben oldValue und newValue:
- Produkte:
title,handle,description,status,vendor,productType,tags - Bestellungen:
financialStatus,fulfillmentStatus,tags,note,lineItemsundcustomAttributes.<name> - Kunden:
tags,note,state(ENABLED,DISABLED,INVITED,DECLINED)
Die Liste ist leer, wenn die Aktualisierung außerhalb dieser Felder erfolgte - beispielsweise bei einer Änderung des Inventars - oder wenn die App den Datensatz zum ersten Mal sieht. Das Beispielereignis, das Sie im Editor erfassen, zeigt das Feld an, sodass Sie dessen tatsächliche Struktur erkennen können, bevor Sie Daten darin speichern.
/**
* Fire only when a product BECOMES active - not on every later edit of an
* active product, which is what a condition on the current status would do.
*/
export async function transform(payload, topic, shop, ctx) {
const change = (payload._changes || []).find((c) => c.field === "status");
if (!change) return null;
if (change.oldValue !== "draft" || change.newValue !== "active") return null;
return {
productId: payload.admin_graphql_api_id,
title: payload.title,
oldStatus: change.oldValue,
newStatus: change.newValue,
};
}Die spezifischeren Ereignisse verfügen über eigene alte und neue Werte, sodass Sie dort _changes nicht benötigen: Eine Preisänderung hat oldPrice, newPrice und percentChange; eine Inventaränderung hat _oldAvailable, _newAvailable und _delta; eine Änderung der Metafelder hat previousValue neben metafield.value.
Beginnen Sie mit einer Vorlage
Wenn im Editor „Fires on“ ausgewählt ist, wählt die Option „Aus einer Vorlage beginnen“ das Ereignis aus und fügt funktionierenden Code ein. Bearbeiten Sie die Konstanten am Anfang, testen Sie das Ergebnis und speichern Sie anschließend. Jede Vorlage liest einen Wert vor und nach der Änderung aus:
- Ein Produkt-, Bestell- oder Kundenfeld hat sich von einem Wert auf einen anderen geändert - der Status wechselte von „Entwurf“ zu „aktiv“, eine Bestellung wurde bezahlt, ein Konto wurde freigeschaltet.
- Der Preis ist um mehr als N Prozent gesunken - eine echte Preissenkung, nicht jede Preisänderung.
- Der Lagerbestand ist unter einen Schwellenwert gefallen - es wird einmal ausgelöst, und zwar in dem Moment, in dem der Lagerbestand die Grenze überschreitet, nicht bei jedem Verkauf, solange der Bestand bereits niedrig ist.
- Die Zahl eines Produkt-Metafelds hat einen Schwellenwert überschritten - eine Bewertung ist unter 3 gefallen, eine Marge ist über 40 gestiegen.
- Bestellung, die von einem Großkunden bezahlt wurde - liest die Gesamtumsatzsumme des Kunden in Ihren Shops aus und löst erst ab dem von Ihnen festgelegten Betrag aus.

Abrufen zusätzlicher Daten mit ctx.shopify
Webhook-Inhalte enthalten ausschließlich die Felder, die von Shopify gesendet werden. Wenn Sie weitere Informationen benötigen - beispielsweise die Anzahl der Bestellungen eines Kunden, das Inventar einer Variante oder ein Metafeld -, fragen Sie die Admin-API direkt aus Ihrer Transformation ab:
export async function transform(payload, topic, shop, ctx) {
const data = await ctx.shopify(`
query($id: ID!) {
customer(id: $id) { numberOfOrders tags }
}
`, { id: payload.customer.admin_graphql_api_id });
// Only fire for repeat customers
if (data.customer.numberOfOrders < 5) return null;
return {
orderId: payload.admin_graphql_api_id,
orderCount: data.customer.numberOfOrders,
};
}Die Funktion gibt den data der Abfrage zurück und löst einen Ausnahmetyp aus, falls die Abfrage Fehler enthält, sodass in Ihrem Test ein Fehler angezeigt wird, anstatt stillschweigend keine Ausgabe zu erzeugen.
Drei wichtige Grenzwerte:
- Bis zu 10 Aufrufe pro Durchlauf. Für die Anreicherung reicht eine Handvoll aus; bei mehr als dieser Anzahl ist in der Regel eine Schleife erforderlich. Rufen Sie die benötigten Daten nach Möglichkeit in einer einzigen Abfrage ab.
- Die App liest, sie schreibt nicht. Sie nutzt die von Ihnen erteilten Berechtigungen, und die App fordert stets nur Lesezugriff an. Eine Abfrage von Bestelldaten schlägt fehl, sofern auf der Seite „Berechtigungen“ kein Zugriff auf Bestelldaten gewährt wurde. Wenn Sie etwas in Ihrem Shop ändern möchten, tun Sie dies in den Shopify Flow-Aktionen, die auf den Trigger folgen.
- Die Anmeldedaten Ihres Shops gelangen niemals in Ihren Code. Die Abfrage wird von der App in Ihrem Auftrag ausgeführt, sodass es in der Sandbox kein Zugriffstoken gibt, das offengelegt werden könnte.
ctx.fetch(url, options) Funktioniert wie die Funktion fetch des Browsers für alle Inhalte im öffentlichen Internet: den Bestands-Feed eines Anbieters, einen Wechselkurs oder Ihre eigene API. Interne und private Netzwerkadressen werden abgelehnt. Falls Ihr Trigger-Code auf GitHub gespeichert ist, fügen Sie darin keinen API-Schlüssel ein.
Trigger, die nach einem Zeitplan ausgeführt werden
Shopify Flow reagiert, wenn etwas geschieht. Es kann nicht reagieren, wenn nichts geschieht, und es kann nichts außerhalb Ihres Shops erkennen. Wählen Sie hierfür unter „Was löst die Ausführung aus?“ die Option „Nach Zeitplan“ aus. Hinter einem solchen Trigger steht kein Shopify-Ereignis: Ihr Code wird in bestimmten Intervallen ausgeführt - von alle 30 Sekunden bis hin zu einmal täglich - und entscheidet selbst, was als Änderung gilt.
Es handelt sich um dieselbe Funktion transform, jedoch mit einer anderen payload und einem anderen Rückgabewert:
payload.state- den Wert, den Ihr Code beim letzten Durchlauf alsstatezurückgegeben hat. Beim ersten Durchlauf ist diesnull.payload.nowsowiepayload.lastRunAt- Zeitstempel.- Geben Sie
{ state, events }zurück: den neuen zu speichernden Status (bis zu 32 KB) und eine Liste der auszulösenden Ereignisse (bis zu 100 pro Durchlauf). Jedes Ereignis löst den benutzerdefinierten Trigger einmal aus; dieresourceIdeines Ereignisses, sofern Sie eine festgelegt haben, wird zur Datensatz-ID in Shopify Flow. Geben Sienullzurück, wenn nichts zu melden ist.
Stellen Sie sicher, dass der Code beim ersten Durchlauf lediglich Daten erfasst, aber niemals Trigger aktiviert. Beim ersten Durchlauf hat Ihr Code noch keinen Vergleichswert, sodass alles neu erscheint. Speichern Sie die erfassten Daten und geben Sie keine Ereignisse zurück; durch das Aktivieren des Triggers werden Ihre Workflows niemals überlastet. Alle Vorlagen verfahren so.

// Fires when a value at a JSON URL changes, with the value before and after.
const URL = "https://api.example.com/stock/1042"
export async function transform(payload, topic, shop, ctx) {
const res = await ctx.fetch(URL, { headers: { accept: "application/json" } })
if (!res.ok) throw new Error("The URL answered with HTTP " + res.status)
const value = String((await res.json()).stock)
// The first run only remembers the value.
const previous = payload.state ? payload.state.value : undefined
if (previous === undefined || previous === value) return { state: { value } }
return {
state: { value },
events: [{ oldValue: previous, newValue: value }],
}
}Vorlagen für geplante Trigger unter „Von einer Vorlage aus starten“ auf der Karte „Zeitplan“:
- Produkt, Bestellung oder Kunde seit N Tagen nicht aktualisiert - veraltete Katalogbewertungen, festgefahrene Bestellungen, Rückgewinnung. Jeder Datensatz wird einmal pro Ruhephase ausgelöst, und bereits überfällige Einträge zum Zeitpunkt der Aktivierung werden nicht alle auf einmal ausgelöst.
- Ein Wert außerhalb von Shopify wurde geändert - ein Lieferantenbestandsfeed, ein Wechselkurs, eine Preisliste, wobei es sich bei den Zahlen um die Differenz und den Prozentsatz handelt.
- Neuer Eintrag in einem RSS- oder Atom-Feed - Anbieter-News, ein Produktverzeichnis-Feed, eine Statusseite.
- Keine Bestellungen seit N Stunden - ein „Herzschlag“ für Ihren Shop. Wird einmal ausgelöst, wenn keine Bestellungen mehr eingehen, und einmal, wenn wieder Bestellungen eingehen.
Mit „Test“ wird Ihr Code einmal ausgeführt, ohne dass dabei etwas ausgelöst oder der Zustand gespeichert wird, sodass Sie ihn so oft ausführen können, wie Sie möchten.
Verwendung in Shopify Flow
Jeder benutzerdefinierte Trigger wird in Shopify Flow als derselbe Trigger angezeigt: „Benutzerdefinierter Trigger“. Fügen Sie ihn einem Workflow hinzu und fügen Sie anschließend die Bedingung „Trigger-Handle entspricht dem Handle Ihres Triggers“ hinzu.
Dieser Name wird auf der Seite des Triggers angezeigt und ändert sich niemals, selbst wenn Sie den Trigger umbenennen - so bleibt Ihr Workflow weiterhin funktionsfähig.
Jeder Schlüssel, den Ihre Transformation zurückgibt, wird zu einem Feld im Trigger, und das gesamte Objekt steht Ihnen auch im JSON-Format zur Verfügung, falls Sie es lieber selbst auswerten möchten.
Speichern Sie den Code auf GitHub
Sie können ein GitHub-Repository verknüpfen, damit Ihr Trigger-Code unter Versionskontrolle steht. Änderungen können in einem Pull-Request überprüft werden, Sie können sehen, wer was geändert hat, und Sie können eine Transformation rückgängig machen, die nicht mehr funktioniert.
Richten Sie die Verbindung auf der Entwicklerseite unter „Verbindungen“ ein. Sie legen fest, auf welche Repositorys die App zugreifen darf, und können diesen Zugriff jederzeit über GitHub widerrufen.
Sobald ein Repository ausgewählt wurde, werden alle vorhandenen Trigger sofort dorthin geschrieben, und die Synchronisation erfolgt in beide Richtungen:
| Was Sie tun | Was geschieht |
|---|---|
| Erstellen, bearbeiten oder duplizieren Sie einen Trigger in der App | Die Datei wurde in Ihr Repository eingecheckt |
| Einen Trigger in der App löschen | Die Datei wird aus Ihrem Repository entfernt |
| Eine Änderung in den verbundenen Zweig übertragen | Der Code des Triggers wird in der App aktualisiert |
Jeder Trigger besteht aus einer Datei, die nach ihrem Handle benannt ist und genau das Modul enthält, das Sie im Editor sehen - ohne jegliche zusätzliche Umhüllung. Das bedeutet, dass Sie die Datei in Ihrem eigenen Editor öffnen, ausführen und wie jede andere JavaScript-Datei auf Fehler prüfen können.
Zurück zu einer früheren Version
Sie müssen sich nicht mit Git auskennen, um eine Änderung rückgängig zu machen. Sobald eine Verbindung zu einem Repository hergestellt ist, zeigt der Editor ein Dropdown-Menü „Version“ an, in dem alle früheren Versionen dieser Datei mit Datum und Autor aufgelistet sind. Wählen Sie eine davon aus, und sie wird als ungespeicherte Änderung in den Editor geladen, sodass Sie sie zunächst lesen können - erst durch das Speichern wird sie wiederhergestellt.
Testen Sie während der lokalen Bearbeitung
Wenn Sie die Datei in Ihrem eigenen Editor bearbeiten, können Sie sie mit dem erfassten Beispielereignis ausführen, ohne sie zuvor in der App zu speichern. Verwenden Sie dazu einen API-Schlüssel mit der Berechtigungsstufe „execute“ von der Entwicklerseite:
curl -X POST https://shopify.workflow-trigger-extensions.app/api/v1/triggers/custom/high-value-vip-order/test \
-H "Authorization: Bearer ftk_your_key_here" \
-H "Content-Type: application/json" \
-d "$(jq -Rn --rawfile c flow-triggers/high-value-vip-order.js '{code:$c}')"Sie erhalten dasselbe Ergebnis, das auch die Schaltfläche „Test“ der App anzeigt: ob der Befehl ausgelöst würde, das Ausgabeobjekt, Ihre ctx.log-Zeilen sowie die Ausführungszeit.
Über diesen Endpunkt wird weder etwas ausgelöst noch gespeichert, und es wird kein Kontingent verbraucht - daher kann er bedenkenlos bei jedem Speichervorgang eines Datei-Watchers ausgeführt werden. (Die Schaltfläche „Test ausführen“ innerhalb der App löst Ihren Shopify Flow-Workflow aus, sodass Sie dessen Ausführung von Anfang bis Ende verfolgen können; dies ist ebenfalls kostenlos.)
Sie können die Beispiel-Payload auch separat mit einem Lesezugriffsschlüssel abrufen, lokal speichern und die Datei vollständig offline ausführen:
curl https://shopify.workflow-trigger-extensions.app/api/v1/triggers/custom/high-value-vip-order/test \
-H "Authorization: Bearer ftk_your_key_here"Wird bei einem benutzerdefinierten Trigger das Kontingent meines Plans verbraucht?
Ja, und er zählt jedes Ereignis, das er überwacht - nicht nur diejenigen, bei denen er ausgelöst wird. Wenn Ihr Trigger auf „Produktaktualisierung“ abhört und Ihr Shop monatlich 60.000 Produktaktualisierungen verzeichnet, sind das 60.000 Ereignisse, selbst wenn Ihr Code nur bei 100 davon ausgelöst wird.
Wir empfangen jedes dieser Ereignisse, entfernen Duplikate und stellen es in die Warteschlange; anschließend führen wir Ihren Code in einer isolierten Sandbox aus - und zwar noch bevor Ihr Code entscheidet, ob er ausgelöst wird. Die Anzahl spiegelt diesen Arbeitsaufwand wider.
Anders ausgedrückt: Die Kosten entsprechen denen eines integrierten Triggers für dasselbe Ereignis. Für die Filterung fallen keine zusätzlichen Kosten an, und das Testen ist stets kostenlos. Ein geplanter Trigger wird einmal pro Durchlauf gezählt.
Ist die Untersuchung kostenlos?
Ja. Sowohl die Schaltfläche „Test ausführen“ in der App als auch der API-Endpunkt /test sind davon ausgenommen, obwohl die Funktion „Test ausführen“ Ihren Shopify Flow tatsächlich auslöst, sodass Sie dessen Ausführung beobachten können. Nur Live-Ausführungen werden auf Ihr Kontingent angerechnet, sodass Sie eine Transformation so oft wie gewünscht iterieren können.
Warum ist „Payload._changes“ leer?
Entweder lag die Aktualisierung außerhalb der erfassten Felder - beispielsweise eine Änderung des Inventars oder einer Produktvariante bei einem Produkt - oder die App verfügt noch über keine Baseline für diesen Datensatz. Die Baseline wird gespeichert, sobald die App einen Datensatz zum ersten Mal erkennt; daher enthält die allererste Aktualisierung eines Datensatzes, den die App noch nie gesehen hat, keinen alten Wert. Jede nachfolgende Aktualisierung enthält hingegen einen solchen Wert.
Kann mein Code Daten in meinen Shops ändern?
Nr. ctx.shopify wird mit den von Ihnen gewährten Leserechten ausgeführt, und die App fordert niemals Schreibzugriff an. Dies ist beabsichtigt: Ein Trigger, der den Datensatz bearbeitet, auf den er überwacht, löst sich selbst erneut aus - genau diese Endlosschleife verhindert die Funktion Shopify, indem sie Workflows deaktiviert. Nehmen Sie Änderungen an den Daten in den Shopify Flow-Aktionen vor, die auf den Trigger folgen.
Kann ich den Griff später austauschen?
Nein, und das ist beabsichtigt. Ihr Shopify Flow-Workflow filtert anhand des Handles; eine Änderung würde daher die Ausführung dieses Workflows stillschweigend unterbrechen. Sie können den Trigger beliebig umbenennen - der Handle bleibt unverändert.
Der Handle ist zugleich der Dateiname in Ihrem GitHub-Repository, sodass auch dieser niemals geändert wird.
Was passiert, wenn mein Code einen Fehler enthält?
Das Ereignis wird übersprungen und der Fehler wird im Trigger protokolliert, sodass Sie erkennen können, was schiefgelaufen ist. Eine fehlgeschlagene Transformation blockiert niemals andere Vorgänge - Ihre übrigen Trigger, seien sie benutzerdefiniert oder systemeigen, laufen davon unbeeindruckt weiter.
Wo wird mein Code ausgeführt?
In einer isolierten Sandbox, getrennt vom Rest der App, mit einem kurzen Zeitlimit und ohne Zugriff auf die Anmeldedaten Ihres Shops. Es sieht ausschließlich die von Ihnen erfasste Ereignis-Payload sowie alles, was Sie mit ctx.shopify oder ctx.fetch abrufen.
Was passiert, wenn ich die Datei gleichzeitig in GitHub und in der App bearbeite?
Was auch immer Sie zuletzt speichern, hat Vorrang. Das Speichern in der App führt zu einer Festschreibung der Datei, und das Pushen in den verbundenen Zweig überschreibt den in der App gespeicherten Code. Wenn Sie überwiegend in Ihrem Repository arbeiten, sollten Sie den Editor der App als schreibgeschützt betrachten, um unerwartete Überraschungen zu vermeiden.
Kann eine Datei in meinem Repository einen neuen Trigger auslösen?
Nein. Ein Trigger muss außerdem wissen, auf welches Ereignis Shopify er reagiert, und die Datei enthält lediglich Code - würde man das Ereignis erraten, würde der Trigger auf die falsche Funktion verweisen. Erstellen Sie den Trigger zunächst in der App und bearbeiten Sie anschließend die zugehörige Datei nach Belieben.
Kann es bei Ereignissen ausgelöst werden, die die App noch nicht empfängt?
Nein. Ein benutzerdefinierter Trigger überwacht die Ereignisse, die die App bereits für Ihren Shop abonniert hat; dies hängt von den Berechtigungen ab, die Sie erteilt haben. Erteilen Sie die Berechtigung für eine Ressource, stehen deren Ereignisse auch benutzerdefinierten Triggern zur Verfügung. Für alle anderen Fälle führen Sie den Trigger nach einem Zeitplan aus.
Nächste Schritte
- Entwickler-API, MCP, GitHub und Trigger-Simulation - Verwalten und testen Sie Trigger aus Ihrem eigenen Code oder über einen KI-Assistenten.
- Trigger-Code mit KI generieren - Beschreiben Sie den Trigger in einfacher Sprache und lassen Sie die KI den Code schreiben.
- Pläne und Nutzung - Was als Ereignis gilt und wie die Beihilfe funktioniert.
- So funktionieren Trigger - die integrierten Trigger und wie diese ausgelöst werden.
