Trackily Docs

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.

Email — Sequences

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_active pour 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=true sur le step ET sur la sequence ET sur la liste. Trois flags séparés.
  • delay_days interprété comme "depuis le step précédent" — non : c'est depuis l'enrollment. Pour 3 steps espacés de 1 jour chacun, tu mets 0, 1, 2 (pas 0, 1, 1).
  • Variables non rendues ({{first_name}} apparaît tel quel) — typo dans le nom de variable, ou subscriber n'a pas name/custom_fields setté. 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_id est un FK simple, un seul ID. Si tu en crées plusieurs, seule la première (chronologiquement) devient default.

Voir aussi