Aangepaste triggers

Aangepaste triggers

Pagina kopiëren

Maak een aangepaste Shopify Flow-trigger op basis van elke gebeurtenis, met voor- en na-waarden en JavaScript om precies op uw voorwaarde te activeren.

De ingebouwde triggers dekken de wijzigingen die voor de meeste winkels van belang zijn. Een aangepaste trigger dekt de rest: u kiest een gebeurtenis in Shopify, schrijft een paar regels JavaScript om te bepalen of deze van belang is en welke gegevens moeten worden verzonden, en zo ontstaat een trigger die u kunt gebruiken in Shopify Flow.

Drie zaken die het oplost en die een ingebouwde trigger niet kan:

  • Vuur alleen af op basis van uw voorwaarde. „Alleen wanneer een bestelling van meer dan 500 EUR het tag vip krijgt” is één regel code, in plaats van een workflow die bij elke bestelling wordt uitgevoerd en vervolgens filtert.
  • Pas geen voorwaarde toe op een overgang, niet op een toestand. Uw code neemt de waarde vóór en na de wijziging waar, dus “de status is veranderd van ‘concept’ naar ‘actief’” of “de voorraad is onder de 5 gedaald” is mogelijk. Een voorwaarde op basis van de huidige waarde kan dat niet uitdrukken.
  • Verzend uitsluitend de velden die u nodig hebt. Pas de gebeurtenis aan naar de waarden die uw workflow daadwerkelijk gebruikt, in plaats van deze één voor één opnieuw uit te lezen.

Een aangepaste trigger heeft zelfs geen gebeurtenis van het type Shopify nodig: deze kan ook volgens een schema worden uitgevoerd en zelf bepalen wat er is gewijzigd.

Hoe het werkt

  1. Kies hoe het wordt uitgevoerd: een eenmalige gebeurtenis (Shopify) of een schema.
  2. Kies voor een gebeurtenis de gebeurtenis waarop deze reageert - elke gebeurtenis van het type Shopify die de app al ontvangt - of begin met een sjabloon, waarbij de gebeurtenis automatisch wordt geselecteerd en de code wordt ingevuld.
  3. Leg een echte payload vast. Breng die wijziging aan in uw winkel en de app registreert de exacte inhoud van de gebeurtenis.
  4. Schrijf een transformatie: retourneer een object om de actie uit te voeren, en retourneer null om deze over te slaan.
  5. Test het aan de hand van de vastgelegde gebeurtenis en bekijk precies wat uw workflow zou ontvangen.
  6. Zet het aan.
De editor voor aangepaste triggers met naam, identificatiecode, de keuze tussen een Shopify-gebeurtenis en een schema, de gebeurtenis en een sjabloon
Een nieuwe aangepaste trigger: kies wat ervoor zorgt dat deze wordt geactiveerd, selecteer de gebeurtenis en begin desgewenst op basis van een sjabloon.

De transformatie opstellen

Uw trigger is een JavaScript-module die een functie met de naam transform exporteert. Deze functie ontvangt vier argumenten:

  • payload - de onbewerkte inhoud van de gebeurtenis Shopify, precies zoals deze binnenkomt.
  • topic - welke gebeurtenis is geactiveerd, bijvoorbeeld PRODUCTS_UPDATE.
  • shop - uw MyShopify-domein.
  • ctx - ctx.log(...) geeft informatie weer in het logpaneel naast de editor, ctx.shopify(...) voert een Admin GraphQL-query uit en ctx.fetch(...) roept een URL op het openbare internet op.

Wat u teruggeeft, bepaalt wat er gebeurt:

  • Geef een object terug en de trigger wordt geactiveerd, waarbij dat object wordt doorgegeven.
  • Geef null terug en het evenement wordt overgeslagen. Zo werkt het filteren - u hoeft geen aparte filtertaal te leren.
  • Laat het bestand leeg; dan wordt het bij elke gebeurtenis van dat type geactiveerd.
flow-triggers/high-value-vip-order.jsjavascript
/**
 * 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,
  };
}

De waarde vóór de wijziging

Shopify

Bij productupdates, bestelupdates en klantupdates geeft payload._changes een overzicht van alle bijgehouden velden die door deze update zijn gewijzigd, telkens met de links oldValue en newValue:

  • Producten: title, handle, description, status, vendor, productType, tags
  • Bestellingen: financialStatus, fulfillmentStatus, tags, note, lineItems en customAttributes.<name>
  • Klanten: tags, note, state (ENABLED, DISABLED, INVITED, DECLINED)

De lijst is leeg wanneer de wijziging buiten die velden plaatsvond - bijvoorbeeld een wijziging in de voorraad - of wanneer de app het record voor het eerst ziet. Het voorbeeldgebeurtenis dat u in de editor vastlegt, toont het veld, zodat u de werkelijke indeling ervan kunt zien voordat u er gegevens in invoert.

flow-triggers/product-went-live.jsjavascript
/**
 * 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,
  };
}

De meer specifieke gebeurtenissen hebben hun eigen oude en nieuwe waarden, dus u hebt daar geen _changes nodig: een prijswijziging heeft oldPrice, newPrice en percentChange; een voorraadwijziging heeft _oldAvailable, _newAvailable en _delta; een metaveldwijziging heeft previousValue naast metafield.value.

Begin met een sjabloon

Als in de editor de optie „Fires on“ is geselecteerd, kiest „Start from a template“ de gebeurtenis en vult deze met werkende code. Bewerk de constanten bovenaan, test het resultaat en sla het vervolgens op. Elk sjabloon leest een waarde vóór en na de wijziging:

  • Een veld van een product, een bestelling of een klant is gewijzigd van de ene waarde naar de andere - de status is gewijzigd van ‘concept’ naar ‘actief’, een bestelling is betaald, een account is geactiveerd.
  • De prijs is met meer dan N procent gedaald - een echte prijsverlaging, niet zomaar een prijsaanpassing.
  • De voorraad is onder een drempelwaarde gedaald - er wordt één keer een signaal gegeven, op het moment dat de voorraad de drempel overschrijdt, en niet bij elke verkoop terwijl de voorraad al laag is.
  • Het aantal metavelden van een product heeft een drempelwaarde overschreden - een beoordeling is onder de 3 gedaald, een marge is boven de 40 gekomen.
  • Bestelling betaald door een klant met een hoge bestedingswaarde - het systeem leest de totale bestedingen van de klant in uw winkel uit en activeert de functie pas wanneer het bedrag hoger is dan het door u ingestelde bedrag.
De Transform-kaart van de editor met de code van een sjabloon met de tekst payload._changes
Een sjabloon vult werkende code in. Pas de constanten bovenaan aan, test het en sla het vervolgens op.

Extra gegevens ophalen met ctx.shopify

De inhoud van Webhooks bevat uitsluitend de velden die door de Shopify worden verzonden. Wanneer u andere gegevens nodig hebt - zoals het aantal bestellingen van een klant, de voorraad van een variant of een metaveld - dient u de Admin API rechtstreeks vanuit uw transformatie op te vragen:

Enrich the event before decidingjavascript
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,
  };
}

Deze functie retourneert de data van de query en genereert een uitzondering als de query fouten bevat, zodat er in uw test een foutmelding verschijnt in plaats van dat er stilzwijgend geen resultaat wordt weergegeven.

Drie beperkingen die u moet kennen:

  • Maximaal 10 oproepen per uitvoering. Voor verrijking is een handvol nodig; meer dan dat betekent doorgaans een lus. Haal, waar mogelijk, alles wat u nodig hebt in één query op.
  • De app leest alleen**, ze schrijft niet.** Ze maakt gebruik van de rechten die u hebt toegekend, en de app vraagt uitsluitend om leestoegang. Een verzoek om bestelgegevens mislukt tenzij „Toegang tot bestelgegevens” is toegekend op de pagina „Rechten”. Als u iets in uw winkel wilt wijzigen, doet u dat via de Shopify Flow-acties die op de trigger volgen.
  • De inloggegevens van uw winkel komen nooit in uw code terecht. De query wordt door de app namens u uitgevoerd, zodat er binnen de sandbox geen toegangstoken is dat zou kunnen uitlekken.

ctx.fetch(url, options) werkt net als de fetch van de browser voor alles op het openbare internet: de voorraadfeed van een leverancier, een wisselkoers, uw eigen API. Interne en privé-netwerkadressen worden geweigerd. Indien uw triggercode op GitHub is opgeslagen, vermeld daar dan geen API-sleutel in.

Triggers die volgens een schema worden uitgevoerd

Shopify Flow reageert wanneer er iets gebeurt. Het kan niet reageren wanneer er niets gebeurt, en het kan niets buiten uw winkel waarnemen. Kies daarvoor de optie „Volgens een schema” onder „Wat zorgt ervoor dat dit wordt uitgevoerd”. Aan een dergelijke trigger is geen Shopify-gebeurtenis gekoppeld: uw code wordt met een bepaalde frequentie uitgevoerd, variërend van elke 30 seconden tot één keer per dag, en bepaalt zelf wat als een wijziging wordt beschouwd.

Het betreft dezelfde functie transform, maar met een andere payload en een andere retourwaarde:

  • payload.state - de waarde die uw code bij de vorige uitvoering als state heeft geretourneerd. Bij de eerste uitvoering is dit null.
  • payload.now en payload.lastRunAt - tijdstempels.
  • Retour{ state, events }e: de nieuwe status die moet worden onthouden (maximaal 32 KB) en een lijst met te activeren gebeurtenissen (maximaal 100 per uitvoering). Elke gebeurtenis activeert de aangepaste trigger één keer; de resourceId van een gebeurtenis, indien u deze hebt ingesteld, wordt het record-ID in Shopify Flow. Retournull wanneer er niets te melden is.

Zorg ervoor dat de code bij de eerste uitvoering alleen onthoudt, maar nooit iets activeert. Bij de eerste uitvoering heeft uw code niets om mee te vergelijken, dus alles zou er nieuw uitzien. Sla op wat u ziet en geef geen gebeurtenissen terug; door de trigger in te schakelen, worden uw workflows nooit overspoeld. Alle sjablonen werken op deze manier.

De editor voor aangepaste triggers in de modus „Volgens schema“, met het interval en het aantal keren dat deze in 30 dagen wordt uitgevoerd
Volgens een schema: kies de interval - de editor geeft aan tot hoeveel herhalingen dit in totaal komt - en begin met een vooraf opgesteld sjabloon.
flow-triggers/supplier-stock-changed.jsjavascript
// 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 }],
  }
}

Sjablonen voor geplande triggers, onder ‘Beginnen met een sjabloon’ op de kaart ‘Planning’:

  • **Product, bestelling van klant is al N dagen niet bijgewerkt **- verouderde catalogusbeoordelingen, vastgelopen bestellingen, terugwinnen van klanten. Elk record wordt één keer per rustperiode geactiveerd, en items die al achterstallig waren op het moment dat u deze functie inschakelt, worden niet allemaal tegelijk geactiveerd.
  • Een waarde buiten Shopify is gewijzigd - een voorraadfeed van een leverancier, een wisselkoers, een prijslijst, waarbij het verschil en het percentage betrekking hebben op getallen.
  • Nieuw item in een RSS- of Atom-feed - nieuws van leveranciers, een productlijstfeed, een statuspagina.
  • Geen bestellingen gedurende N uur - een ‘hartslag’ voor uw winkel. Wordt één keer geactiveerd wanneer de bestellingen stoppen en één keer wanneer ze weer binnenkomen.

Met ‘Test’ wordt uw code één keer uitgevoerd zonder dat er iets wordt geactiveerd en zonder dat de status wordt opgeslagen, zodat u deze zo vaak kunt uitvoeren als u wilt.

Het gebruik ervan in Shopify Flow

Elke aangepaste trigger wordt in Shopify Flow weergegeven als dezelfde trigger: Aangepaste trigger. Voeg deze toe aan een workflow en voeg vervolgens een voorwaarde toe: ‘Trigger-handle is gelijk aan de handle van uw trigger’.

De naam wordt weergegeven op de pagina van de trigger en verandert nooit, zelfs niet als u de trigger een andere naam geeft - zodat uw workflow gewoon blijft werken.

Elke sleutel die uw transformatie retourneert, wordt een veld in de trigger, en het volledige object is ook beschikbaar als JSON, mocht u het liever zelf willen parseren.

Bewaar de code op GitHub

U kunt een GitHub-repository koppelen, zodat uw trigger-code onder versiebeheer valt. Wijzigingen kunnen vervolgens in een pull-verzoek worden beoordeeld, u kunt zien wie wat heeft gewijzigd en u kunt een transformatie terugdraaien die niet meer werkt.

Koppel deze op de pagina ‘Ontwikkelaar’, onder ‘Verbindingen’. U kiest zelf welke repositories de app kan zien, en u kunt die toegang op elk moment via GitHub intrekken.

Zodra een repository is geselecteerd, wordt elke bestaande trigger onmiddellijk daarheen geschreven, en blijft de synchronisatie in beide richtingen behouden:

Wat u doet Wat gebeurt er?
Een trigger aanmaken, bewerken of dupliceren in de app Het bestand is opgeslagen in uw repository
Een trigger in de app verwijderen Het bestand is uit uw repository verwijderd
Een wijziging naar de gekoppelde branch pushen De code van de trigger wordt bijgewerkt in de app

Elke trigger bestaat uit één bestand dat is vernoemd naar zijn handle en dat precies de module bevat die u in de editor ziet - zonder enige extra omhulling. Dat betekent dat u het in uw eigen editor kunt openen, uitvoeren en op fouten controleren, net als elk ander JavaScript-bestand.

Terugkeren naar een eerdere versie

U hoeft geen kennis van Git te hebben om een wijziging ongedaan te maken. Zodra er verbinding is gemaakt met een repository, toont de editor een vervolgkeuzemenu ‘Versie’ met daarin alle eerdere versies van dat bestand, inclusief de datum en de auteur. Kies er een uit en deze wordt in de editor geladen als een niet-opgeslagen wijziging, zodat u deze eerst kunt bekijken - pas door op te slaan wordt de wijziging daadwerkelijk teruggezet.

Test terwijl u lokaal bewerkt

Als u het bestand in uw eigen editor bewerkt, kunt u het uitvoeren op basis van de vastgelegde voorbeeldgebeurtenis zonder het eerst in de app op te slaan. Gebruik een API-sleutel met het uitvoeringsniveau van de ontwikkelaarspagina:

Test the file you are editingbash
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}')"

U krijgt hetzelfde resultaat terug als wat de knop ‘Test’ van de app weergeeft: of de actie zou worden geactiveerd, het uitvoerobject, uw regels in ctx.log en de uitvoertijd.

Dit eindpunt activeert niets en slaat niets op, en het verbruikt geen deel van uw abonnementskwote - u kunt het dus veilig uitvoeren bij elke opslag door een bestandsbewaker. (De knop ‘Test uitvoeren’ in de app activeert wel uw Shopify Flow-workflow, zodat u deze van begin tot eind kunt volgen; ook dat is gratis.)

U kunt de voorbeeldpayload ook afzonderlijk ophalen met een leessleutel, deze lokaal opslaan en het bestand volledig offline uitvoeren:

Get the captured sample payloadbash
curl https://shopify.workflow-trigger-extensions.app/api/v1/triggers/custom/high-value-vip-order/test \
  -H "Authorization: Bearer ftk_your_key_here"
Wordt het dataverbruik van mijn abonnement aangesproken bij het gebruik van een aangepaste trigger?

Ja, en het telt elke gebeurtenis die het controleert - niet alleen degene waarop uw trigger reageert. Als uw trigger luistert naar ‘Productupdate’ en uw winkel 60.000 productupdates per maand heeft, zijn dat 60.000 gebeurtenissen, zelfs als uw code slechts op 100 daarvan reageert.

Wij ontvangen al deze gebeurtenissen, verwijderen dubbele exemplaren en plaatsen ze in de wachtrij, waarna wij uw code uitvoeren in een geïsoleerde sandbox - en dit alles voordat uw code beslist of deze wordt geactiveerd. Het aantal weerspiegelt deze werkzaamheden.

Met andere woorden: het kost evenveel als de ingebouwde trigger voor dezelfde gebeurtenis zou kosten. Er worden geen extra kosten in rekening gebracht voor het filteren, en het testen is altijd gratis. Een geplande trigger telt één keer per uitvoering.

Is de test gratis?

Ja. Zowel de knop ‘Run test’ in de app als het API-eindpunt /test vallen hier niet onder, ook al activeert ‘Run test’ daadwerkelijk uw Shopify Flow-workflow, zodat u deze kunt volgen terwijl deze wordt uitgevoerd. Alleen live-uitvoeringen verbruiken uw quotum, dus u kunt een transformatie zo vaak herhalen als u wilt.

Waarom is `payload._changes` leeg?

Ofwel betrof de wijziging een veld dat niet wordt bijgehouden - bijvoorbeeld een wijziging in de voorraad of een wijziging in de variant bij een product - ofwel beschikt de app nog niet over een basislijn voor dat record. De basislijn wordt opgeslagen op het moment dat de app een record voor het eerst tegenkomt; de allereerste wijziging van een record dat de app nog nooit heeft gezien, bevat dus geen oude waarde. Elke volgende wijziging bevat dat wel.

Kan mijn code gegevens in mijn winkel wijzigen?

Nee. De ctx.shopify wordt uitgevoerd met de leesrechten die u hebt toegekend, en de app vraagt nooit om schrijftoegang. Dat is bewust zo ontworpen: een trigger die het record bewerkt waarnaar hij luistert, start zichzelf opnieuw, en dat is de lus waarvoor de Shopify workflows uitschakelt. Wijzig de gegevens in de Shopify Flow-acties die op de trigger volgen.

Kan ik de handgreep later nog vervangen?

Nee, en dat is bewust zo gedaan. Uw Shopify Flow-workflow filtert op de handle, dus als u deze wijzigt, zou de workflow zonder waarschuwing worden stopgezet. U kunt de trigger naar believen hernoemen - de handle blijft ongewijzigd.

De gebruikersnaam is tevens de bestandsnaam in uw GitHub-repository, dus ook deze verandert nooit.

Wat gebeurt er als mijn code een fout bevat?

De gebeurtenis wordt overgeslagen en de fout wordt geregistreerd bij de trigger, zodat u kunt zien wat er mis is gegaan. Een mislukte transformatie blokkeert nooit iets anders - uw andere triggers, zowel aangepaste als ingebouwde, gaan gewoon door zonder dat ze hierdoor worden beïnvloed.

Waar wordt mijn code uitgevoerd?

In een geïsoleerde sandbox, los van de rest van de app, met een korte tijdslimiet en zonder toegang tot de inloggegevens van uw winkel. Deze sandbox krijgt uitsluitend de door u vastgelegde gebeurtenispayloads te zien, plus de gegevens die u ophaalt via ctx.shopify of ctx.fetch.

Wat gebeurt er als ik het bestand tegelijkertijd in GitHub en in de app bewerk?

Wat u als laatste opslaat, is doorslaggevend. Als u in de app opslaat, wordt dit bovenop het bestand vastgelegd, en als u naar de gekoppelde branch pusht, wordt de code in de app overschreven. Als u voornamelijk in uw repository werkt, kunt u de editor van de app het beste als alleen-lezen beschouwen om onaangename verrassingen te voorkomen.

Kan een bestand in mijn repository een nieuwe trigger activeren?

Nee. Een trigger moet ook weten naar welke gebeurtenis van Shopify hij luistert, en het bestand bevat alleen code - als u de gebeurtenis zou moeten raden, zou de trigger aan de verkeerde gebeurtenis worden gekoppeld. Maak de trigger eerst in de app aan en bewerk vervolgens het bijbehorende bestand naar eigen inzicht.

Kan deze functie worden geactiveerd door gebeurtenissen die de app nog niet ontvangt?

Nee. Een aangepaste trigger reageert op de gebeurtenissen waarop de app al is geabonneerd voor uw winkel, afhankelijk van de machtigingen die u hebt verleend. Verleent u de machtiging voor een bron, dan worden de bijbehorende gebeurtenissen ook beschikbaar voor aangepaste triggers. Voor al het overige kunt u de trigger volgens een schema laten uitvoeren.

Volgende stappen