Sequences
Une sequence, c'est l'autoresponder : une suite ordonnée de steps qui partent au bout de N minutes/heures/jours après l'enrollment d'un subscriber dans la liste parente. Le premier step créé sur une liste devient automatiquement sa
default_sequence— celle que tout nouvel abonné déclenche.

Concept
Une sequence vit toujours dans le contexte d'une liste (email_sequences.list_id NOT NULL). Tu peux avoir N sequences sur une liste, mais une seule est marquée comme default_sequence côté liste : c'est celle qui se déclenche automatiquement à chaque enroll_email_subscriber. Les autres sequences existent pour des envois manuels, des A/B tests, ou des flows déclenchés par script.
Chaque sequence est composée de steps ordonnés par position. Pour chaque step, tu définis :
- Un délai depuis l'enrollment (
delay_days+delay_hours+delay_minutes) — note : c'est un delta depuis le moment où le subscriber a été enrôlé, pas depuis le step précédent. Ça rend la lecture de la sequence triviale ("Day 0, Day 1, Day 3, Day 7…") et évite les drifts cumulés. - Un subject + preheader
- Un body_html + body_text (le HTML est dominant ; le text est généré automatiquement si tu laisses vide, mais le fournir explicitement améliore la délivrabilité)
- Un internal name facultatif (label dans le builder, séparé du subject)
- Un flag
is_activepour désactiver un step sans le supprimer
Le modèle de données
email_sequences :
| Colonne | Type | Note |
|---|---|---|
id |
SERIAL PK | |
list_id |
INTEGER FK NOT NULL | la liste parente |
name |
TEXT | label humain |
description |
TEXT | optionnel |
is_active |
BOOLEAN | si false, les enrollments ne déclenchent rien |
total_steps |
INTEGER | dénormalisé pour l'UI |
deleted_at |
TIMESTAMPTZ | soft-delete |
email_sequence_steps :
| Colonne | Type | Note |
|---|---|---|
id |
SERIAL PK | |
sequence_id |
INTEGER FK NOT NULL | |
position |
INTEGER | ordre d'affichage et de tri (0, 1, 2…) |
delay_days / delay_hours / delay_minutes |
INTEGER | depuis l'enrollment, pas depuis le step précédent |
subject |
TEXT NOT NULL | |
preheader |
TEXT | inbox preview, ~110 chars |
body_html |
TEXT | obligatoire (peut être minimal) |
body_text |
TEXT | fallback plain-text |
name |
TEXT | internal label (ex: "Day 0 — Welcome") |
from_name_override |
TEXT | écrase la liste/SMTP juste pour ce step |
reply_to_override |
TEXT | idem |
is_active |
BOOLEAN | step désactivable sans suppression |
Créer une sequence
Via MCP
// Request
{
"name": "create_email_sequence",
"arguments": {
"list_id": 7,
"name": "Welcome series",
"description": "3-step onboarding for sweepstakes buyers"
}
}
// Response
{
"status": "ok",
"tool": "create_email_sequence",
"message": "Email sequence created. It is the default sequence of list 7.",
"sequence": {
"id": 12,
"list_id": 7,
"name": "Welcome series",
"is_active": true,
"total_steps": 0
}
}
Note la phrase de retour : si c'est la première sequence créée sur la liste, le tool met aussi à jour email_lists.default_sequence_id = 12. C'est intentionnel : 99% du temps, c'est ce que l'opérateur veut. Si tu veux changer la default plus tard, fais un update_email_list({ id: 7, default_sequence_id: <other> }).
Via l'UI
Sidebar → Email Marketing → Sequences → New sequence. Tu sélectionnes la liste parente, donnes un nom, et le builder vide s'ouvre. Tu cliques "+ Add step" pour ajouter le premier step.
Ajouter des steps
Step Day 0 (envoi immédiat)
{
"name": "add_email_sequence_step",
"arguments": {
"sequence_id": 12,
"name": "Day 0 — Welcome",
"position": 0,
"delay_days": 0,
"delay_hours": 0,
"delay_minutes": 5,
"subject": "Bienvenue {{first_name}} ! Voici ce qui t'attend",
"preheader": "Un cadeau de bienvenue + 3 trucs à savoir avant de continuer",
"body_html": "<p>Salut {{first_name}},</p><p>Merci d'avoir rejoint <strong>{{list_name}}</strong>. Voici ton code de bienvenue : <code>WELCOME15</code>.</p><p><a href=\"https://example.com/checkout?code=WELCOME15\">Utiliser mon code</a></p>",
"body_text": "Salut {{first_name}},\n\nMerci d'avoir rejoint {{list_name}}. Voici ton code de bienvenue : WELCOME15.\n\nLien : https://example.com/checkout?code=WELCOME15"
}
}
Le delay_minutes: 5 évite que le mail parte EXACTEMENT en même temps que le double opt-in (s'il y en a un) ou le reçu de commande — ce qui ferait deux mails simultanés et abîmerait l'expérience.
Step Day 1 (reminder)
{
"name": "add_email_sequence_step",
"arguments": {
"sequence_id": 12,
"name": "Day 1 — Reminder",
"position": 1,
"delay_days": 1,
"subject": "Tu n'as pas encore utilisé ton code, {{first_name}} ?",
"preheader": "Petit rappel — WELCOME15 expire dans 48 h",
"body_html": "<p>Salut {{first_name}},</p><p>Le code <strong>WELCOME15</strong> qu'on t'a envoyé hier est toujours actif, mais plus pour longtemps : <strong>expire dans 48 h</strong>.</p><p><a href=\"https://example.com/checkout?code=WELCOME15\">Récupérer mon offre</a></p>"
}
}
Step Day 3 (last call)
{
"name": "add_email_sequence_step",
"arguments": {
"sequence_id": 12,
"name": "Day 3 — Last call",
"position": 2,
"delay_days": 3,
"subject": "Dernier rappel : ton WELCOME15 expire ce soir",
"preheader": "C'est maintenant ou jamais",
"body_html": "<p>{{first_name}},</p><p>C'est la dernière fois qu'on t'en parle. Le code <strong>WELCOME15</strong> expire <strong>ce soir à minuit</strong>.</p><p>Si tu veux le tester avant qu'il disparaisse : <a href=\"https://example.com/checkout?code=WELCOME15\">click ici</a>.</p><p>Sinon, no worries — on a plein d'autres trucs cool dans la suite de la newsletter.</p>"
}
}
Éditer un step
{
"name": "update_email_sequence_step",
"arguments": {
"id": 47,
"subject": "Tu n'as pas encore utilisé WELCOME15, {{first_name}} ?",
"delay_days": 2
}
}
Tous les champs sont optionnels — tu envoies seulement ce que tu modifies. Pour désactiver un step sans le supprimer : { id, is_active: false }. Pour le réactiver : { id, is_active: true }.
Variables disponibles dans subject + preheader + body_html
Rendues au moment de l'envoi, en faisant un lookup sur le subscriber + sa liste :
| Variable | Source |
|---|---|
{{first_name}} |
premier mot de email_subscribers.name, fallback partie locale de l'email |
{{name}} |
email_subscribers.name |
{{email}} |
email_subscribers.email |
{{country}} |
email_subscribers.country_code |
{{custom.X}} |
email_subscribers.custom_fields->>'X' |
{{unsubscribe_url}} |
lien one-click signé, valide à vie |
{{list_name}} |
email_lists.name |
Le moteur n'échappe pas les variables — si tu interpoles {{name}} dans du HTML, assure-toi que name est safe (la validation côté enroll_email_subscriber n'autorise pas les < ni >, mais ne fais pas confiance aveuglément).
Send Time Optimization (STO)
Si tu actives sto_enabled: true sur la liste, chaque step planifié n'est pas envoyé à l'heure "naturelle" (= enrolled_at + delay), mais snappé à l'heure préférée du subscriber.
L'heure préférée est calculée à partir de ses email_events de type open : on regarde l'histogramme des heures d'ouverture sur les 90 derniers jours, et on stocke le pic dans email_subscribers.preferred_send_hour (SMALLINT, 0-23 UTC).
Tant qu'on n'a pas appris la préférence (nouveau subscriber, ou peu d'opens), on retombe sur email_lists.sto_default_hour (par défaut 10h UTC).
Le gain documenté dans l'industrie est de +15 à +25% sur l'open rate. À activer une fois que tu as 2-3 sequences en flight et que tu peux faire un avant/après crédible.
Test d'envoi
Avant de sauvegarder un step, envoie-toi un test :
{
"name": "send_test_email",
"arguments": {
"to": "moi@example.com",
"subject": "Bienvenue Marie ! Voici ce qui t'attend",
"body_html": "<p>Salut Marie,</p>...",
"list_id": 7,
"custom_fields": { "first_name": "Marie" }
}
}
Le tool envoie synchrone, bypass la queue, et ne logge PAS dans email_sends ni email_events (pour ne pas polluer les stats). Aucun tracking pixel ni footer auto-injecté — tu vois exactement ce que ta sequence enverra (moins le rendu final du tracker/footer).
Lister + inspecter
// list_email_sequences (filtre optionnel par list_id)
{ "name": "list_email_sequences", "arguments": { "list_id": 7 } }
// get_email_sequence_detail (settings + steps + preview body 200 chars)
{ "name": "get_email_sequence_detail", "arguments": { "id": 12 } }
Worked example : welcome series 3 steps
Recap complet, condensé :
// 1. Create the sequence (becomes the default sequence of list 7)
{ "name": "create_email_sequence", "arguments": { "list_id": 7, "name": "Welcome series" } }
// → returns sequence.id = 12
// 2. Day 0 (5 min after enrollment)
{ "name": "add_email_sequence_step", "arguments": {
"sequence_id": 12, "position": 0,
"delay_minutes": 5,
"subject": "Bienvenue {{first_name}} !",
"body_html": "<p>Voici ton code WELCOME15</p>"
}}
// 3. Day 1 reminder
{ "name": "add_email_sequence_step", "arguments": {
"sequence_id": 12, "position": 1,
"delay_days": 1,
"subject": "Tu n'as pas encore utilisé ton code ?",
"body_html": "<p>Petit rappel — WELCOME15 expire bientôt</p>"
}}
// 4. Day 3 last call
{ "name": "add_email_sequence_step", "arguments": {
"sequence_id": 12, "position": 2,
"delay_days": 3,
"subject": "Dernier rappel : WELCOME15 expire ce soir",
"body_html": "<p>C'est la dernière fois qu'on t'en parle</p>"
}}
// 5. Bind a landing to the list — every form submit will now trigger
// the welcome series automatically
{ "name": "bind_landing_to_email_list", "arguments": { "landing_id": 42, "list_id": 7 } }
// 6. Manually enroll yourself to test the full flow
{ "name": "enroll_email_subscriber", "arguments": {
"list_id": 7,
"email": "moi@example.com",
"name": "Test User",
"custom_fields": { "source_test": "manual" }
}}
5 minutes plus tard, tu reçois le Day 0. Le lendemain à la même heure, le Day 1. 3 jours après l'enrollment, le Day 3. Si STO est activé et que tu as un historique d'opens, chaque mail tombe à ton heure préférée.
Erreurs courantes
- Step créé mais jamais envoyé — vérifie
is_active=truesur le step ET sur la sequence ET sur la liste. Trois flags séparés. delay_daysinterprété comme "depuis le step précédent" — non : c'est depuis l'enrollment. Pour 3 steps espacés de 1 jour chacun, tu mets0,1,2(pas0,1,1).- Variables non rendues (
{{first_name}}apparaît tel quel) — typo dans le nom de variable, ou subscriber n'a pasname/custom_fieldssetté. Le moteur ne crashe pas, il laisse la chaîne brute. - Plusieurs sequences "default" sur une liste — impossible côté DB :
email_lists.default_sequence_idest un FK simple, un seul ID. Si tu en crées plusieurs, seule la première (chronologiquement) devient default.
Voir aussi
- Lists — où vivent les sequences
- Automations — déclencher l'enrollment automatiquement
- SMTP — sans relais, aucun step ne part
- MCP — tools reference / email — toutes les opérations email en un endroit