Trackily Docs

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.

Email — Lists

Concept

Une liste répond à trois besoins :

  1. 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_fields JSONB sur chaque subscriber permettent une segmentation fine au sein de la liste.
  2. Isoler les réglages d'envoi. Une liste a sa propre adresse from_email/from_name, son reply_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.
  3. Brancher l'enrôlement. Une landing pointe une liste via landing_pages.email_list_id. Un conversion trigger pointe une liste via email_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 mais refuse d'envoyer
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é
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
  • 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é.

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'enrollment
  • user_agent — UA du browser
  • source — 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 ne comptent pas.

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_id est bien set sur la liste. Sans ça, l'enrollment se fait mais aucune drip ne tourne.
  • Subscribers en pending_confirm qui ne reçoivent rien — double opt-in actif sans SMTP configuré → la confirmation email ne part jamais. Branche un SMTP ou désactive le double opt-in.
  • Compteur figé à 0 — tu as utilisé INSERT INTO email_subscribers direct au lieu de passer par enroll_email_subscriber (qui met à jour le compteur).

Voir aussi