clickSomo
Ouvrir ClickSomo

Tunnels & déclencheurs

Un tunnel est un graphe. Une exécution est une ligne. Une attente est un instant.

C'est tout le modèle, et chaque propriété difficile de ce produit découle de ces trois phrases. C'est grâce à elles que modifier un tunnel en production est sûr. C'est grâce à elles qu'une relance ne peut pas envoyer en double. C'est grâce à elles qu'une personne qui se désabonne mardi n'entend plus parler jeudi.

Ce qui se passe réellement à l'exécution

La publication d'un tunnel écrit une version immuable. Quelqu'un entre, et une ligne apparaît : une exécution, pour ce contact, rattachée à cette version, portant le nœud courant, un instant de réveil et son propre contexte.

Un worker loue les exécutions dont l'instant de réveil est passé, en les revendiquant avec SKIP LOCKED pour que deux workers ne puissent pas prendre la même. Il exécute les nœuds jusqu'à atteindre une attente ou un nœud terminal, puis écrit le prochain instant de réveil et relâche.

Un nœud est une fonction pure de l'exécution, du contact et du nœud — et ses effets sont validés dans la même transaction que l'avancement de l'exécution elle-même. Cette seule propriété rend une relance sûre. Un worker tué dans la demi-seconde entre « envoyer » et « avancer » laisse soit les deux, soit aucun, jamais un seul.

Et comme l'application fournit l'heure plutôt que la base de données, une ligne écrite maintenant arrive à échéance maintenant. Une colonne de planification par défaut à l'horloge de la base de données n'est pas encore à échéance à l'instant où elle est écrite, et manque le tout premier tick qui l'a créée — un bug qui ne semble être rien du tout jusqu'à ce qu'un message arrive avec une heure de retard.

Un tick du workerExécution
  • 1Locationwake_at <= now(), FOR UPDATE SKIP LOCKED. Une file sans location envoie en double par défaut.
  • 2ExécutionLes nœuds dans l'ordre jusqu'à une attente ou un nœud terminal. Chacun écrit une étape : ce qu'il a décidé, ce qu'il a émis.
  • 3ValiderEffets et avancement, une seule transaction. C'est toute l'astuce.
  • 4SommeilLe prochain wake_at est écrit. Aucune ligne en aval n'existe encore, et aucune n'a besoin de l'être.

Une exécution par contact et par version

Quatorze déclencheurs

Ce qui peut démarrer une exécution

Certains sont des choses que vous faites. La plupart sont des choses que votre client fait, ou ne fait pas — et l'absence d'une action est un déclencheur aussi valable que l'action elle-même.

Ils arrivent

form_submit, list_join, contact_created, tag_added et segment_enter. Un segment est un prédicat vivant, donc « entre dans le segment » couvre tous les « est devenu » que vous pouvez exprimer — trois commandes, quatre-vingt-dix jours de silence, dépasse un seuil.

Ils font quelque chose

page_visit depuis le snippet du site, message_opened, link_clicked, booking_made et payment_made. L'ouverture d'un message est elle-même un événement sur le contact, donc un tunnel peut attendre une réaction à la dernière chose qu'il a envoyée.

Le temps, ou vous

date_field avec un décalage — un anniversaire, un renouvellement, « un an depuis », sept jours avant ou trois jours après. schedule pour le récurrent. manual pour l'annonce que vous envoyez parce que vous en avez décidé ainsi.

Votre propre application

api_event est un événement personnalisé que vous publiez depuis votre propre code avec votre propre jeton. Tout ce que votre produit sait devient un déclencheur : activé, invité un collègue, atteint la limite, annulé, exporté. C'est celui qui transforme un outil d'envoi en une partie de votre produit.

Ré-entrée, décidée une fois

Un tunnel est soit ré-entrant, soit il ne l'est pas, et la base de données le garantit : une exécution par contact et par tunnel, sauf si vous en avez décidé autrement. Le même déclencheur qui se déclenche deux fois dans la même seconde ne peut pas produire deux exécutions par accident.

Conditions d'entrée

Un déclencheur se déclenche et la spécification d'entrée décide si ce contact particulier est éligible — un prédicat de segment devant la porte. Moins cher qu'un nœud de condition à la première étape, et cela garde le graphe centré sur ce qui se passe plutôt que sur qui a le droit d'entrer.

Quatorze choses peuvent le démarrer. Seize choses peuvent se produire ensuite.

Seize actions et sept nœuds de flux

Ce qu'un tunnel peut faire, et comment il décide

Envoyer quelque chose

send_email, send_sms, send_push, send_letter — quatre canaux, un seul graphique — plus notify_team quand la personne à prévenir travaille chez vous.

Modifier le contact

add_tag, remove_tag, add_to_list, remove_from_list, set_field. Marquer les contacts au fil du parcours, c'est ce qui rend le segment du prochain tunnel simple.

Atteindre l'extérieur

http_request vers ce que vous voulez, create_payment sur votre propre compte connecté, et book_slot sur une ressource de réservation. Le payeur reste le vôtre ; personne ne devient notre client.

Passer d'un tunnel à l'autre

enter_funnel et exit_funnel. Construisez une seule séquence de bienvenue et appelez-la depuis quatre endroits, plutôt que d'entretenir quatre copies qui divergent d'ici mars.

Générer au moment de l'envoi

ai_generate remplit les variables de fusion par contact, décompté sur votre quota et mis en cache par hash de création et d'attribut de contact — sinon vous paieriez par destinataire à chaque envoi.

Attendre, brancher, répartir, rejoindre

wait accepte une durée, une date-heure, un jour de la semaine avec heure, ou un champ de date avec un décalage. condition est un prédicat de segment avec un oui et un non. split est un A/B/n avec pondérations. join rassemble les branches.

goal — le nœud qui compte

Un objectif termine le parcours pour quiconque l'atteint. La personne a réservé, acheté, répondu : le reste de la séquence est annulé pour elle spécifiquement. Personne ne reçoit « vous nous manquez » le lendemain de son retour, et c'est ce nœud qui l'empêche.

throttle et quiet_hours

Le throttle régule les rafales pour qu'une boîte mail à faible limite de débit ne soit pas martelée jusqu'à la suspension. Les heures calmes retiennent un message jusqu'à une heure convenable — appliquées à la couche message, et non copiées dans chaque branche du graphique.

Vérifié avant de pouvoir s'exécuter

Le validateur refuse les mêmes choses pour vous et pour l'IA

Un graphique est vérifié avant de pouvoir être publié, et la vérification n'est pas consultative. C'est le même chemin de code que le tunnel ait été dessiné par une personne ou généré par un modèle, et c'est la seule raison pour laquelle les tunnels générés sont dignes de confiance.

Exactement une entrée

Deux nœuds d'entrée créent une ambiguïté que personne ne remarque jusqu'à ce que la mauvaise moitié d'une liste reçoive la mauvaise séquence.

Chaque nœud est atteignable

Une branche orpheline est soit une erreur, soit un message que vous croyez parti et qui ne part pas. Dans les deux cas, cela mérite qu'on vous le signale.

Un cycle doit contenir une attente

Une boucle sans attente est une boucle infinie avec un envoi au milieu. Cette règle fait la différence entre un tunnel et un incident.

Chaque envoi a sa création

Un nœud send_email sans création ni objet ne peut pas être publié. Le message avec le bon objet et un corps vide est un mode de défaillance bien réel ; il est refusé ici.

Chaque variable est connue

Les variables de fusion sont validées à la publication. {{frist_name}} est une faute de frappe que vous voyez pendant l'édition, et non un « Bonjour , » qui arrive dans quarante mille boîtes de réception.

Puis simulez-le

Faites passer un contact réel dans tout le graphique à blanc et consultez le chemin suivi et chaque message qui serait envoyé, avec son jour. Rien ne sort du bâtiment.

Les cas épineux

Sept choses qui cassent un moteur naïf

Chacune de ces situations est un test avec une horloge déterministe derrière, car chacune casse une implémentation qui semble parfaitement correcte jusqu'à sa rencontre avec la réalité.

Ce contre quoi le moteur est testéFalsification
  • 1Un tunnel qui boucle sur lui-mêmeLégitime, courant et tout à fait acceptable — à condition que le cycle contienne une attente, ce que le validateur exige.
  • 2Quelqu'un se désabonne en cours de routeLa désinscription est vérifiée à l'envoi, pas à la mise en file. Vérifier à la mise en file enverrait un mail aux personnes parties pendant l'attente.
  • 3Le funnel est modifié alors que dix mille personnes s'y trouventElles poursuivent la version qu'elles ont empruntée à leur entrée, jusqu'au bout. Les nouveaux entrants suivent la nouvelle.
  • 4Le même déclencheur se déclenche deux fois en une secondeUne seule exécution, car l'unicité est un index plutôt qu'une vérification suivie d'une insertion.
  • 5Un contact est supprimé en cours d'exécutionL'exécution se termine. Une suppression qui laisse une séquence encore adressée à quelqu'un n'est pas une suppression.
  • 6Une attente chevauche un changement d'heure« Trois jours à neuf heures du matin » signifie neuf heures du matin de part et d'autre du changement d'heure.
  • 7Un worker est tué entre l'envoi et l'avancementLes effets et l'avancement forment une seule transaction. Soit les deux ont eu lieu, soit aucun.

Horloge déterministeChaque test casse une implémentation plausible

Les campagnes sont l'autre moitié

Un funnel réagit. Une campagne est la diffusion ponctuelle : une audience, un calendrier, une limitation de débit et un envoi. C'est une chose d'une autre forme, et elle est volontairement maintenue séparée plutôt que de prétendre être un funnel à un seul nœud.

Deux règles la rendent sûre. Une audience est matérialisée une seule fois et refuse de s'exécuter deux fois — une résolution à nouveau ajouterait discrètement tous ceux qui sont arrivés depuis le début de l'envoi, et l'index de déduplication le masquerait en empêchant les doublons qu'elle aurait créés. Et les compteurs sont recalculés à partir des événements de livraison, jamais incrémentés sur place, si bien qu'un webhook rejoué ne peut pas gonfler un rapport.

Lequel choisir : si cela se produit à cause de quelque chose que la personne a fait, c'est un funnel. Si cela se produit à cause d'une décision que vous avez prise un mardi, c'est une campagne. Une quantité surprenante d'automatisation marketing tourne mal en forçant la seconde dans la forme de la première.