Créer un agent marketing IA : tutoriel complet
Construisez un agent marketing IA avec Python : génération de contenu, campagnes email et reporting automatique. Tutoriel pas à pas avec code inclus.
Créer un agent marketing IA : tutoriel complet
Introduction
Le marketing digital repose sur des tâches répétitives : rédiger des posts, envoyer desemailings, compiler des rapports de performance. Ces opérations consomment des heures chaque semaine — heures que vous pourriez investir dans la stratégie.
Un agent marketing IA les automatise. Branché sur vos APIs (OpenAI ou Anthropic pour la génération de texte, SendGrid ou Mailchimp pour l'envoi, Google Analytics pour les métriques), il exécute un workflow complet de manière autonome : génération, validation optionnelle, envoi, reporting.
Dans ce tutoriel, vous allez construire cet agent de A à Z en Python. Prérequis : un niveau intermédiaire en Python, un compte OpenAI ou Anthropic, et une APIs email transactional. Durée estimée : 45 minutes.
Résumé rapide
| Étape | Module | Outil principal |
|---|---|---|
| 1 | Génération de contenu | OpenAI / Anthropic |
| 2 | Campagne email | SendGrid / Mailchimp |
| 3 | Reporting automatique | Google Analytics API |
| 4 | Orchestration | Python + schedule |
Architecture de l'agent marketing
Avant de coder, le schéma. L'agent marketing suit un pipeline en 4 modules :
Input (brief campagne)
│
▼
[Module 1] Génération contenu
│ → posts réseaux, variations A/B
▼
[Module 2] Campagne email
│ → segmentation, perso, envoi
▼
[Module 3] Reporting
│ → collecte métriques, résumé LLM
▼
Output (rapport exécutif)
Chaque module est indépendant : vous pouvez n'en activer qu'un seul ou chaîner les quatre. Le déclencheur peut être un schedule (quotidien, hebdo) ou un événement externe (nouveau produit, publication d'un article).
Module 1 : génération de contenu
Le premier module utilise un LLM pour produire des variations de contenu marketing. On commence par installer les dépendances :
pip install openai python-dotenv schedule
Configuration de base :
import os
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
BRAND_VOICE = """Tu es un copywriter expert en marketing digital francophone.
Ton style : direct, persuasif, concret. Pas de formule creuse.
Chaque phrase apporte une information ou un argument."""
def generate_post(topic: str, platform: str, n_variations: int = 3) -> list[str]:
"""Génère N variations de posts pour une plateforme donnée."""
platform_hints = {
"linkedin": "350-400 caractères, ton professionnel, inclut uneCTA,
"twitter": "200-280 caractères, ton percutant,Hashtag pertinent",
"instagram": "150-200 mots, ton engageant, 3-5 emojis max",
}
prompt = f"""{BRAND_VOICE}
Sujet : {topic}
Plateforme : {platform}
Contraintes : {platform_hints.get(platform, "")}
Génère exactement {n_variations} variations distinctes, numérotées 1 à {n_variations}.
"""
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "system", "content": prompt}],
temperature=0.8,
)
text = response.choices[0].message.content
return [v.strip() for v in text.split("\n") if v.strip() and v[0].isdigit()]
Exemple d'utilisation :
posts = generate_post(
topic="Nouvelle fonctionnalité : analyse de performance en temps réel",
platform="linkedin",
n_variations=3,
)
for i, post in enumerate(posts, 1):
print(f"Variation {i}:\n{post}\n")
La variable BRAND_VOICE est votre prompt système. Modifiez-la pour refléter le ton de votre marque. Plus elle est précise, plus les variations seront cohérentes entre elles.
Pour une campagne A/B, générez 2 variations avec des angles différents :
def ab_variations(topic: str) -> tuple[str, str]:
"""Génère 2 variations A/B avec angles distincts."""
prompt_a = f"""{BRAND_VOICE}\nSujet : {topic}\nAngle :BENEFICE client concret (chiffres, résultats)."""
prompt_b = f"""{BRAND_VOICE}\nSujet : {topic}\nAngle : PROBLEME résolu (douleur client avant/après)."""
response_a = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "system", "content": prompt_a}],
)
response_b = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "system", "content": prompt_b}],
)
return (
response_a.choices[0].message.content.strip(),
response_b.choices[0].message.content.strip(),
)
Module 2 : campagne email automatisée
L'envoi d'emails marketing impose des contraintes légales (RGPD en Europe). Votre agent respecte le cadre :
- Double opt-in : l'abonné confirme son inscription par email
- Lien de désinscription obligatoire dans chaque email (
List-Unsubscribe) - Pas d'achat de listes : seulement vos propres contacts consentants
Installation SendGrid :
pip install sendgrid
import sendgrid
from sendgrid.helpers.mail import Mail, Email, To, Content, Subscriber
sg = sendgrid.SendGridAPIClient(api_key=os.getenv("SENDGRID_API_KEY"))
def send_campaign(
subject: str,
html_body: str,
recipients: list[dict],
) -> dict:
"""
Envoie une campagne à une liste de destinataires.
recipients : [{"email": "x@y.com", "name": "X Y"}, ...]
RGPD: chaque destinataire doit avoir consenti.
"""
# Segmentation simple : filtrer les inactifs (exemple)
active = [r for r in recipients if r.get("active", True)]
# Construction du contenu
# Note: en production, utilisez un template SendGrid dynamique
results = {"sent": 0, "failed": 0, "errors": []}
for recipient in active:
try:
message = Mail(
from_email=Email("marketing@votredomaine.com"),
to_emails=To(recipient["email"]),
subject=subject,
html_content=Content("text/html", html_body),
)
# Ajout du footer RGPD obligatoire
message.footer = True
response = sg.send(message)
results["sent"] += 1
except Exception as e:
results["failed"] += 1
results["errors"].append({"email": recipient["email"], "error": str(e)})
return results
Pour personnaliser le contenu par segment, utilisez les attributs de contact SendGrid :
def personalize_content(base_html: str, recipient: dict) -> str:
"""Remplace les variables de personnalisation dans le template."""
replacements = {
"{{first_name}}": recipient.get("name", "Client").split()[0],
"{{company}}": recipient.get("company", ""),
"{{last_purchase}}": recipient.get("last_purchase", "votre dernier achat"),
}
content = base_html
for placeholder, value in replacements.items():
content = content.replace(placeholder, value)
return content
Module 3 : reporting de performance
Le troisième module collecte les métriques (via Google Analytics Data API) et utilise le LLM pour produire un résumé exécutif :
pip install google-analytics-data
from google.analytics.data_v1beta import BetaAnalyticsDataClient
from google.analytics.data_v1beta.types import RunReportRequest
import os
GA_PROPERTY_ID = os.getenv("GA_PROPERTY_ID")
client = BetaAnalyticsDataClient()
def fetch_metrics(days: int = 7) -> dict:
"""Collecte les métriques principales sur N jours."""
return {
"sessions": 0,
"conversions": 0,
"bounce_rate": 0,
"top_pages": [],
}
def ai_summary(metrics: dict, campaign_name: str) -> str:
"""Génère un résumé exécutif avec le LLM."""
prompt = f"""Tu es un analyste marketing senior. Voici les métriques d'une campagne
appelée "{campaign_name}" sur les 7 derniers jours :
- Sessions : {metrics['sessions']}
- Conversions : {metrics['conversions']}
- Taux de rebond : {metrics['bounce_rate']}%
- Pages les plus visitées : {', '.join(metrics['top_pages'])}
Rédige un résumé exécutif de 100 mots maximum, en français,
avec 2-3 KPIs mis en avant et une recommandation d'action.
Format : paragraphe unique, pas de bullet points."""
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
)
return response.choices[0].message.content.strip()
Orchestration : enchaîner les 3 modules
Le module d'orchestration déclenche les 3 modules dans l'ordre, avec une validation humaine optionnelle :
import schedule
import time
import threading
class MarketingAgent:
def __init__(self, config: dict):
self.config = config
self.human_validation = config.get("human_validation", True)
def run_full_campaign(self, campaign_brief: dict):
"""Exécute le pipeline complet campagne."""
print(f"🚀 Lancement campagne : {campaign_brief['name']}")
# Module 1 : contenu
print("📝 Génération du contenu...")
posts = generate_post(
topic=campaign_brief["topic"],
platform=campaign_brief.get("platform", "linkedin"),
n_variations=campaign_brief.get("n_variations", 3),
)
print(f" → {len(posts)} variations générées")
# Validation humaine optionnelle
if self.human_validation:
print("\n⚠️ Validation humaine requise avant envoi.")
print(" Relectez les contenus ci-dessus.")
approval = input(" Envoyer ? (o/n) : ")
if approval.lower() != "o":
print(" Campagne annulée.")
return
# Module 2 : email
if campaign_brief.get("send_email"):
print("📧 Envoi de la campagne email...")
results = send_campaign(
subject=campaign_brief["subject"],
html_body=self.build_html_email(posts[0]),
recipients=campaign_brief["recipients"],
)
print(f" → {results['sent']} emails envoyés, {results['failed']} échecs")
# Module 3 : reporting
print("📊 Génération du rapport...")
metrics = fetch_metrics(days=7)
summary = ai_summary(metrics, campaign_brief["name"])
print(f"\n Résumé IA :\n {summary}\n")
def build_html_email(self, post_content: str) -> str:
"""Construit le HTML de l'email depuis le contenu du post."""
return f"""
<html><body>
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<div style="background: #1a1a2e; color: white; padding: 20px; text-align: center;">
<h1 style="margin:0;">Votre actualité</h1>
</div>
<div style="padding: 20px; line-height: 1.6;">
<p>{post_content}</p>
<hr style="border: none; border-top: 1px solid #eee; margin: 20px 0;">
<p style="font-size: 12px; color: #888;">
Vous recevez cet email car vous vous êtes inscrit sur notre site.<br/>
<a href="#unsubscribe">Se désinscrire</a>
</p>
</div>
</div>
</body></html>
"""
def schedule_campaign(self, campaign_brief: dict, time_str: str = "09:00"):
"""Planifie une campagne à une heure donnée (format HH:MM)."""
schedule.every().day.at(time_str).do(
self.run_full_campaign, campaign_brief
)
print(f"📅 Campagne planifiée chaque jour à {time_str}")
# Lancement
if __name__ == "__main__":
agent = MarketingAgent(config={"human_validation": True})
campaign = {
"name": "Campagne Avril - Feature X",
"topic": "Nouvelle fonctionnalité : analyse de performance en temps réel",
"platform": "linkedin",
"n_variations": 3,
"subject": "Découvrez notre nouvelle fonctionnalité analytique",
"send_email": True,
"recipients": [
{"email": "client1@example.com", "name": "Jean Dupont", "active": True},
{"email": "client2@example.com", "name": "Marie Martin", "active": True},
],
}
# Exécution immédiate (test)
agent.run_full_campaign(campaign)
# Ou planifier : agent.schedule_campaign(campaign, "09:00")
# while True:
# schedule.run_pending()
# time.sleep(60)
Ce script exécute le pipeline complet en une seule commande. En production, décommentez la section schedule pour un lancement automatique quotidien.
Tableau récapitulatif des outils utilisés
| Fonction | Outil | Alternative |
|---|---|---|
| Génération LLM | OpenAI GPT-4o | Anthropic Claude |
| Envoi email | SendGrid | Mailchimp, Brevo |
| Analytics | Google Analytics Data API | Plausible, Matomo |
| Scheduling | Python schedule | Celery, cron |
| Segmentation | SendGrid contacts API | Mailchimp segments |
Bonnes pratiques
Révision humaine obligatoire — Ne laissez jamais un agent envoyer des emails sans relecture. Le ton de marque, l'exactitude des données et la conformité RGPD nécessitent un regard humain.
Prompts système stables — Définissez votre BRAND_VOICE une fois et testez-le sur 10 contenus avant de le figer. Un prompt mal calibré produit des variations incohérentes qui nuisent à votre image.
Limites RGPD — En Europe, le consentement doit être explicite et documenté. Conservez une trace du opt-in (date, source). L'agent ne doit jamais envoyer d'email à une personne qui ne s'est pas explicitement inscrite.
Gestion des erreurs — Chaque module retourne ses erreurs séparément. Ne laissez pas un échec en cascade compromettre toute la campagne. Le module email capture les échecs par destinataire et vous permet de retenter uniquement les échecs.
Rate limits — Les APIs (OpenAI, SendGrid) ont des limites de débit. Implémentez un backoff exponentiel :
import time
from openai import RateLimitError
def generate_with_retry(prompt: str, max_retries: int = 3) -> str:
for attempt in range(max_retries):
try:
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
)
return response.choices[0].message.content
except RateLimitError:
wait = 2 ** attempt
print(f"Rate limit — attente {wait}s...")
time.sleep(wait)
raise Exception("Max retries exceeded")
Questions fréquentes
Comment maintenir un ton de marque cohérent sur toutes les variations ?
Définissez un prompt système détaillé (brand voice) et générez au minimum 3 variations. Triez par cohérence avec le brand voice avant de valider. Pour les marques avec plusieurs persona (B2B vs B2C), maintenez deux prompts distincts et appliquez le bon selon le segment.
Peut-on utiliser cet agent pour plusieurs clients simultanément ?
Oui. Instanciez un MarketingAgent par client, chacun avec sa propre configuration (API keys, liste de destinataires, brand voice). Attention à bien isoler les données clients et à respecter les quotas d'API par client.
Comment suivre les performances au-delà de Google Analytics ?
Ajoutez des UTMs (Urchin Tracking Module) à chaque lien dans vos emails pour suivre les clics par campagne dans GA4. Pour un tracking plus fin, intégrez des pixels de conversion sur vos pages de destination.
L'agent peut-il gérer des campagnes multilingues ?
Oui. Spécifiez la langue dans le prompt système pour chaque campagne. Pour l'espagnol, l'allemand ou l'italien, GPT-4o fonctionne correctement. Pour des langues moins courantes, privilégiez Claude qui offre une meilleure couverture multilingue.
Comment éviter que les emails finissent en spam ?
Trois leviers : authentification SPF/DKIM/DMARC configurée sur votre domaine d'envoi, taux de désinscription bas (moins de 0,5%), et contenu sans termes spam (évitez "GRATUIT", "GAGNEZ", majuscules excessives). SendGrid fournit un outil de prévisualisation spam avant envoi.
Articles liés
Votre agent marketing est opérationnel. Pour aller plus loin, explorez les automatisations qui chainent avec ce que l'agent génère :
- Créer un agent IA : guide complet — les bases de l'architecture agent avant d'étendre ce marketing agent
- Automatiser le marketing avec OpenClaw — stratégies avancées de campaigns automation multi-canaux
- Automatiser le SEO avec OpenClaw — connectez la génération de contenu à un pipeline SEO
- Automatisation par agents IA — panorama complet des cas d'usage automation
- Agent SEO avec OpenClaw — connectez votre agent marketing à un pipeline SEO pour amplifier la visibilité
Restez informé sur les agents IA
Nouveaux tutoriels, comparatifs et guides pratiques directement dans votre boîte mail.