Flussi: trigger e step di automazione
Crea sequenze email automatizzate che reagiscono a eventi su contatti ed email
Un flusso iscrive automaticamente i contatti e li fa passare attraverso una sequenza di step — invia un'email, attendi, dividi in base a una condizione, aggiorna il contatto, chiama un webhook — in base a un trigger che definisci. I flussi vivono all'interno di un tenant, girano interamente lato server e non richiedono polling: iscrizione e ogni step sono guidati da eventi.
Questa pagina documenta il motore dei flussi così come si comporta davvero in produzione, inclusi quali tipi di trigger sono collegati oggi e quali sono riservati a una release futura. Configurare un flusso su un trigger non ancora attivo non genera errori — semplicemente non iscriverà mai nessuno, in silenzio. Vedi Tipi di Trigger qui sotto.
Come Funziona
Un flusso ha tre parti: un trigger (cosa avvia l'iscrizione), un array di step (cosa succede a un contatto iscritto, in ordine) e uno status (draft, active, inactive).
Succede qualcosa (es. un tag viene aggiunto a un contatto)
↓
Ogni flusso active il cui trigger corrisponde viene trovato
↓
Il contatto viene iscritto (idempotente — lo stesso evento non iscrive mai due volte)
↓
Lo step 0 viene eseguito
↓
Lo step 1 viene eseguito (subito, o dopo il ritardo di uno step wait)
↓
...
↓
L'iscrizione si completaSotto il cofano, sono due Cloud Function che comunicano tramite Pub/Sub e Cloud Tasks:
- Valutazione del trigger — qualsiasi azione che fa scattare un trigger (es. un cambio di tag) pubblica un messaggio. Una funzione interroga ogni flusso
activeil cuitrigger.typecorrisponde, controlla la config del trigger contro l'evento, e crea un'iscrizione per ogni corrispondenza. Gli ID di iscrizione sono deterministici (un hash di tenant + flusso + contatto + contesto del trigger), quindi lo stesso evento non può mai iscrivere due volte lo stesso contatto. - Esecuzione degli step — ogni step gira come un proprio Cloud Task. Uno step
waitnon tiene aperta una funzione; pianifica il task dello step successivo con un ritardo e ritorna subito. Questo significa che un flusso con un'attesa di 14 giorni non costa nulla mentre attende, e sopravvive a deploy, riavvii, tutto.
Un contatto viene saltato (non fallito) se il suo status è unsubscribed, bounced, o complained al momento dell'invio — controllato di nuovo a ogni step send_email, non solo all'iscrizione.
Tipi di Trigger
| Trigger | Stato | Iscrive quando |
|---|---|---|
contact_tag_added | Disponibile | Un tag specifico viene aggiunto a un contatto |
contact_tag_removed | Disponibile | Un tag specifico viene rimosso da un contatto |
contact_joins_audience | Riservato | (lo schema esiste; nulla pubblica ancora questo evento) |
email_event | Riservato | (lo schema esiste; nulla pubblica ancora questo evento) |
manual | Riservato | (lo schema esiste; non esiste ancora un endpoint di iscrizione) |
Solo contact_tag_added e contact_tag_removed iscrivono davvero i contatti oggi. Gli altri tre tipi di trigger sono valori validi che l'API accetta — un flusso che li usa si salva senza problemi, si attiva senza problemi, mostra 0 iscrizioni per sempre, e non ti dice mai perché. Se ti serve "iscrivi quando succede X" e X non è un cambio di tag, fai tu stesso il tagging: aggiorna i tag del contatto tramite PATCH /v1/contacts/:id dal tuo codice nel momento in cui l'evento reale accade, e fai scattare il trigger su quel tag.
Configurazione del trigger
La config del trigger è un oggetto piatto { chiave: valore }, solo valori stringa. Una chiave di config vuota o assente significa "corrispondi a qualsiasi cosa", non "non corrispondere a nulla" — omettila deliberatamente.
| Tipo di trigger | Chiave config | Comportamento se impostata | Comportamento se omessa |
|---|---|---|---|
contact_tag_added / contact_tag_removed | tagName | Iscrive solo per quel tag esatto | Iscrive su qualsiasi cambio di tag — quasi mai quello che vuoi |
contact_joins_audience | audienceId | Limita a un'audience | Corrisponde a qualsiasi ingresso in audience |
email_event | eventType, emailId | Limita a un tipo di evento e/o una email specifica | Corrisponde in modo ampio |
{
"type": "contact_tag_added",
"config": { "tagName": "waitlist-confirmed" }
}Crea un Flusso
Creare è in due step: l'API permette solo di dare un nome al flusso in creazione — trigger e step si impostano dopo con PATCH. Rispecchia il builder della dashboard, che crea una bozza vuota nel momento in cui clicchi "Nuovo flow" e ti lascia collegare tutto sul canvas.
1. Crea
curl -X POST https://api.tratto.email/v1/flows \
-H "Authorization: Bearer tratto_live_..." \
-H "Content-Type: application/json" \
-d '{"name": "Nurturing waitlist"}'{ "data": { "id": "flow_8f3ZqXnryVtC5k2Wm7B9e4" } }2. Configura trigger + step
curl -X PATCH https://api.tratto.email/v1/flows/flow_8f3ZqXnryVtC5k2Wm7B9e4 \
-H "Authorization: Bearer tratto_live_..." \
-H "Content-Type: application/json" \
-d '{
"trigger": {
"type": "contact_tag_added",
"config": { "tagName": "waitlist-confirmed" }
},
"steps": [
{ "id": "s0", "type": "send_email", "config": { "templateId": "tmpl_welcome", "subject": "Sei dentro", "from": "[email protected]", "fromName": "La tua azienda" } },
{ "id": "s1", "type": "wait", "config": { "delay": "2", "unit": "hours" } },
{ "id": "s2", "type": "send_email", "config": { "templateId": "tmpl_nurture_1", "subject": "Cosa stiamo costruendo", "from": "[email protected]", "fromName": "La tua azienda" } }
]
}'Un flusso viene creato in draft e ci resta — senza iscrivere nessuno — finché non lo attivi. Massimo 20 step per flusso. Gli id degli step sono stringhe a tua scelta; devono solo essere univoci all'interno del flusso.
Tipi di Step
Il config di ogni step è { chiave: stringa }, come i trigger — l'API non converte i tipi, quindi numeri e booleani entrano come stringhe.
send_email
| Chiave config | Obbligatoria | Note |
|---|---|---|
templateId | Sì, per renderizzare qualcosa | ID di un template — vedi Template |
subject | Consigliata | Se omessa, resta vuota |
from | Consigliata | Se omessa, resta vuota — i destinatari vedranno un mittente vuoto |
fromName | No | Nome visualizzato abbinato a from |
{ "id": "s0", "type": "send_email", "config": { "templateId": "tmpl_abc123", "subject": "Benvenuto", "from": "[email protected]", "fromName": "La tua azienda" } }Variabili disponibili nel template: email, firstName, lastName del contatto, e ogni chiave nei customFields del contatto vengono passate automaticamente come {{token}} — non serve dichiararle sullo step. Se un contatto ha customFields: { "position": "42" }, un template contenente {{position}} renderizza 42 per quell'invio, senza configurazione aggiuntiva.
wait
| Chiave config | Obbligatoria | Note |
|---|---|---|
delay | Sì | Un intero positivo, come stringa, es. "2" |
unit | No, default minutes | Uno tra seconds, minutes, hours, days |
{ "id": "s1", "type": "wait", "config": { "delay": "14", "unit": "days" } }Il puntatore di step dell'iscrizione avanza subito; è il task dello step successivo a essere ritardato. Controllare un'iscrizione a metà attesa mostra correttamente che è già sullo step successivo, solo non ancora dovuto.
branch
Valuta una condizione sui campi del contatto stesso (non customFields — campi di primo livello come status) e salta a un indice di step diverso in base al risultato.
| Chiave config | Obbligatoria | Note |
|---|---|---|
conditionField | Sì | Nome di un campo sul documento del contatto |
conditionOperator | No, default equals | equals, not_equals, exists, not_exists, contains |
conditionValue | Per equals/not_equals/contains | Valore da confrontare |
trueNextStep | No, default lo step successivo | Indice di step a cui saltare se la condizione è vera |
falseNextStep | No, default termina il flusso | Indice di step a cui saltare se la condizione è falsa |
{
"id": "s2",
"type": "branch",
"config": {
"conditionField": "status",
"conditionOperator": "equals",
"conditionValue": "subscribed",
"trueNextStep": "3",
"falseNextStep": "5"
}
}trueNextStep/falseNextStep sono indici nell'array steps (come stringhe), non ID di step — pianifica l'ordine dell'array prima di collegare i branch.
Lo step branch del builder nella dashboard espone al momento una coppia campo/valore semplificata che non corrisponde alle chiavi di config qui sopra. Configura gli step branch via API finché il builder non viene aggiornato.
update_contact
| Chiave config | Obbligatoria | Note |
|---|---|---|
action | No, default set_field | set_field, add_tag, remove_tag |
field, value | Per set_field | Imposta un campo arbitrario sul contatto |
tag | Per add_tag/remove_tag | Nome del tag da aggiungere o rimuovere |
{ "id": "s3", "type": "update_contact", "config": { "action": "add_tag", "tag": "nurtured" } }webhook_call
Notifica un URL esterno. Il corpo della richiesta è fisso — { "tenantId", "enrollmentId", "stepId" } — non è un template che compili tu.
| Chiave config | Obbligatoria | Note |
|---|---|---|
url | Sì | Deve essere http/https e un indirizzo pubblico — IP privati/riservati (127.0.0.1, 10.x, 192.168.x, ecc.) sono rifiutati |
method | No, default POST | Qualsiasi metodo HTTP |
secret | No | Se impostato, firma la richiesta con X-Tratto-Signature (HMAC-SHA256) — stesso schema dei webhook normali |
{ "id": "s4", "type": "webhook_call", "config": { "url": "https://tuaapi.com/hooks/flow-completed", "secret": "whsec_..." } }Timeout di 10 secondi; i fallimenti vengono loggati ma non fermano il flusso.
Attivare, Disattivare, Modificare
# Attiva — inizia a iscrivere
curl -X POST https://api.tratto.email/v1/flows/flow_abc123/activate \
-H "Authorization: Bearer tratto_live_..."
# Disattiva — ferma le nuove iscrizioni, quelle in corso continuano
curl -X POST https://api.tratto.email/v1/flows/flow_abc123/deactivate \
-H "Authorization: Bearer tratto_live_..."Non puoi fare PATCH degli steps di un flusso active — disattiva prima, modifica, riattiva. trigger e name si possono ancora cambiare mentre è attivo.
Elenca, Recupera, Elimina
curl https://api.tratto.email/v1/flows \
-H "Authorization: Bearer tratto_live_..."
curl https://api.tratto.email/v1/flows/flow_abc123 \
-H "Authorization: Bearer tratto_live_..."
curl -X DELETE https://api.tratto.email/v1/flows/flow_abc123 \
-H "Authorization: Bearer tratto_live_..."Eliminare un flusso active è bloccato allo stesso modo in cui lo è modificarne gli step — disattiva prima.
Testare un Flusso
Non esiste oggi una scorciatoia di iscrizione manuale via API (vedi Tipi di Trigger). Per testare un flusso contact_tag_added/contact_tag_removed end to end:
- Attiva il flusso.
- Crea o riusa un contatto di test.
- Aggiungi il tag esatto per cui il trigger è configurato, via
PATCH /v1/contacts/:id. - Controlla
GET /v1/flows/flow_abc123—enrollmentsdovrebbe incrementare, e il contatto di test dovrebbe ricevere il primo stepsend_emailentro pochi secondi.
Perché Costruire un Flusso
Qualsiasi cosa del tipo "quando succede X a un contatto, fai Y nel tempo" — senza dover scrivere e ospitare tu la logica di scheduling.
Nurturing di iscrizione / waitlist. Tagga un contatto waitlist-confirmed nel momento in cui completa il double opt-in, e lascia che un flusso mandi subito un'email di benvenuto, poi un breve drip (cosa stai costruendo, perché è prezzato in un certo modo, un'anteprima prodotto, un'offerta early-access) distanziato di giorni o settimane — è esattamente lo schema su cui gira la waitlist di Tratto stessa.
Re-engagement / win-back. Esegui un tuo controllo di inattività (ultima apertura email, ultimo login, qualsiasi segnale che dica "sparito") su uno schedule, tagga i contatti corrispondenti inactive-30d, e lascia che un flusso mandi una sequenza di recupero — un primo tocco, poi uno sconto o un aggiornamento prodotto, poi una notifica finale "smetteremo di scriverti" abbinata a uno step update_contact che li disiscrive se ancora non hanno interagito.
Checklist di onboarding. Tagga un contatto quando si iscrive al tuo prodotto; fai un drip di qualche giorno con "hai già provato X", ognuna che punta a una feature diversa, con step wait che danno il tempo di andare davvero a provarla prima del prossimo sollecito.
Passaggio alle vendite su alto intento. Tagga un contatto pricing-page-viewed-3x (dal tuo tracking) e usa uno step webhook_call per avvisare un canale Slack o il CRM nel momento in cui succede — il flusso diventa il trigger per un processo umano, non solo altra email.
Igiene dei dati. Tagga i contatti che entrano in uno stato specifico (trial-expired, payment-failed) e usa step update_contact per normalizzare un campo lifecycle_stage, così la segmentazione altrove nel prodotto (audience, campagne) resta coerente senza un passaggio di pulizia manuale.
Best Practice
Progetta intorno all'unico trigger davvero attivo. Finché contact_joins_audience/email_event/manual non sono collegati, ogni flusso parte di fatto da un cambio di tag. Prendi l'abitudine di taggare i contatti dal tuo codice applicativo nei momenti che contano — è quello il vero punto di ingresso.
Imposta tagName esplicitamente. Un trigger su tag vuoto corrisponde a ogni cambio di tag su ogni contatto. Compilalo sempre.
Dai ai flussi nomi che descrivono cosa fanno, non cosa sono. Follow-up post-acquisto 7 giorni, non Flusso 3.
Disattiva prima di modificare gli step. Non puoi evitarlo — lo impone l'API — quindi prendi l'abitudine presto invece di trovarti l'errore a metà modifica.
Distanzia gli invii con criterio. Gli step wait sono gratuiti e asincroni — non c'è pressione di costo per comprimere una sequenza. Dai ai contatti il tempo di leggere e agire su un'email prima che arrivi la successiva.
Prossimi Passi
- Tracciare le email inviate dai flussi? Configura i Webhook
- Inviare via API direttamente? Vedi Invia Email
- Costruire i template che un flusso invia? Vai a Template
- Gestire i tag dei contatti? Vedi Contatti
Modifica questa pagina su GitHub
Ultimo aggiornamento