Pâlnii & declanșatoare
O pâlnie este un graf. O rulare este un rând. O așteptare este un timp.
Acesta este întregul model, iar fiecare proprietate dificilă a acestui produs decurge din aceste trei propoziții. Datorită lor, editarea unei pâlnii active este sigură. Datorită lor, o reîncercare nu poate trimite de două ori. Datorită lor, o persoană care se dezabonează marți nu aude nimic joi.
Ce se întâmplă în realitate la rulare
Publicarea unei pâlnii scrie o versiune imuabilă. Cineva intră și apare un rând: o rulare, pentru acest contact, legată de acea versiune, care reține nodul curent, un moment de trezire și propriul context.
Un worker închiriază rulările al căror moment de trezire a trecut, revendicându-le cu SKIP LOCKED, astfel încât doi workeri să nu poată lua aceeași. Execută noduri până ajunge la o așteptare sau la un terminal, apoi scrie următorul moment de trezire și se eliberează.
Un nod este o funcție pură a rulării, a contactului și a nodului — iar efectele sale se comit în aceeași tranzacție cu avansul rulării. Această singură proprietate face o reîncercare sigură. Un worker ucis în jumătatea de secundă dintre „trimitere” și „avans” lasă fie ambele, fie niciunul, niciodată doar unul.
Și, fiindcă aplicația furnizează timpul, nu baza de date, un rând scris acum este scadent acum. O coloană de planificare care folosește implicit ceasul bazei de date nu este încă scadentă în momentul scrierii și ratează chiar bătaia care a creat-o — un defect care nu pare nimic până când un mesaj întârzie o oră.
- 1Închiriere
wake_at <= now(),FOR UPDATE SKIP LOCKED. O coadă fără închirieri trimite de două ori în mod implicit. - 2ExecuțieNoduri în ordine, până la o așteptare sau un terminal. Fiecare scrie un pas: ce a decis, ce a emis.
- 3TrimitereEfecte și avans, într-o singură tranzacție. Aceasta este toată șmecheria.
- 4RepausUrmătorul
wake_ateste scris. Încă nu există rânduri în aval și nici nu este nevoie.
O rulare per contact per versiune
Patru sprezece declanșatoare
Ce poate porni o rulare
Unele dintre acestea sunt lucruri pe care le faceți dumneavoastră. Majoritatea sunt lucruri pe care clientul dumneavoastră le face sau nu le face — iar absența unei acțiuni este un declanșator la fel de bun ca acțiunea însăși.
Ajung
form_submit, list_join, contact_created, tag_added și segment_enter. Un segment este un predicat live, deci „intră în segment” acoperă fiecare „a devenit” pe care îl puteți exprima — trei comenzi, nouăzeci de zile de liniște, cheltuieli peste un prag.
Fac ceva
page_visit din fragmentul de site, message_opened, link_clicked, booking_made și payment_made. Deschiderea unui mesaj este ea însăși un eveniment pe contact, deci o pâlnie poate aștepta o reacție la ultimul lucru trimis.
Timpul, sau dumneavoastră
date_field cu un decalaj — o zi de naștere, o reînnoire, „un an de la”, șapte zile înainte sau trei zile după. schedule pentru cel recurent. manual pentru anunțul pe care îl trimiteți pentru că ați decis dumneavoastră.
Aplicația dumneavoastră
api_event este un eveniment personalizat pe care îl publicați din propriul cod, cu propriul token. Orice știe produsul dumneavoastră devine declanșator: activat, a invitat un coleg, a atins limita, a anulat, a exportat. Acesta este cel care transformă un instrument de trimitere de e-mailuri într-o parte a produsului dumneavoastră.
Reintrarea, decisă o singură dată
O pâlnie este fie re-entrantă, fie nu, iar baza de date impune acest lucru: o rulare per contact per pâlnie, cu excepția cazului în care ați spus altfel. Același declanșator care se activează de două ori în aceeași secundă nu poate produce din întâmplare două rulări.
Condiții de intrare
Un declanșator se activează, iar specificația de intrare decide dacă acest anumit contact este eligibil — un predicat de segment în fața ușii. Mai ieftin decât un nod de condiție pe primul pas, și menține graficul concentrat pe ceea ce se întâmplă, nu pe cine are voie să intre.

Patru sprezece lucruri îl pot porni. Șaisprezece lucruri se pot întâmpla apoi.
Șaisprezece acțiuni și șapte noduri de flux
Ce poate face o pâlnie și cum decide
Trimite ceva
send_email, send_sms, send_push, send_letter — patru canale, un singur graf — plus notify_team când persoana care trebuie anunțată lucrează pentru dumneavoastră.
Modifică contactul
add_tag, remove_tag, add_to_list, remove_from_list, set_field. Faptul că marcați pe cineva pe parcurs este ceea ce face segmentul următorului funnel simplu.
Acoperire în afara platformei
http_request către orice doriți, create_payment pe propriul cont conectat și book_slot pe o resursă de rezervări. Plătitorul rămâne al dumneavoastră; nimeni nu devine clientul nostru.
Deplasare între funnels
enter_funnel și exit_funnel. Construiți o singură secvență de bun venit și apelați-o din patru locuri, în loc să întrețineți patru copii care diverg până în martie.
Generare la momentul trimiterii
ai_generate completează variabilele de îmbinare pentru fiecare contact, contorizat în limita cotei dumneavoastră și stocat în cache după hash-ul creativului și al atributelor contactului — altfel ați plăti per destinatar la fiecare trimitere.
Așteptare, ramificare, divizare, unire
wait acceptă o durată, o dată-oră, o zi a săptămânii cu oră sau un câmp de dată cu un decalaj. condition este un predicat de segment cu un da și un nu. split este A/B/n cu ponderi. join reunește ramurile.
goal — cel care contează
Un obiectiv încheie rularea pentru oricine îl atinge. A rezervat, a cumpărat, a răspuns: restul secvenței este anulat specific pentru el. Nimeni nu primește „ne dorim de tine” a doua zi după ce s-a întors, iar acesta este nodul care previne asta.
throttle și quiet_hours
Throttle reglează ritmul unui vârf de trafic astfel încât o cutie poștală cu o limită scăzută de rată să nu fie bombardată până la suspendare. Quiet hours rețin un mesaj până la o oră civilizată — aplicate la nivelul mesajului, nu copiate în fiecare ramură a graficului.
Verificat înainte de a putea rula
Validatorul refuză aceleași lucruri atât pentru dumneavoastră, cât și pentru AI
Un grafic este verificat înainte de a putea fi publicat, iar verificarea nu este doar consultativă. Este același traseu de cod indiferent dacă o persoană a desenat funnelul sau un model l-a generat, iar acesta este singurul motiv pentru care funnelurile generate sunt de încredere.
Exact un punct de intrare
Două noduri de intrare sunt o ambiguitate pe care nimeni nu o observă până când jumătatea greșită a unei liste nu primește secvența greșită.
Fiecare nod este accesibil
O ramură orfană este fie o greșeală, fie un mesaj pe care credeți că îl trimiteți, dar care nu pleacă. Ambele cazuri merită semnalate.
Un ciclu trebuie să conțină o așteptare
O buclă fără așteptare în interior este o buclă infinită cu o trimitere în mijloc. Această regulă face diferența dintre un funnel și un incident.
Fiecare trimitere are creativul său
Un nod send_email fără un creativ și un subiect nu poate fi publicat. Mesajul cu subiectul corect și corpul gol este un mod de eșec real; este refuzat aici.
Fiecare variabilă este cunoscută
Variabilele de îmbinare sunt validate la publicare. {{frist_name}} este o greșeală de tastare pe care o vedeți în timpul editării, nu un „Bună ,” care ajunge în patruzeci de mii de inboxuri.
Apoi simulați-l
Rulați un contact real în regim de probă prin întregul grafic și citiți traseul parcurs și fiecare mesaj care ar fi trimis, cu ziua sa. Nimic nu iese din clădire.
Cazurile incomode
Șapte lucruri care strică un motor naiv
Fiecare dintre acestea este un test cu un ceas determinist în spate, pentru că fiecare strică o implementare care pare perfect corectă până când întâlnește realitatea.
- 1Un funnel care se buclă în sineLegitim, frecvent și în regulă — cu condiția ca ciclul să conțină o așteptare, ceea ce validatorul impune.
- 2Cineva se dezabonează pe parcursSuprimarea este verificată la trimitere, nu la punerea în coadă. Verificarea la punerea în coadă trimite mesaje persoanelor care au plecat în timpul așteptării.
- 3Funnelul este editat cu zece mii de oameni în interiorEi continuă să parcurgă versiunea în care au intrat, până la capăt. Noii intrați parcurg versiunea nouă.
- 4Același declanșator se activează de două ori într-o secundăO singură rulare, deoarece unicitatea este un index, nu o verificare urmată de o inserare.
- 5Un contact este șters în mijlocul rulăriiRularea se încheie. O ștergere care lasă o secvență încă adresată cuiva nu este o ștergere.
- 6O așteptare traversează o schimbare de oră de vară„Trei zile la ora nouă dimineața” înseamnă ora nouă dimineața pe ambele părți ale schimbării de ceas.
- 7Un worker este oprit între trimitere și avansareEfectele și avansarea sunt o singură tranzacție. Fie s-au întâmplat ambele, fie niciuna.
Ceas deterministFiecare test rupe o implementare plauzibilă
Campaniile sunt cealaltă jumătate
O pâlnie reacționează. O campanie este difuzarea unică: o audiență, un program, o limitare de viteză și o trimitere. Este un lucru de altă formă și este păstrat în mod deliberat separat, în loc să pretindă că este o pâlnie cu un singur nod.
Două reguli o fac sigură. O audiență este materializată o singură dată și refuză să ruleze de două ori — rezolvarea din nou ar adăuga în tăcere pe toți cei care s-au alăturat de la începerea trimiterii, iar indexul de deduplicare ar ascunde acest lucru prin prevenirea duplicatelor pe care le-ar fi creat. Iar contoarele sunt recalculate din evenimentele de livrare, niciodată incrementate pe loc, astfel încât un webhook reîncercat nu poate umfla un raport.
Ce să utilizați: dacă se întâmplă din cauza a ceva ce a făcut persoana, este o pâlnie. Dacă se întâmplă din cauza a ceva ce ați decis marți, este o campanie. O cantitate surprinzătoare de automatizări de marketing merg prost prin forțarea celei de-a doua în forma primei.