Transformationsfunktionen
Mapping entnimmt Werte aus einer Anfrage. Eine Transformationsfunktion geht noch einen Schritt weiter: Es handelt sich um Ihr eigenes JavaScript, das bei jeder Anfrage vor Shopify Flow ausgeführt wird, sodass Sie die Payload umgestalten, etwas nachschlagen, entscheiden können, ob die Anfrage überhaupt einen Workflow-Lauf rechtfertigt, oder den Aufrufer selbst beantworten können.
Diese Option befindet sich auf der Registerkarte „Funktion“ eines Webhooks. Ein leerer Editor bedeutet, dass die Funktion deaktiviert ist.
Die Form einer Funktion
export default async function transform(payload, ctx) {
// payload - the parsed request body (JSON, form or XML)
// return an object -> it becomes the payload for mapping and Flow
// return null -> nothing is sent to Flow, and nothing counts
return { ...payload, source: "warehouse" }
}Was Ihnen ctx bietet
ctx.request |
method, contentType, die Anfrage headers (geheime Angaben unkenntlich gemacht) und query |
ctx.webhook |
Die Webhooks id und name |
ctx.shop |
Ihre myshopify-Domain |
ctx.log(...) |
Schreibt eine Zeile, die Sie im Testfenster und im Verlauf lesen können |
await ctx.fetch(url, init) |
Ruft eine öffentliche API auf |
await ctx.shopify(query, variables) |
Liest Shop-Daten mit Admin GraphQL |
ctx.storage |
Behält kleine Werte zwischen den Durchläufen bei (siehe unten) |
ctx.respond(body, options) |
Nimmt den Anruf sofort entgegen |
Eine Payload umgestalten
Die häufigste Anwendung: Die Struktur eines Absenders in die wenigen Werte umwandeln, die Ihr Workflow benötigt.
export default async function transform(payload) {
const order = payload.data.attributes
return {
orderNumber: String(order.number),
email: order.customer.email.toLowerCase(),
total: Number(order.total_cents) / 100,
}
}Nicht benötigte Anfragen löschen
Geben Sie null zurück, und die Anfrage wird an dieser Stelle beendet: Es erfolgt kein Shopify Flow-Durchlauf, es wird kein Eintrag im Verlauf erstellt, und es wird nichts auf Ihr Kontingent angerechnet. Der Aufrufer erhält 200 mit dem Status { "skipped": true }, sodass kein erneuter Versuch unternommen wird.
export default async function transform(payload, ctx) {
if (payload.status !== "paid" || payload.total < 100) {
ctx.log("skipping", payload.id, payload.status, payload.total)
return null
}
return payload
}Sich zwischen den Läufen an Dinge erinnern
ctx.storage ist ein kleiner Schlüssel-Wert-Speicher, der zu Ihrem Shop gehört. Er dient dazu, die Frage „Habe ich das schon einmal gesehen?“ zu beantworten: Speichern Sie eine ID, sobald ein Ereignis eintrifft, und überspringen Sie die nächste Anfrage mit derselben ID, selbst wenn diese erst Tage später eingeht.
| Anruf | Ist |
|---|---|
await ctx.storage.get(key) |
Der gespeicherte Wert, auch als null bezeichnet |
await ctx.storage.set(key, value) |
Speichert einen beliebigen JSON-Wert und überschreibt dabei |
await ctx.storage.delete(key) |
Entfernt die Datei true, sofern diese existiert |
await ctx.storage.list({ prefix, limit, cursor }) |
Wichtige Bezeichnungen und Maße, Seite für Seite |
export default async function transform(payload, ctx) {
const key = `seen:${payload.id}`
if (await ctx.storage.get(key)) return null
await ctx.storage.set(key, { at: Date.now() })
return payload
}Anreicherung mit Shop-Daten
ctx.shopify Führt schreibgeschützte Admin-GraphQL-Abfragen für Ihren Shop aus, sodass ein Workflow mit Daten gestartet werden kann, über die der Absender nie verfügt hat. Er sieht nur das, was Sie zulassen: Erteilen Sie die erforderlichen Zugriffsbereiche unter „Zugriff auf Shop-Daten“ auf der Registerkarte „Funktion“. Standardmäßig wird kein Zugriff gewährt, und Mutationen werden abgelehnt.
export default async function transform(payload, ctx) {
const data = await ctx.shopify(
`query($q: String!) {
productVariants(first: 1, query: $q) { nodes { id title price } }
}`,
{ q: `sku:${payload.sku}` },
)
const variant = data.productVariants.nodes[0]
if (!variant) return null
return { sku: payload.sku, variantId: variant.id, price: variant.price }
}Den Anruf selbst entgegennehmen
ctx.respond() sendet umgehend eine Antwort zurück, wodurch der Webhook zu einem kleinen API-Endpunkt wird: etwas validieren, eine Antwort berechnen und in einer einzigen Anfrage antworten. Shopify Flow läuft weiterhin mit dem, was Sie zurückgeben.
export default async function transform(payload, ctx) {
const ok = typeof payload.email === "string" && payload.email.includes("@")
ctx.respond({ accepted: ok }, { status: ok ? 200 : 422 })
return ok ? payload : null
}Prüfung
Das Testfeld auf der Registerkarte „Funktion“ führt den Code im Editor - einschließlich nicht gespeicherter Änderungen - anhand einer Beispiel-Payload aus. Es zeigt den Rückgabewert, die Antwort, die Ihre Funktion senden würde, die von ihr erzeugten Flow-Felder, Ihre Protokollzeilen und die Dauer an. Es wird kein Shopify Flow ausgelöst, es wird nichts in den Verlauf geschrieben und es wird nichts auf Ihren Plan angerechnet. Speicherzugriffe finden jedoch tatsächlich statt: Bei einem Testlauf wird derselbe Speicher wie bei Live-Anfragen gelesen und beschrieben.
Wenn eine Funktion fehlschlägt
Sollte Ihr Code einen Fehler auslösen, eine Zeitüberschreitung verursachen oder einen unbrauchbaren Wert zurückgeben, wird die Anfrage mit dem Status 422 abgelehnt und der Fehler wird im Verlauf zusammen mit der Fehlermeldung und Ihren Protokolleinträgen protokolliert, sodass Sie nachvollziehen können, was geschehen ist. Beheben Sie den Fehler im Code und führen Sie diesen Eintrag erneut aus: Bei der Wiederholung wird die neue Version ausgeführt.
Grenzen
- 5 Sekunden und 64 MB pro Durchlauf sowie 50.000 Zeichen Code.
- Keine npm-Pakete.
ctx.fetchist die einzige Möglichkeit, und interne oder private Adressen werden abgelehnt. ctx.shopifyErlaubt 10 Aufrufe pro Durchlauf, ausschließlich Abfragen, beschränkt auf die von Ihnen gewährten Zugriffsbereiche.- Jeder Durchlauf, der „Shopify Flow“ erreicht, gilt als normaler Aufruf und wird auf Ihren Plan angerechnet. Eine übersprungene Anfrage wird nicht angerechnet.

