Email Lists
Une liste, c'est un conteneur d'abonnés avec ses propres réglages d'opt-in, son SMTP attaché, sa sequence par défaut, et son binding à des landings. Toute la machinerie (sends, events, suppression) s'organise autour de ce concept.

Concept
Une liste répond à trois besoins :
- Segmenter ta base. Différentes audiences (acheteurs sweepstakes vs nutra vs SaaS) n'ont pas besoin des mêmes drips. Une liste = un segment grossier ; les
custom_fieldsJSONB sur chaque subscriber permettent une segmentation fine au sein de la liste. - Isoler les réglages d'envoi. Une liste a sa propre adresse
from_email/from_name, sonreply_to, son SMTP, ses politiques opt-in. Tu peux router "Newsletter brand A" via Mailgun et "Transactional brand B" via Postmark, depuis la même instance. - Brancher l'enrôlement. Une landing pointe une liste via
landing_pages.email_list_id. Un conversion trigger pointe une liste viaemail_conversion_triggers.target_list_id. Une liste, c'est l'adresse stable vers laquelle tu redirigies des subscribers depuis n'importe quelle source.
Le modèle de données
Schema email_lists (extrait) :
| Colonne | Type | Note |
|---|---|---|
id |
SERIAL PK | |
name |
TEXT | label humain |
slug |
TEXT UNIQUE | utilisé dans les URLs de tracking |
smtp_server_id |
INTEGER FK | NULL = pas encore configuré — la liste accepte des subscribers, et leurs envois attendent : retenus jusqu'à 24 h après leur échéance, ils partent dès qu'un SMTP actif est rattaché, sinon ils échouent en smtp_indisponible |
default_sequence_id |
INTEGER FK | sequence auto-déclenchée à l'enrollment (NULL = pas de drip auto) |
double_opt_in |
BOOLEAN | si true, le subscriber doit cliquer un lien de confirmation avant de recevoir la sequence |
track_opens |
BOOLEAN | injecte le pixel d'ouverture |
track_clicks |
BOOLEAN | réécrit les liens via un redirect signé (/k/, HMAC de l'envoi + l'URL ; un lien non signé mène à une page de sortie, jamais à une redirection automatique) |
unsubscribe_redirect_url |
TEXT | URL vers laquelle on redirige après un click sur unsubscribe (vide = page interne) |
custom_unsubscribe_message |
TEXT | message affiché sur la page d'unsubscribe (vide = défaut) |
confirmation_subject |
TEXT | subject de l'email de double opt-in |
confirmation_body_html |
TEXT | HTML du même |
from_name_override |
TEXT | si non-vide, écrase le from_name du SMTP server |
reply_to_override |
TEXT | idem pour reply-to |
sto_enabled |
BOOLEAN | active Send-Time Optimization (chaque send est snappé à l'heure préférée du subscriber) |
sto_default_hour |
SMALLINT 0-23 UTC | heure de fallback quand on n'a pas encore appris la préférence d'un subscriber |
is_active |
BOOLEAN | soft-disable : aucune envoi, mais la liste reste lisible |
subscriber_count |
INTEGER | dénormalisé, mis à jour par trigger |
deleted_at |
TIMESTAMPTZ | soft-delete : la liste disparaît de l'UI mais reste queryable pour l'archive |
Créer une liste
Via l'UI
Sidebar → Email Marketing → Lists → New list. Tu remplis les champs essentiels :
- Name + slug (auto-suggéré depuis le name)
- SMTP server — optionnel, tu peux laisser vide et brancher plus tard. En attendant, les envois de la liste sont retenus : rattache un serveur actif dans les 24 h qui suivent l'échéance d'un envoi, sinon il échoue en
smtp_indisponibleet ne sera pas reprogrammé. Même règle si le serveur de la liste est désactivé ou supprimé ; réaffecter la liste à un serveur actif fait partir les envois retenus - Double opt-in — coche si tu veux la confirmation par email avant d'envoyer la sequence
- Track opens / Track clicks — décoche pour les listes transactionnelles où le tracking serait inutile / mal vu
Via MCP
// Request
{
"name": "create_email_list",
"arguments": {
"name": "Sweepstakes Buyers FR",
"slug": "sweeps-buyers-fr",
"smtp_server_id": 1,
"double_opt_in": false,
"track_opens": true,
"track_clicks": true
}
}
// Response
{
"status": "ok",
"tool": "create_email_list",
"message": "Email list created",
"list": {
"id": 7,
"name": "Sweepstakes Buyers FR",
"slug": "sweeps-buyers-fr",
"smtp_server_id": 1,
"default_sequence_id": null,
"subscriber_count": 0,
"is_active": true,
"created_at": "2026-05-18T12:14:02.213Z"
}
}
Le tool est défini dans autopilot-email-tools.js. Scope requis : email:write.
Modes d'opt-in
| Mode | double_opt_in |
Comportement |
|---|---|---|
| Single opt-in | false |
Le subscriber est status='subscribed' immédiatement. La sequence démarre dès l'enrollment. |
| Double opt-in | true |
Le subscriber est status='pending_confirm'. Un email de confirmation est envoyé. Tant qu'il n'a pas cliqué le lien (confirm_token), aucun email de la sequence n'est envoyé. Exception : une inscription avec skip_double_optin: true (postback de conversion, import en masse, outil MCP) entre directement subscribed — une confirmation encore en file est alors annulée. |
Quand choisir lequel ?
- Single opt-in : trafic affiliate, leads qualifiés par un formulaire prelander, conversions e-commerce. Le coût d'opportunité d'attendre un click de confirmation est trop élevé.
- Double opt-in : list-building pur (lead magnet, newsletter), audiences européennes où le GDPR pousse à documenter le consentement, listes que tu veux protéger contre le bot signup.
Champs GDPR / compliance
Trackily stocke pour chaque subscriber :
enrolled_at— quand le consentement a été donnéconfirmed_at— quand le lien double opt-in a été cliqué (si applicable)ip— IP au moment de l'enrollmentuser_agent— UA du browsersource— texte libre ("landing:foo-slug","manual:admin","trigger:postback-offer-42")country_code— auto-détecté via le tracking
Ces données t'aident à prouver le consentement en cas de demande GDPR. Pas de RGPD-magic automatique : à toi d'exposer une page d'export / suppression (et de propager l'unsubscribe vers email_suppression si la personne le demande).
Subscriber counts
email_lists.subscriber_count est dénormalisé pour éviter un COUNT(*) à chaque chargement de page. Il est recalculé :
- À chaque
enroll_email_subscriber/unsubscribe_email_subscriber - À chaque bounce / complaint reçu via webhook MTA
- Manuellement via un utilitaire admin si tu as bidouillé la DB en direct
Le compteur reflète les status='subscribed' uniquement — pending_confirm, unsubscribed, bounced, complained, nettoye ne comptent pas.
Langue des contacts et centre de préférences
langue_contact (en par défaut, fr, ar) règle la langue de ce que tes CONTACTS voient pour cette liste : le pied de chaque e-mail (« Se désinscrire » + « Gérer mes préférences ») et la page de préférences (de droite à gauche en arabe). Les listes existantes restent en anglais. Elle s'accepte à la création (POST /admin/api/email/lists) comme à l'édition, validée (400 langue_invalide). Par MCP : update_email_list avec langue_contact. Le détail d'une liste (GET /admin/api/email/lists/:id) rend aussi pieds_apercu : le pied dans les trois langues, tel que le moteur l'ajoute.
Depuis la page « Gérer mes préférences », un contact choisit ses listes, reçoit moins ou fait une pause : Centre de préférences.
Nettoyer une liste
Une vieille liste importée contient toujours des adresses mortes. Nettoyer la liste les trouve sans rien envoyer (syntaxe, fautes de frappe comme gmial.com, boîtes jetables, noreply@, domaines sans serveur de messagerie, adresses déjà en suppression), te montre le nombre par motif, et ne retire qu'après ta confirmation. Les lignes retirées passent « Nettoyée » ; tout est annulable 30 jours. Le guide complet : Nettoyer une liste.
Lister, inspecter, éditer
Lister toutes les listes
// Request
{ "name": "list_email_lists", "arguments": {} }
// Response (excerpt)
{
"status": "ok",
"lists": [
{
"id": 1,
"name": "Newsletter FR",
"slug": "newsletter-fr",
"subscriber_count": 8421,
"smtp_server_id": 1,
"default_sequence_id": 3,
"double_opt_in": false,
"is_active": true,
"bound_landings": 4,
"sequences": 2
}
]
}
Inspecter en profondeur
{
"name": "get_email_list_detail",
"arguments": { "id": 1 }
}
Retourne settings + histogramme des subscriber statuses + 10 plus récents subscribers + sequences attachées + landings bound. À utiliser AVANT toute opération de masse (rotation de sequence, soft-delete, changement de SMTP) pour t'éviter une surprise.
Patch incrémental
{
"name": "update_email_list",
"arguments": {
"id": 1,
"default_sequence_id": 5,
"from_name_override": "Marie de Brand FR"
}
}
Tu envoies seulement les champs à modifier. Les autres restent intacts.
Bind une liste à une landing
{
"name": "bind_landing_to_email_list",
"arguments": {
"landing_id": 42,
"list_id": 7
}
}
Toute soumission du formulaire de la landing enrôle désormais l'email dans la liste 7 et démarre sa default_sequence. Pour unbind, passe "list_id": null.
Détails sur les automations dans la page dédiée → Automations.
Soft-delete
Une liste se supprime de manière réversible. La table email_lists reçoit deleted_at = NOW(), mais les subscribers, sends, events, suppression sont conservés.
{
"name": "delete_email_list",
"arguments": { "id": 1 }
}
C'est un tool Tier-2 : la première call retourne une preview avec subscriber_count + nombre de landings bound. Tu rappelles avec confirm_token pour exécuter.
Erreurs courantes
- "column does not exist : from_name_override" — ta DB n'a pas appliqué la migration v41. Lance le startup une fois, le migrator y va.
- Sequence ne démarre pas — vérifie que
default_sequence_idest bien set sur la liste. Sans ça, l'enrollment se fait mais aucune drip ne tourne. - Subscribers en
pending_confirmqui ne reçoivent rien — double opt-in actif sans SMTP configuré → la confirmation attend. Branche un SMTP actif dans les 24 h qui suivent l'inscription (elle part alors au tick suivant), sinon elle échoue ensmtp_indisponible. Ou désactive le double opt-in. - Compteur figé à 0 — tu as utilisé
INSERT INTO email_subscribersdirect au lieu de passer parenroll_email_subscriber(qui met à jour le compteur).
Voir aussi
- Sequences — l'autoresponder qui se déclenche à l'enrollment
- SMTP — relais à attacher
- Automations — binding landing/liste, conversion triggers, post-purchase
- Suppression — pourquoi un subscriber peut être bloqué
- Nettoyer une liste — retirer les adresses mortes avant d'envoyer
- Centre de préférences — listes, fréquence, pause : ce que le contact règle lui-même
- MCP — tools reference — tous les tools email en un endroit