Trigger personalizzato

Trigger personalizzato

Copia pagina

Crea trigger personalizzati per Shopify Flow da qualsiasi evento, con confronto prima/dopo e condizioni JavaScript su misura.

I trigger predefiniti coprono le modifiche che interessano alla maggior parte dei negozi. Un trigger personalizzato copre il resto: basta selezionare un evento di Shopify, scrivere alcune righe di JavaScript per stabilire se tale evento è rilevante e quali dati inviare, e il risultato diventa un trigger che potrete utilizzare in Shopify Flow.

Tre aspetti che risolve e che un trigger integrato non è in grado di risolvere:

  • Attivare la funzione solo alle condizioni da Lei stabilite. “Solo quando un ordine superiore a 500 EUR riceve il tag vip” è una singola riga di codice, anziché un workflow che viene eseguito su ogni ordine e poi effettua il filtraggio.
  • Eseguite la verifica su una transizione, non su uno stato. Il vostro codice rileva il valore prima e dopo la modifica, pertanto è possibile che “lo stato sia passato da bozza ad attivo” o che “le scorte siano scese al di sotto di 5”. Una condizione basata sul valore corrente non può esprimere tale situazione.
  • Inviate esattamente i campi desiderati. Riorganizzate l'evento in base ai valori effettivamente utilizzati dal vostro workflow, anziché leggerli nuovamente uno per uno.

Un trigger personalizzato non necessita nemmeno di un evento Shopify: può anche essere eseguito secondo una pianificazione e stabilire autonomamente quali modifiche siano state apportate.

Come funziona

  1. Scegliete come farlo funzionare: un evento Shopify o una pianificazione.
  2. Per un evento, selezionate l’evento a cui è associato - qualsiasi evento di tipo Shopify che l’app riceve già - oppure partite da un modello, che seleziona l’evento e inserisce il codice.
  3. Acquisite un payload reale. Apportate tale modifica nel vostro negozio e l’app acquisirà il corpo esatto dell’evento.
  4. Scriva una trasformazione: restituisca un oggetto da attivare; restituisca unnulle da ignorare.
  5. Lo provi con l'evento acquisito e verifichi esattamente cosa riceverebbe il Suo workflow.
  6. Lo accenda.
L'editor di trigger personalizzati con nome, identificativo, la possibilità di scegliere tra un evento Shopify e una pianificazione, l'evento e un modello
Un nuovo trigger personalizzato: scegliete cosa lo attiva, selezionate l’evento e, se lo desiderate, partite da un modello.

Scrittura della trasformazione

Il Suo trigger è un modulo JavaScript che esporta una funzione denominata transform. Essa riceve quattro argomenti:

  • payload - il corpo grezzo dell'evento Shopify, esattamente così come viene ricevuto.
  • topic - quale evento si è verificato, ad esempio PRODUCTS_UPDATE.
  • shop - il Suo dominio MyShopify.
  • ctx - ctx.log(...) visualizza i dati nel pannello di log accanto all’editor, ctx.shopify(...) esegue una query GraphQL di amministrazione e ctx.fetch(...) effettua una richiesta a un URL su Internet.

Ciò che restituite determina ciò che accadrà:

  • Restituisca un oggetto e il trigger si attivi, trasportando tale oggetto.
  • Restituisca null e l'evento verrà saltato. È così che funziona il filtraggio: non è necessario imparare un linguaggio di filtraggio a sé stante.
  • Se lascia il file vuoto, l'evento verrà attivato ogni volta che si verifica un evento di quel tipo.
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,
  };
}

Il valore prima della modifica

Shopify

Nelle sezioni “Aggiornamento prodotto”, “Aggiornamento ordine” e “Aggiornamento cliente”, all’indirizzo payload._changes sono elencati tutti i campi monitorati modificati da tale aggiornamento, ciascuno con le relative pagine oldValue e newValue:

  • Prodotti: title, handle, description, status, vendor, productType, tags
  • Ordini: financialStatus, fulfillmentStatus, tags, note, lineItems e customAttributes.<name>
  • Clienti: tags, note, state (ENABLED, DISABLED, INVITED, DECLINED)

Si tratta di un elenco vuoto quando l'aggiornamento non ha interessato tali campi - ad esempio, una modifica all'inventario - oppure quando l'applicazione visualizza il record per la prima volta. L'evento di esempio che si acquisisce nell'editor mostra il campo, consentendo di visualizzarne la struttura effettiva prima di effettuare qualsiasi scrittura al suo interno.

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,
  };
}

Gli eventi più specifici presentano valori propri, sia vecchi che nuovi, pertanto non è necessario utilizzare _changes in quel caso: una variazione di prezzo presenta oldPrice, newPrice e percentChange; una variazione di inventario presenta _oldAvailable, _newAvailable e _delta; una variazione di metacampo presenta previousValue accanto a metafield.value.

Partite da un modello

Nella sezione “Fires on” dell’editor, l’opzione “Start from a template” seleziona l’evento e inserisce il codice funzionante. Modifichi le costanti nella parte superiore, esegua un test, quindi salvi. Ogni modello legge un valore prima e dopo la modifica:

  • Un campo relativo a un prodotto, a un ordine o a un cliente è stato modificato da un valore a un altro: lo stato è passato da “bozza” a “attivo”, un ordine è stato pagato, un account è stato attivato.
  • Il prezzo è sceso di oltre l’N per cento: si tratta di una vera e propria riduzione, non di una semplice modifica del prezzo.
  • Le scorte sono scese al di sotto di una soglia: si attiva un avviso una sola volta, nel momento in cui le scorte superano tale soglia, non ad ogni vendita quando il livello è già basso.
  • Il valore di un metacampo del prodotto ha superato una soglia: una valutazione è scesa al di sotto di 3, un margine ha superato il valore di 40.
  • Ordine pagato da un cliente di alto valore: rileva la spesa complessiva del cliente nel vostro negozio e si attiva solo al superamento dell’importo da voi stabilito.
La scheda "Transform" dell'editor contenente il codice di un modello denominato payload._changes
Un modello inserisce automaticamente il codice funzionante. Modifichi le costanti nella parte superiore, lo provi e poi lo salvi.

Recupero di dati aggiuntivi con ctx.shopify

I corpi dei Webhook contengono solo i campi inviati da Shopify. Qualora abbiate bisogno di altre informazioni - ad esempio il numero di ordini di un cliente, l’inventario di una variante o un metacampo - effettuate una richiesta all’API di amministrazione direttamente dalla vostra trasformazione:

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,
  };
}

Restituisce l’data della query e genera un’eccezione qualora la query presenti degli errori, in modo che nel Suo test venga segnalato un errore anziché non produrre alcun risultato in modo silenzioso.

Tre limiti che vale la pena conoscere:

  • Fino a 10 chiamate per esecuzione. L’arricchimento ne richiede poche; se se ne utilizzano di più, di solito si tratta di un ciclo. Recuperate ciò di cui avete bisogno in un’unica query, ove possibile.
  • L'app** legge, ma non scrive.** Utilizza le autorizzazioni che Le avete concesso e richiede sempre e solo l'accesso in lettura. Una richiesta relativa ai dati degli ordini non andrà a buon fine a meno che non sia stata concessa l'autorizzazione “Accesso ai dati degli ordini” nella pagina “Autorizzazioni”. Per apportare modifiche al Suo negozio, lo faccia nelle azioni di Shopify Flow che seguono il trigger.
  • Le credenziali del Suo negozio non vengono mai trasmesse al Suo codice. La query viene eseguita dall'app per Suo conto, pertanto all'interno della sandbox non è presente alcun token di accesso che possa essere oggetto di fuga.

ctx.fetch(url, options) Funziona come il servizio fetch del browser per qualsiasi risorsa presente su Internet: i dati di magazzino di un fornitore, un tasso di cambio, la propria API. Gli indirizzi di rete interni e privati vengono rifiutati. Se il codice di attivazione è salvato su GitHub, si prega di non inserirvi alcuna chiave API.

Trigger che vengono eseguiti secondo una pianificazione

Shopify Flow Reagisce quando si verifica un evento. Non può reagire quando non si verifica alcun evento e non è in grado di rilevare nulla al di fuori del Suo negozio. A tal fine, selezioni “In base a una pianificazione” nella sezione “Cosa fa scattare questa operazione”. Non vi è alcun evento Shopify alla base di tale trigger: il Suo codice viene eseguito a intervalli regolari, da ogni 30 secondi fino a una volta al giorno, e decide autonomamente cosa si configura come modifica.

Si tratta della stessa funzione transform, con un payload diverso e un valore di ritorno diverso:

  • payload.state - qualunque sia stato il valore restituito dal Suo codice come state nell'esecuzione precedente. null nella prima esecuzione.
  • payload.now e payload.lastRunAt - timestamp.
  • **Restituisca { state, events }`**`: il nuovo stato da memorizzare (fino a 32 KB) e un elenco di eventi da attivare (fino a 100 per esecuzione). Ogni evento attiva **`Trigger personalizzato`** una sola volta; l’`resourceId` di un evento, se ne è stato impostato uno, diventa l’ID del record in Shopify Flow. Restituisca null`` quando non vi è nulla da segnalare.

Durante la prima esecuzione, si ricordi di non attivare mai alcuna azione. Alla prima esecuzione, il Suo codice non ha alcun termine di paragone, quindi tutto apparirà nuovo. Salvi ciò che vede e non generi alcun evento; in questo modo, l’attivazione del trigger non sovraccaricherà mai i Suoi workflow. Tutti i modelli funzionano in questo modo.

L'editor personalizzato dei trigger in modalità "In base a una pianificazione", con l'intervallo e il numero di esecuzioni negli ultimi 30 giorni
In base a una pianificazione: scegliete l’intervallo - l’editor vi mostrerà il numero totale di esecuzioni risultanti - e partite da un modello di pianificazione.
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 }],
  }
}

Modelli per i trigger programmati, nella sezione “Avvia da un modello” della scheda “Pianificazione”:

  • Prodotto, ordine o cliente non aggiornato da N giorni: recensioni obsolete nel catalogo, ordini in sospeso, campagne di riconquista. Ogni record viene attivato una volta per ogni periodo di inattività e gli elementi già scaduti al momento dell’attivazione non vengono attivati tutti in una volta.
  • È stato modificato un valore esterno a Shopify: un feed delle scorte di un fornitore, un tasso di cambio, un listino prezzi, con la differenza e la percentuale relative ai numeri.
  • Nuovo elemento in un feed RSS o Atom: notizie del fornitore, un feed con l'elenco dei prodotti, una pagina di stato.
  • Nessun ordine per N ore: un "battito cardiaco" per il Suo negozio. Si attiva una volta quando gli ordini si interrompono e una volta quando riprendono.

Test esegue il codice una sola volta senza attivare alcuna azione e senza memorizzare lo stato, consentendovi così di eseguirlo tutte le volte che desiderate.

Come utilizzarlo in Shopify Flow

Ogni trigger personalizzato viene visualizzato in Shopify Flow con lo stesso nome: Trigger personalizzato. Lo si aggiunge a un workflow, quindi si imposta una condizione del tipo “L’ID del trigger è uguale all’ID del proprio trigger”.

Tale identificativo viene visualizzato nella pagina del trigger e non cambia mai, anche se si rinomina il trigger; in questo modo il Suo workflow continua a funzionare.

Ogni chiave restituita dalla vostra trasformazione diventa un campo del trigger, e l’intero oggetto è disponibile anche in formato JSON qualora preferiate analizzarlo autonomamente.

Conservate il codice su GitHub

È possibile collegare un repository GitHub in modo che il codice del trigger sia sottoposto al controllo di versione. Le modifiche diventano così soggette a revisione tramite una pull request; è possibile verificare chi ha apportato quali modifiche ed è possibile ripristinare una trasformazione che ha smesso di funzionare.

Lo colleghi nella pagina “Sviluppatori”, nella sezione “Connessioni”. È possibile scegliere quali repository l’app possa visualizzare e revocare tale accesso da GitHub in qualsiasi momento.

Una volta selezionato un repository, ogni trigger esistente vi viene immediatamente scritto e la sincronizzazione viene mantenuta in entrambe le direzioni:

Di cosa si occupa Cosa succede
Creare, modificare o duplicare un trigger nell'app Il file è stato salvato nel Suo repository
Eliminare un trigger nell'app Il file è stato rimosso dal Suo repository
Inviare una modifica al ramo collegato Il codice del trigger viene aggiornato nell'app

Ogni trigger è costituito da un unico file il cui nome corrisponde al proprio handle, contenente esattamente il modulo visualizzato nell'editor, senza alcun codice aggiuntivo. Ciò significa che è possibile aprirlo nel proprio editor, eseguirlo e sottoporlo a lint come qualsiasi altro file JavaScript.

Tornare a una versione precedente

Non è necessario conoscere Git per annullare una modifica. Una volta collegato un repository, l’editor mostra un menu a tendina “Versione” che elenca tutte le versioni precedenti di quel file con la relativa data e l’autore. Selezionandone una, questa verrà caricata nell’editor come modifica non salvata, in modo da poterla prima leggere; sarà il salvataggio a ripristinarla.

Eseguite i test mentre modificate localmente

Se sta modificando il file nel proprio editor, può eseguirlo sull’evento di esempio acquisito senza doverlo prima salvare nell’app. Utilizzi una chiave API con livello di esecuzione dalla pagina “Sviluppatori”:

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}')"

Otterrà lo stesso risultato visualizzato dal pulsante “Test” dell’app: se il codice verrebbe eseguito, l’oggetto di output, le righe di codice ctx.log e il tempo di esecuzione.

Questo endpoint non attiva alcuna azione né esegue alcun salvataggio, e non utilizza alcuna quota del piano; pertanto, può essere eseguito in tutta sicurezza ad ogni salvataggio da un file watcher. (Il pulsante "Esegui test" all’interno dell’app attiva invece il workflow Shopify Flow, consentendo di osservarne l’esecuzione dall’inizio alla fine; anche questa operazione è gratuita.)

È inoltre possibile scaricare il payload di esempio separatamente utilizzando una chiave di lettura, salvarlo in locale ed eseguire il file completamente offline:

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"
L'utilizzo di un trigger personalizzato consuma il mio traffico incluso nel piano?

Sì, e conta ogni evento che analizza, non solo quelli su cui si attiva. Se il Suo trigger è configurato per rilevare gli aggiornamenti dei prodotti e il Suo negozio registra 60.000 aggiornamenti al mese, si tratta di 60.000 eventi, anche se il Suo codice si attiva solo su 100 di essi.

Riceviamo, deduplichiamo e mettiamo in coda ciascuno di questi eventi, quindi eseguiamo il Suo codice in un ambiente sandbox isolato - il tutto prima che il Suo codice decida se attivarsi. Il conteggio riflette tale attività.

In altre parole: il costo è lo stesso che si avrebbe per un trigger integrato relativo allo stesso evento. Non vi viene addebitato alcun costo aggiuntivo per il filtraggio e i test sono sempre gratuiti. Un trigger pianificato viene conteggiato una volta per ogni esecuzione.

Il test è gratuito?

Sì. Sia il pulsante “Esegui test” nell’app sia l’endpoint API /test sono esenti, anche se il pulsante “Esegui test” avvia effettivamente il workflow in modo da consentirLe di osservarne l’esecuzione. Solo le esecuzioni in tempo reale consumano la Sua quota, pertanto può ripetere una trasformazione tutte le volte che desidera.

Perché il campo `payload._changes` è vuoto?

O l’aggiornamento riguardava campi non monitorati - ad esempio, una modifica all’inventario o a una variante del prodotto - oppure l’applicazione non dispone ancora di una linea di base per quel record. La linea di base viene memorizzata la prima volta che l’applicazione rileva un record; pertanto, il primissimo aggiornamento di un record che non ha mai visto prima non presenta alcun valore precedente. Tutti gli aggiornamenti successivi ne presentano invece uno.

Il mio codice può modificare i dati presenti nel mio negozio?

N. ctx.shopify funziona con i permessi di lettura da Lei concessi e l’app non richiede mai l’accesso in scrittura. Si tratta di una scelta deliberata: un trigger che modifica il record che sta monitorando si riavvia automaticamente, ed è proprio questo ciclo che Shopify interrompe i workflow. Modifichi i dati nelle azioni del flusso che seguono il trigger.

Posso sostituire la maniglia in un secondo momento?

No, ed è una scelta deliberata. Il Suo Shopify Flow applica un filtro in base all’identificatore; pertanto, modificandolo, si interromperebbe silenziosamente l’esecuzione di tale workflow. Può rinominare liberamente il trigger: l’identificatore rimane invariato.

L'identificativo corrisponde anche al nome del file nel Suo repository GitHub, pertanto non cambia mai.

Cosa succede se il mio codice presenta un bug?

L'evento viene saltato e l'errore viene registrato nel trigger, in modo da poter individuare la causa del problema. Una trasformazione non riuscita non blocca mai nient'altro: gli altri trigger, sia personalizzati che predefiniti, continuano a funzionare senza subire alcuna interferenza.

Dove viene eseguito il mio codice?

In un ambiente sandbox isolato, separato dal resto dell’app, con un limite di tempo breve e senza accesso alle credenziali del Suo negozio. Esso vede esclusivamente il payload dell’evento da Lei acquisito, oltre a quanto da Lei recuperato tramite ctx.shopify o ctx.fetch.

Cosa succede se modifico il file contemporaneamente su GitHub e nell'app?

Vince l’ultima operazione di salvataggio effettuata. Il salvataggio nell’app esegue il commit sul file, mentre il push sul ramo collegato sovrascrive il codice presente nell’app. Se lavorate prevalentemente nel vostro repository, considerate l’editor dell’app come di sola lettura per evitare sorprese.

Un file presente nel mio repository può generare un nuovo trigger?

No. Un trigger deve anche sapere a quale evento Shopify è associato, mentre il file contiene solo codice: cercare di indovinare l’evento comporterebbe collegarlo all’elemento sbagliato. Crei prima il trigger nell’app, poi modifichi liberamente il relativo file.

È in grado di attivarsi in occasione di eventi che l'app non riceve già?

No. Un trigger personalizzato rileva gli eventi a cui l’app è già iscritta per il Suo negozio, in base alle autorizzazioni che ha concesso. Concedendo l’autorizzazione per una risorsa, i relativi eventi diventano disponibili anche per i trigger personalizzati. Per qualsiasi altra operazione, la esegua secondo una pianificazione.

Prossimi passi