Files
html/se2.dat
2026-04-12 22:57:03 +02:00

436 lines
32 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Ethica — Send Engine</title>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
<style>
:root{--bg:#0f0e17;--surface:#1a1930;--surface2:#232145;--border:#2d2b55;--text:#e8e6f0;--text2:#a9a5c4;--text3:#6b6794;--purple:#a78bfa;--green:#10b981;--orange:#f59e0b;--red:#ef4444;--blue:#3b82f6;--cyan:#06b6d4}
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:'DM Sans',sans-serif;background:var(--bg);color:var(--text);overflow-x:hidden;font-size:13px}
.mono{font-family:'JetBrains Mono',monospace}
.container{max-width:1400px;margin:0 auto;padding:20px}
.header{display:flex;justify-content:space-between;align-items:center;margin-bottom:24px}
.header h1{font-size:20px;font-weight:700;display:flex;align-items:center;gap:10px}
.header h1 .dot{width:8px;height:8px;border-radius:50%;animation:blink 2s infinite}
@keyframes blink{0%,100%{opacity:1}50%{opacity:.3}}
.header .actions{display:flex;gap:8px}
.btn{padding:8px 16px;border:none;border-radius:8px;font-family:inherit;font-size:12px;font-weight:600;cursor:pointer;transition:.15s;display:flex;align-items:center;gap:6px}
.btn-purple{background:var(--purple);color:#fff}.btn-purple:hover{filter:brightness(1.15)}
.btn-green{background:var(--green);color:#fff}.btn-green:hover{filter:brightness(1.15)}
.btn-ghost{background:transparent;border:1px solid var(--border);color:var(--text2)}.btn-ghost:hover{border-color:var(--purple);color:var(--text)}
.btn-red{background:var(--red);color:#fff}.btn-red:hover{filter:brightness(1.15)}
.btn:disabled{opacity:.4;cursor:not-allowed}
/* KPI Cards */
.kpi-row{display:grid;grid-template-columns:repeat(5,1fr);gap:12px;margin-bottom:20px}
.kpi{background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:16px;position:relative;overflow:hidden}
.kpi::before{content:'';position:absolute;top:0;left:0;right:0;height:2px}
.kpi.green::before{background:var(--green)}.kpi.purple::before{background:var(--purple)}.kpi.orange::before{background:var(--orange)}.kpi.blue::before{background:var(--blue)}.kpi.cyan::before{background:var(--cyan)}
.kpi-label{font-size:11px;color:var(--text3);text-transform:uppercase;letter-spacing:.5px;margin-bottom:6px}
.kpi-value{font-size:24px;font-weight:700;font-family:'JetBrains Mono',monospace}
.kpi-sub{font-size:11px;color:var(--text2);margin-top:4px}
/* Grid layout */
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}
.grid-3{display:grid;grid-template-columns:2fr 1fr;gap:16px;margin-bottom:16px}
/* Cards */
.card{background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:20px}
.card-title{font-size:14px;font-weight:700;margin-bottom:14px;display:flex;justify-content:space-between;align-items:center}
.card-title .tag{font-size:10px;padding:3px 8px;border-radius:6px;font-weight:600;font-family:'JetBrains Mono',monospace}
.tag-live{background:rgba(16,185,129,.15);color:var(--green)}.tag-draft{background:rgba(245,158,11,.15);color:var(--orange)}
/* ISP Bars */
.isp-bar{margin-bottom:10px}
.isp-bar .isp-label{display:flex;justify-content:space-between;font-size:12px;margin-bottom:4px}
.isp-bar .bar-bg{height:8px;background:var(--surface2);border-radius:4px;overflow:hidden}
.isp-bar .bar-fill{height:100%;border-radius:4px;transition:width .6s}
.isp-gmail .bar-fill{background:var(--red)}.isp-yahoo .bar-fill{background:var(--purple)}.isp-ms .bar-fill{background:var(--blue)}.isp-other .bar-fill{background:var(--text3)}
/* Sender Table */
.sender-table{width:100%;border-collapse:collapse;font-size:12px}
.sender-table th{text-align:left;padding:8px 10px;color:var(--text3);font-size:10px;text-transform:uppercase;letter-spacing:.5px;border-bottom:1px solid var(--border)}
.sender-table td{padding:7px 10px;border-bottom:1px solid rgba(45,43,85,.5)}
.sender-table tr:hover{background:rgba(167,139,250,.05)}
.st-dot{width:6px;height:6px;border-radius:50%;display:inline-block;margin-right:6px}
.st-active{background:var(--green)}.st-failed{background:var(--red)}.st-idle{background:var(--text3)}
/* Send Log */
.log-area{background:var(--bg);border:1px solid var(--border);border-radius:8px;padding:12px;max-height:300px;overflow-y:auto;font-family:'JetBrains Mono',monospace;font-size:11px;line-height:1.7}
.log-sent{color:var(--green)}.log-fail{color:var(--red)}.log-info{color:var(--text3)}.log-warn{color:var(--orange)}
/* Campaign Queue */
.camp-item{display:flex;justify-content:space-between;align-items:center;padding:10px 0;border-bottom:1px solid rgba(45,43,85,.5)}
.camp-progress{width:120px;height:6px;background:var(--surface2);border-radius:3px;overflow:hidden}
.camp-progress .fill{height:100%;background:var(--green);border-radius:3px;transition:width .4s}
/* Test Send */
.test-send{background:var(--surface2);border:1px dashed var(--border);border-radius:10px;padding:20px;text-align:center}
.test-send input{background:var(--bg);border:1px solid var(--border);border-radius:8px;padding:8px 14px;color:var(--text);font-family:inherit;width:300px;text-align:center;font-size:13px}
.test-send input:focus{outline:none;border-color:var(--purple)}
/* Chatbot */
.chatbot-toggle{position:fixed;bottom:20px;right:20px;width:50px;height:50px;background:linear-gradient(135deg,#7c3aed,#a78bfa);border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 4px 20px rgba(124,58,237,.4);z-index:1000;font-size:20px;transition:.2s}
.chatbot-toggle:hover{transform:scale(1.1)}
.chatbot-panel{position:fixed;bottom:80px;right:20px;width:380px;height:500px;background:var(--surface);border:1px solid var(--border);border-radius:16px;box-shadow:0 8px 40px rgba(0,0,0,.5);z-index:1000;display:none;flex-direction:column;overflow:hidden}
.chatbot-panel.open{display:flex}
.chatbot-header{background:linear-gradient(135deg,#1a1a2e,#2d2b55);padding:14px 18px;display:flex;justify-content:space-between;align-items:center}
.chatbot-header h3{font-size:14px;font-weight:700}
.chatbot-messages{flex:1;overflow-y:auto;padding:14px;display:flex;flex-direction:column;gap:10px}
.msg{max-width:85%;padding:10px 14px;border-radius:12px;font-size:12px;line-height:1.6}
.msg.bot{background:var(--surface2);align-self:flex-start;border-bottom-left-radius:4px}
.msg.user{background:var(--purple);align-self:flex-end;border-bottom-right-radius:4px}
.chatbot-input{display:flex;gap:8px;padding:12px;border-top:1px solid var(--border)}
.chatbot-input input{flex:1;background:var(--bg);border:1px solid var(--border);border-radius:8px;padding:8px 12px;color:var(--text);font-family:inherit;font-size:12px}
.chatbot-input input:focus{outline:none;border-color:var(--purple)}
.chatbot-quick{display:flex;flex-wrap:wrap;gap:6px;padding:0 14px 10px}
.chatbot-quick button{background:var(--surface2);border:1px solid var(--border);border-radius:6px;padding:4px 10px;color:var(--text2);font-size:10px;cursor:pointer;font-family:inherit}
.chatbot-quick button:hover{border-color:var(--purple);color:var(--text)}
/* Toast */
.toast{position:fixed;top:20px;right:20px;background:var(--green);color:#fff;padding:12px 20px;border-radius:10px;font-weight:600;display:none;z-index:9999;box-shadow:0 4px 20px rgba(16,185,129,.3)}
@media(max-width:900px){.kpi-row{grid-template-columns:repeat(2,1fr)}.grid-2,.grid-3{grid-template-columns:1fr}}
</style>
</head>
<body>
<div id="toast" class="toast"></div>
<div class="container">
<!-- Header -->
<div class="header">
<h1><span class="dot" id="pmta-dot" style="background:var(--text3)"></span> Send Engine <span class="mono" style="font-size:12px;color:var(--text3)">PMTA v5.0r3</span></h1>
<div class="actions">
<button class="btn btn-ghost" onclick="loadStatus()">↻ Refresh</button>
<button class="btn btn-purple" onclick="openTestSend()">✉ Test Send</button>
</div>
</div>
<!-- KPI Row -->
<div class="kpi-row">
<div class="kpi green"><div class="kpi-label">PMTA Status</div><div class="kpi-value" id="k-pmta">—</div><div class="kpi-sub" id="k-pmta-sub">Checking...</div></div>
<div class="kpi purple"><div class="kpi-label">Senders Actifs</div><div class="kpi-value" id="k-senders">—</div><div class="kpi-sub" id="k-senders-sub">pool O365</div></div>
<div class="kpi blue"><div class="kpi-label">Capacité / Jour</div><div class="kpi-value" id="k-capacity">—</div><div class="kpi-sub">emails estimés</div></div>
<div class="kpi orange"><div class="kpi-label">Envoyés Aujourd'hui</div><div class="kpi-value" id="k-today">—</div><div class="kpi-sub" id="k-today-sub">sent + failed</div></div>
<div class="kpi cyan"><div class="kpi-label">Taux Succès</div><div class="kpi-value" id="k-rate">—</div><div class="kpi-sub">des dernières 24h</div></div>
</div>
<!-- ISP Distribution + Campaign Queue -->
<div class="grid-2">
<div class="card">
<div class="card-title">📊 Distribution ISP — Base HCP <span class="tag tag-live">LIVE</span></div>
<div id="isp-dist">
<div class="isp-bar isp-gmail"><div class="isp-label"><span>📧 Gmail</span><span id="isp-gmail-pct">—</span></div><div class="bar-bg"><div class="bar-fill" id="isp-gmail-bar" style="width:0"></div></div></div>
<div class="isp-bar isp-yahoo"><div class="isp-label"><span>📧 Yahoo / Hotmail</span><span id="isp-yahoo-pct">—</span></div><div class="bar-bg"><div class="bar-fill" id="isp-yahoo-bar" style="width:0"></div></div></div>
<div class="isp-bar isp-ms"><div class="isp-label"><span>📧 Microsoft (Outlook)</span><span id="isp-ms-pct">—</span></div><div class="bar-bg"><div class="bar-fill" id="isp-ms-bar" style="width:0"></div></div></div>
<div class="isp-bar isp-other"><div class="isp-label"><span>📧 Autres (topnet, menara, etc)</span><span id="isp-other-pct">—</span></div><div class="bar-bg"><div class="bar-fill" id="isp-other-bar" style="width:0"></div></div></div>
</div>
<div style="margin-top:14px;padding-top:12px;border-top:1px solid var(--border)">
<div style="font-size:11px;color:var(--text3);margin-bottom:8px">⚙️ PMTA Smart Routing</div>
<div style="font-size:11px;display:flex;gap:16px;color:var(--text2)">
<span>Gmail → bcg_local (warmup)</span>
<span>Yahoo → MTA-EU relay</span>
<span>Microsoft → O365 direct</span>
</div>
</div>
</div>
<div class="card">
<div class="card-title">📋 File d'envoi — Campaigns</div>
<div id="campaign-queue">
<div style="color:var(--text3);font-size:12px;text-align:center;padding:20px">Chargement...</div>
</div>
</div>
</div>
<!-- Sender Pool + Send Log -->
<div class="grid-3">
<div class="card">
<div class="card-title">👥 Sender Pool <span class="mono" style="font-size:11px;color:var(--text3)" id="sender-count">—</span></div>
<div style="max-height:300px;overflow-y:auto">
<table class="sender-table">
<thead><tr><th>Sender</th><th>Tenant</th><th>Status</th><th>Dernière Utilisation</th></tr></thead>
<tbody id="sender-tbody"><tr><td colspan="4" style="text-align:center;color:var(--text3)">Chargement...</td></tr></tbody>
</table>
</div>
</div>
<div class="card">
<div class="card-title">📜 Send Log (Live) <button class="btn btn-ghost" style="padding:4px 10px;font-size:10px" onclick="clearLog()">Clear</button></div>
<div class="log-area" id="send-log">
<div class="log-info">En attente de données...</div>
</div>
</div>
</div>
<!-- Test Send Section -->
<div class="card" id="test-section" style="display:none">
<div class="card-title">🧪 Test Send — Mode Sécurisé <span class="tag tag-draft">TEST ONLY</span></div>
<div class="test-send">
<p style="color:var(--text2);margin-bottom:12px;font-size:12px">Envoi test uniquement vers les adresses autorisées. Aucun envoi réel vers les HCPs.</p>
<select id="test-email" class="btn btn-ghost" style="background:var(--bg);color:var(--text);width:320px;text-align:center;padding:10px;font-size:13px;margin-bottom:12px">
<option value="yacineutt@gmail.com">yacineutt@gmail.com</option>
<option value="ymahboub@weval-consulting.com">ymahboub@weval-consulting.com</option>
<option value="joecloud@proton.me">joecloud@proton.me</option>
</select>
<div style="display:flex;gap:8px;justify-content:center;margin-top:10px">
<select id="test-template" class="btn btn-ghost" style="background:var(--bg);color:var(--text)">
<option value="consent">Template Consent</option>
<option value="product_launch">Template Lancement Produit</option>
<option value="webinar">Template Webinar</option>
</select>
<select id="test-campaign" class="btn btn-ghost" style="background:var(--bg);color:var(--text)">
<option value="4">Ethica Consent TN</option>
<option value="5">Ethica Consent DZ</option>
<option value="6">Ethica Consent MA</option>
</select>
<button class="btn btn-green" onclick="sendTest()" id="btn-test">▶ Envoyer Test</button>
</div>
<div id="test-result" style="margin-top:12px;font-size:12px"></div>
</div>
</div>
</div>
<!-- Chatbot Toggle + Panel -->
<div class="chatbot-toggle" onclick="toggleChat()" title="Ethica AI Assistant">🤖</div>
<div class="chatbot-panel" id="chatbot">
<div class="chatbot-header">
<h3>🤖 Ethica Send Assistant</h3>
<span style="cursor:pointer;opacity:.6" onclick="toggleChat()">✕</span>
</div>
<div class="chatbot-messages" id="chat-msgs">
<div class="msg bot">Bonjour ! Je suis l'assistant Ethica — expert <b>emailing pharma</b>, <b>marketing digital</b> et <b>deliverability ISP</b>.<br><br>Je peux vous aider avec :<br>• 💊 Stratégie marketing pharma HCP<br>• 📧 Deliverability ISP (Gmail, Yahoo, Microsoft)<br>• 🎯 Segmentation, A/B testing, ROI<br>• 📋 Consentement & réglementation Maghreb<br>• 🖥️ Utilisation de la plateforme Ethica<br>• 💰 Tarifs & capacités d'envoi</div>
</div>
<div class="chatbot-quick">
<button onclick="askBot('gmail')">Gmail</button>
<button onclick="askBot('yahoo')">Yahoo</button>
<button onclick="askBot('warmup')">Warmup</button>
<button onclick="askBot('pharma')">Stratégie Pharma</button>
<button onclick="askBot('marques')">18 Marques</button>
<button onclick="askBot('consentement')">Consent</button>
<button onclick="askBot('plateforme')">Aide Plateforme</button>
<button onclick="askBot('grille')">Tarifs</button>
</div>
<div class="chatbot-input">
<input id="chat-input" placeholder="Posez votre question..." onkeydown="if(event.key==='Enter')sendChat()">
<button class="btn btn-purple" onclick="sendChat()" style="padding:8px 12px">→</button>
</div>
</div>
<script>
const API = window.location.origin;
const SE_API = API + '/api/ethica-sendengine-api.php';
const SEND_API = API + '/api/ethica-send-api.php';
function toast(m){const t=document.getElementById('toast');t.textContent=m;t.style.display='block';setTimeout(()=>t.style.display='none',3000)}
function n(v){return(v||0).toLocaleString('fr')}
async function fetchJ(url){
try{const r=await fetch(url);return await r.json();}
catch(e){return null;}
}
// ═══ Load Status ═══
async function loadStatus(){
const [status, isp, senders, logs, campaigns] = await Promise.all([
fetchJ(SE_API+'?action=status'),
fetchJ(SE_API+'?action=isp_distribution'),
fetchJ(SE_API+'?action=senders&limit=20'),
fetchJ(SE_API+'?action=send_log&limit=30'),
fetchJ(SE_API+'?action=campaigns')
]);
// KPI
if(status && status.ok){
const s=status;
const dot=document.getElementById('pmta-dot');
dot.style.background=s.pmta_reachable?'var(--green)':'var(--red)';
document.getElementById('k-pmta').textContent=s.pmta_reachable?'ONLINE':'OFFLINE';
document.getElementById('k-pmta-sub').textContent=s.pmta_reachable?'10.1.0.2:25 reachable':'Connection failed';
document.getElementById('k-senders').textContent=n(s.senders_active);
document.getElementById('k-senders-sub').textContent=n(s.senders_total)+' total pool';
document.getElementById('k-capacity').textContent=n(s.capacity_per_day);
document.getElementById('k-today').textContent=n(s.sent_today);
document.getElementById('k-today-sub').textContent=n(s.sent_today_ok)+' sent, '+n(s.sent_today_fail)+' failed';
const rate=s.sent_today>0?Math.round(s.sent_today_ok/s.sent_today*100):100;
document.getElementById('k-rate').textContent=rate+'%';
}
// ISP
if(isp && isp.ok){
const d=isp.distribution;
const total=d.gmail+d.yahoo+d.microsoft+d.other;
if(total>0){
const pct=(v)=>Math.round(v/total*100);
document.getElementById('isp-gmail-pct').textContent=n(d.gmail)+' ('+pct(d.gmail)+'%)';
document.getElementById('isp-gmail-bar').style.width=pct(d.gmail)+'%';
document.getElementById('isp-yahoo-pct').textContent=n(d.yahoo)+' ('+pct(d.yahoo)+'%)';
document.getElementById('isp-yahoo-bar').style.width=pct(d.yahoo)+'%';
document.getElementById('isp-ms-pct').textContent=n(d.microsoft)+' ('+pct(d.microsoft)+'%)';
document.getElementById('isp-ms-bar').style.width=pct(d.microsoft)+'%';
document.getElementById('isp-other-pct').textContent=n(d.other)+' ('+pct(d.other)+'%)';
document.getElementById('isp-other-bar').style.width=pct(d.other)+'%';
}
}
// Senders
if(senders && senders.ok){
document.getElementById('sender-count').textContent=senders.senders.length+' loaded';
document.getElementById('sender-tbody').innerHTML=senders.senders.map(s=>`<tr>
<td><span class="st-dot ${s.status==='ok'?'st-active':'st-failed'}"></span><span class="mono" style="font-size:11px">${s.email.length>35?s.email.substr(0,35)+'...':s.email}</span></td>
<td style="color:var(--text3);font-size:11px">${(s.email.split('@')[1]||'').substr(0,20)}</td>
<td><span style="color:${s.status==='ok'?'var(--green)':'var(--red)'}">●</span> ${s.status}</td>
<td style="color:var(--text3);font-size:11px">${s.last_used||'—'}</td>
</tr>`).join('');
}
// Send Log
if(logs && logs.ok && logs.logs.length){
document.getElementById('send-log').innerHTML=logs.logs.map(l=>{
const cls=l.status==='sent'?'log-sent':l.status==='failed'?'log-fail':'log-info';
return `<div class="${cls}">[${(l.sent_at||'').substr(11,8)}] ${l.status.toUpperCase()} → ${l.email} via ${(l.sender_account||'').split('@')[0]} (${l.isp})</div>`;
}).join('');
}
// Campaigns
if(campaigns && campaigns.ok){
document.getElementById('campaign-queue').innerHTML=campaigns.campaigns.map(c=>{
const pct=c.target_count>0?Math.round((c.sent_count||0)/c.target_count*100):0;
const statusColor=c.status==='active'?'var(--green)':c.status==='draft'?'var(--orange)':'var(--text3)';
return `<div class="camp-item">
<div><strong>${c.name}</strong><br><span style="font-size:11px;color:var(--text3)">${c.target_pays} · ${n(c.target_count)} cibles · ${c.status}</span></div>
<div style="display:flex;align-items:center;gap:10px">
<span class="mono" style="font-size:11px;color:${statusColor}">${pct}%</span>
<div class="camp-progress"><div class="fill" style="width:${pct}%"></div></div>
</div>
</div>`;
}).join('')||'<div style="color:var(--text3);text-align:center;padding:16px">Aucune campagne</div>';
}
}
// ═══ Test Send ═══
function openTestSend(){
const s=document.getElementById('test-section');
s.style.display=s.style.display==='none'?'block':'none';
s.scrollIntoView({behavior:'smooth'});
}
async function sendTest(){
const btn=document.getElementById('btn-test');
const res=document.getElementById('test-result');
btn.disabled=true;btn.textContent='Envoi...';
res.innerHTML='<span style="color:var(--orange)">Envoi en cours via PMTA...</span>';
try{
const r=await fetch(SE_API+'?action=test_send&email='+encodeURIComponent(document.getElementById('test-email').value)+'&template='+
document.getElementById('test-template').value+'&campaign='+document.getElementById('test-campaign').value);
const d=await r.json();
if(d.ok && d.sent){
res.innerHTML='<span style="color:var(--green)">✓ Email envoyé via '+d.sender+' — vérifie la boîte yacineutt@gmail.com</span>';
toast('Test envoyé !');
} else {
res.innerHTML='<span style="color:var(--red)">✗ Échec: '+(d.error||'erreur inconnue')+'</span>';
}
}catch(e){
res.innerHTML='<span style="color:var(--red)">✗ Erreur réseau: '+e.message+'</span>';
}
btn.disabled=false;btn.textContent='▶ Envoyer Test';
}
function clearLog(){document.getElementById('send-log').innerHTML='<div class="log-info">Log effacé.</div>'}
// ═══ Chatbot ═══
function toggleChat(){document.getElementById('chatbot').classList.toggle('open')}
// ═══ ETHICA CHATBOT — Full Expert Knowledge Base ═══
const KB={
// ISP Deliverability
gmail:`<b>🔴 Gmail — Best Practices</b><br><br>• <b>Warmup</b>: 20/jour, +20/jour sur 2 semaines<br>• <b>List-Unsubscribe-Post</b> obligatoire (RFC 8058)<br>• <b>HTML ratio</b>: texte/html > 60%, max 1 image<br>• <b>SPF+DKIM+DMARC</b> alignés<br>• <b>Delay</b>: 3-6s entre envois<br>• <b>Limite</b>: 2000/jour/IP en warmup<br>• <b>ARC headers</b> si relay PMTA<br>• <b>Pas de spamwords</b>: "gratuit", "offre", "urgent"<br>• Gmail = 92% de notre base → priorité #1`,
yahoo:`<b>🟣 Yahoo/Hotmail</b><br><br>• <b>Precedence: bulk</b> header requis<br>• <b>List-Unsubscribe</b> (mailto: préféré)<br>• <b>Feedback loop</b>: feedback.yahoo.com<br>• <b>Rate limit</b>: ~5000/h par IP<br>• <b>TLS obligatoire</b><br>• Yahoo = ~5% de la base`,
microsoft:`<b>🔵 Microsoft/Outlook</b><br><br>• <b>JMRP</b> feedback loop requis<br>• <b>SNDS</b> (postmaster.live.com) monitoring<br>• <b>EOP filtering strict</b><br>• Delay 2-4s recommandé<br>• Microsoft = ~1.5% de la base`,
timing:`<b>⏰ Timing Optimal HCP Maghreb</b><br><br>• <b>Mardi-Jeudi</b>: meilleurs jours<br>• <b>9h-11h</b> locale: ouverture max médecins<br>• <b>Éviter</b>: weekends, fériés, vendredi PM<br>• <b>Fuseau</b>: TN/DZ/MA = GMT+1<br>• <b>Ramadan</b>: après iftar 20h-22h<br>• <b>Volume</b>: max 5000/h en warmup`,
bounce:`<b>📉 Gestion Bounces</b><br><br>• <b>Hard</b> (5.1.x): supprimer immédiatement<br>• <b>Soft</b> (4.x.x): 3 réessais sur 72h<br>• <b>Acceptable</b>: < 2% hard<br>• <b>Auto-cleanup</b>: email_valid='bounced'<br>• <b>Check</b>: mxtoolbox.com, dnsstuff.com`,
warmup:`<b>🔥 Plan Warmup PMTA</b><br><br><b>S1</b>: 50/sender/j → 2,500/j<br><b>S2</b>: 100 → 5,000/j<br><b>S3</b>: 150 → 7,500/j<br><b>S4</b>: 200 → 10,000/j<br><br>• Round-robin automatique<br>• Gmail first (92%)<br>• Si spam > 5% → STOP<br>• Inbox > 80% avant augmenter`,
template:`<b>📝 Template Email Tips</b><br><br>• <b>Subject</b>: max 50 chars, {{PRENOM}}<br>• <b>HTML</b>: max 100KB, 1 image, pas de JS<br>• <b>Plain text</b>: toujours inclure<br>• <b>Mobile</b>: 60% → responsive<br>• <b>CTA</b>: 1 seul, bouton > 44px<br>• <b>From</b>: "Ethica Santé"<br>• <b>Pas d'attachments</b>`,
// Pharma Marketing Strategy
pharma:`<b>💊 Stratégie Marketing Pharma HCP</b><br><br>• <b>Segmentation</b>: spécialité × pays × potentiel prescripteur<br>• <b>Fréquence</b>: max 2-3 emails/mois/HCP (fatigue)<br>• <b>Contenu ROI</b>: études cliniques > promo > invitations<br>• <b>Compliance</b>: mentions légales AMM + RCP obligatoires<br>• <b>KPI secteur</b>: open 18-35%, click 2.5-4.5%, unsub <0.25%<br>• <b>Veeva benchmark</b>: 40% open, 0.50-2€/email<br>• <b>Multi-channel</b>: email + terrain + webinar = x3 impact<br>• <b>Cycle</b>: lancement → rappel → fidélisation`,
hcp:`<b>👨‍⚕️ Ciblage HCP Maghreb</b><br><br>• <b>TN</b>: 22,541 — Tunis, Sfax, Sousse<br>• <b>DZ</b>: 13,706 — Alger, Oran, Constantine<br>• <b>MA</b>: 13,459 — Casa, Rabat, Marrakech<br>• <b>Top spécialités</b>: généralistes (volume), cardio/gastro (valeur)<br>• <b>Langue</b>: français, arabe dialectal pour SMS<br>• <b>Vérification</b>: Google Maps + registre officiel`,
consentement:`<b>📋 Consentement — Réglementation 3 Pays</b><br><br>• <b>Maroc</b>: Loi 09-08 CNDP — opt-in obligatoire<br>• <b>Tunisie</b>: Loi 63-2004 INPDP — opt-in strict, consentement séparé par canal<br>• <b>Algérie</b>: Loi 18-07/25-11 ANPDP — opt-in, DPO obligatoire<br>• <b>AUCUNE exception B2B</b><br>• <b>Sanctions</b>: 300K MAD (MA), 5 ans prison (TN)<br>• <b>Taux opt-in</b>: 20-30% digital, 40-50% tél<br>• <b>Durée campagne</b>: 3-6 mois pour 50%+`,
marques:`<b>🏷️ 18 Marques Ethica</b><br><br><b>TN (8)</b>: Doliprane 1g, Doliprane Vit C, Maxilase, Enterogermina, Telfast, Nasacort, + 2<br><b>MA (8)</b>: No Spa, Aspégic, Flagyl, Uvedose, Allegra, Nasacort, Enterogermina, + 1<br><b>DZ (4)</b>: Doliprane Ped, Telfast, Aspégic, Maxilase, Doliprane 1g<br><br>• <b>Sanofi OTC</b> (Opella): Doliprane, Maxilase, Enterogermina<br>• <b>Sanofi Rx</b>: Telfast, Nasacort, Flagyl, Allegra`,
roi:`<b>📊 ROI & KPIs Pharma</b><br><br>• <b>Open</b>: 18-35%, cible 25%+<br>• <b>Click</b>: 2.25-4.5%, cible 3%+<br>• <b>Bounce</b>: < 2% hard<br>• <b>Unsub</b>: < 0.25%<br>• <b>Cost/HCP</b>: 0.14-0.20€<br>• <b>Veeva</b>: 40% open mais 0.50-2€/email<br>• <b>Notre avantage</b>: 3-10x moins cher`,
// Digital Marketing
ab_testing:`<b>🧪 A/B Testing Email</b><br><br>• <b>Subject</b>: 2-3 variantes sur 10% avant full send<br>• <b>From</b>: "Ethica Santé" vs "Dr. [Nom]" vs "Info Médicale"<br>• <b>CTA</b>: couleur, texte, position<br>• <b>Timing</b>: mardi 9h vs jeudi 10h<br>• <b>Segment</b>: spécialistes vs généralistes<br>• <b>Min 500</b> par variante, 24h pour résultats`,
segmentation:`<b>🎯 Segmentation Avancée</b><br><br>• <b>Spécialité</b>: Telfast → allergologues+ORL+généralistes<br>• <b>Pays</b>: adapter langue, timing, références<br>• <b>Engagement</b>: openers vs non-openers<br>• <b>Source</b>: dabadoc (qualité) vs cnam_tn (volume)<br>• <b>Ville</b>: urbain vs rural<br>• <b>Suppression</b>: bounced, opted-out, already-sent`,
sms:`<b>📱 SMS Marketing HCP</b><br><br>• <b>Coût</b>: MA ~0.03€, TN ~0.01-0.05€, DZ ~0.03-0.05€<br>• <b>Sender ID</b>: "ETHICA" brandé<br>• <b>160 chars max</b>, pas d'accents si possible<br>• <b>10h-18h</b> uniquement, jamais weekend<br>• <b>"STOP au XXXXX"</b> obligatoire<br>• <b>Taux</b>: 15-25% consentement<br>• <b>Credentials OVH</b>: chez Yanis`,
landing:`<b>🌐 Landing Pages Conversion</b><br><br>• <b>Consent</b>: consent.wevup.app<br>• <b>Éléments</b>: identité, finalité, cases non pré-cochées<br>• <b>Mobile first</b> (60%+)<br>• <b>Load < 3s</b><br>• <b>CTA unique</b><br>• <b>Trust signals</b>: logos + mentions légales<br>• <b>Tracking</b>: pixel + UTM`,
// Plateforme Ethica — Aide
plateforme:`<b>🖥️ Plateforme Ethica — Guide</b><br><br>10 modules sur <b>ethica.wevup.app</b>:<br><br>• <b>Dashboard</b>: KPIs globaux<br>• <b>Scraping</b>: sources HCP multi-pays<br>• <b>Validation</b>: pipeline qualité<br>• <b>Campagnes</b>: 18 marques × 3 pays<br>• <b>Send Engine</b>: PMTA + sender pool<br>• <b>Tracking</b>: opens, clicks, bounces<br>• <b>Consents</b>: opt-in/opt-out<br>• <b>Sentinel</b>: actions automatisées<br>• <b>Tokens</b>: tokens consent<br>• <b>Exports</b>: téléchargement`,
campagne_creation:`<b>📧 Créer une Campagne</b><br><br>1. Aller dans <b>Campagnes</b> → sélectionner marque + pays<br>2. Paramétrer objet, from name, template, ISP<br>3. Uploader ou sélectionner creative HTML<br>4. Preview pour vérifier le rendu<br>5. Ajuster la vitesse (50-500/h)<br>6. <b>Test d'abord</b> vers adresse autorisée<br>7. Lancer <b>uniquement après validation Yacine</b>`,
send_engine_help:`<b>⚡ Send Engine — Fonctionnement</b><br><br>• <b>PMTA v5.0r3</b> sur S204 (10.1.0.2:25)<br>• <b>115 comptes O365</b> rotation round-robin<br>• <b>50 emails/sender/jour</b><br>• <b>2,500/jour</b> capacité conservative<br>• <b>Smart routing</b>: Gmail→bcg_local, Yahoo→relay<br>• <b>Anti-spam</b>: Exchange headers, List-Unsubscribe<br>• Logs temps réel dans le panel`,
test_send_help:`<b>🧪 Test Send — Mode Sécurisé</b><br><br>Adresses autorisées uniquement:<br>• yacineutt@gmail.com<br>• ymahboub@weval-consulting.com<br>• joecloud@proton.me<br><br>• Sujet préfixé <b>[TEST]</b><br>• Sender aléatoire du pool<br>• Logé avec campaign_id=0<br>• <b>AUCUN envoi réel HCP</b> sans validation`,
grille:`<b>💰 Grille Tarifaire Ethica</b><br><br>• <b>1-15K/mois</b>: 2,800€ (0.187€/email)<br>• <b>15-30K/mois</b>: 4,200€ (0.140€)<br>• <b>30-45K/mois</b>: 6,000€ (0.133€)<br>• <b>+15K supp</b>: +1,800€ (0.120€)<br>• Engagement <b>12 mois</b><br>• Inclus: base, ciblage, template, routage, KPIs, dashboard<br>• <b>Consent</b>: 3,700€ séparé`,
capacite:`<b>⚙️ Capacité Actuelle</b><br><br>• <b>115 senders</b> / 1,364 pool<br>• <b>PMTA ONLINE</b> (S204:25)<br>• <b>2,500/jour</b> conservative<br>• Consent 28K → <b>~11 jours</b><br>• Promo 45K/mois → <b>57% capacité = OK</b><br>• ISP: Gmail 92%, Yahoo 5.5%<br>• <b>27,854 tokens</b> générés`
};
// Keyword → topic mapping
const KEYWORDS = [
[['gmail','google'], 'gmail'],
[['yahoo','hotmail'], 'yahoo'],
[['microsoft','outlook','office'], 'microsoft'],
[['timing','heure','quand','horaire','jour'], 'timing'],
[['bounce','rebond','rejet'], 'bounce'],
[['warmup','warm','chauffe','montee'], 'warmup'],
[['template','html','subject','objet','sujet','creative'],'template'],
[['pharma','strateg','marketing pharma','labo','laboratoire'],'pharma'],
[['hcp','medecin','docteur','ciblage','cible','specialite'],'hcp'],
[['consent','consentement','rgpd','cndp','opt-in','loi'],'consentement'],
[['marque','brand','doliprane','telfast','maxilase','ethica marque','18 marques','produit'],'marques'],
[['roi','kpi','performance','resultat','taux','ouverture','clic','open rate'],'roi'],
[['ab test','a/b','test','split','variante'],'ab_testing'],
[['segment','ciblage avance','filtr'], 'segmentation'],
[['sms','texto','telephone','mobile'], 'sms'],
[['landing','page','conversion','consent.wevup'],'landing'],
[['plateforme','module','aide','help','comment','interface','ethica.wevup'],'plateforme'],
[['campagne','creer','creation','lancer'], 'campagne_creation'],
[['send engine','moteur','pmta','envoi','sender','envoyer'],'send_engine_help'],
[['test send','test envoi','tester'], 'test_send_help'],
[['tracking','open','click','suivi','pixel'], 'tracking_help'],
[['tarif','prix','grille','cout','devis','combien'], 'grille'],
[['capacit','volume','vitesse','debit','jour'],'capacite'],
];
function askBot(topic){
const labels={gmail:'Gmail tips',yahoo:'Yahoo tips',microsoft:'Microsoft tips',timing:'Timing optimal',bounce:'Bounces',warmup:'Plan warmup',template:'Template tips',pharma:'Stratégie pharma',hcp:'Ciblage HCP',consentement:'Consentement',marques:'18 Marques Ethica',roi:'ROI & KPIs',ab_testing:'A/B Testing',segmentation:'Segmentation',sms:'SMS marketing',landing:'Landing pages',plateforme:'Aide plateforme',campagne_creation:'Créer campagne',send_engine_help:'Send Engine',test_send_help:'Test send',grille:'Tarifs',capacite:'Capacité'};
addMsg(labels[topic]||topic,'user');
setTimeout(()=>addMsg(KB[topic]||'Sujet non trouvé.','bot'),300);
}
function sendChat(){
const inp=document.getElementById('chat-input');
const q=inp.value.trim();if(!q)return;
inp.value='';addMsg(q,'user');
setTimeout(()=>{
const ql=q.toLowerCase();
let found=false;
for(const [keys,topic] of KEYWORDS){
if(keys.some(k=>ql.includes(k))){addMsg(KB[topic],'bot');found=true;break;}
}
if(!found) addMsg('Je peux vous aider sur ces sujets :<br><br><b>📧 Deliverability</b>: gmail, yahoo, microsoft, bounce, warmup, template<br><b>💊 Pharma</b>: stratégie, ciblage HCP, marques, ROI, consentement<br><b>🎯 Digital</b>: A/B testing, segmentation, SMS, landing pages<br><b>🖥️ Plateforme</b>: aide, campagnes, send engine, test, tracking, tarifs, capacité','bot');
},400);
}
function addMsg(text,role){
const d=document.getElementById('chat-msgs');
d.innerHTML+=`<div class="msg ${role}">${text}</div>`;
d.scrollTop=d.scrollHeight;
}
// Init
loadStatus();
setInterval(loadStatus,30000);
</script>
</body>
</html>