Files
wevia-brain/s89-arsenal-screens/predictive-send-window.html
2026-04-12 23:01:36 +02:00

227 lines
18 KiB
HTML
Executable File
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>WEVADS • Predictive Send Window</title>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
<style>
:root{--bg:#060a14;--s:#0c1220;--s2:#111827;--b:#1e293b;--t:#e2e8f0;--d:#64748b;--cy:#22d3ee;--gn:#34d399;--am:#fbbf24;--rd:#f87171;--pu:#a78bfa;--bl:#60a5fa;--pk:#f472b6;--og:#fb923c}
.light{--bg:#f0f2f5;--s:#ffffff;--s2:#f8fafc;--b:#e2e8f0;--t:#1e293b;--d:#64748b}.light input,.light select,.light textarea{background:#f8fafc!important;border-color:#e2e8f0!important;color:#1e293b!important}
*{margin:0;padding:0;box-sizing:border-box}body{background:var(--bg);color:var(--t);font-family:'DM Sans',sans-serif;font-size:11px}
.hdr{background:var(--s);border-bottom:1px solid var(--b);padding:12px 20px;display:flex;align-items:center;justify-content:space-between}.hdr h1{font-size:16px;font-weight:700}.hdr h1 span{color:var(--gn)}
.wrap{padding:16px;max-width:1400px;margin:0 auto}
.stats{display:grid;grid-template-columns:repeat(6,1fr);gap:10px;margin-bottom:16px}
.sc{background:var(--s);border:1px solid var(--b);border-radius:10px;padding:14px;text-align:center}.sc .n{font-family:'JetBrains Mono',monospace;font-size:22px;font-weight:700}.sc .l{font-size:9px;text-transform:uppercase;color:var(--d);margin-top:4px}
.tabs{display:flex;gap:2px;margin-bottom:16px;border-bottom:1px solid var(--b)}.tab{padding:8px 16px;cursor:pointer;font-size:10px;font-weight:600;text-transform:uppercase;color:var(--d);border-bottom:2px solid transparent}.tab:hover{color:var(--t)}.tab.active{color:var(--gn);border-color:var(--gn)}
.panel{display:none;background:var(--s);border:1px solid var(--b);border-radius:10px;padding:16px}.panel.active{display:block}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:12px}.grid3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px}
.form-row{margin-bottom:10px}.form-row label{display:block;font-size:9px;text-transform:uppercase;color:var(--d);margin-bottom:4px}
.form-row input,.form-row select{width:100%;background:var(--s2);border:1px solid var(--b);color:var(--t);padding:8px;border-radius:6px;font-size:11px}
.btn{padding:8px 16px;border-radius:6px;border:1px solid var(--b);background:var(--s2);color:var(--t);cursor:pointer;font-size:10px;font-weight:600}.btn:hover{border-color:var(--gn)}
.btn-gn{background:rgba(52,211,153,.15);border-color:var(--gn);color:var(--gn)}
.badge{font-size:8px;padding:2px 6px;border-radius:3px;font-weight:600}.badge-gn{background:rgba(52,211,153,.15);color:var(--gn)}.badge-am{background:rgba(251,191,36,.15);color:var(--am)}.badge-rd{background:rgba(248,113,113,.15);color:var(--rd)}.badge-cy{background:rgba(34,211,238,.15);color:var(--cy)}
table{width:100%;border-collapse:collapse;font-size:10px}th{text-align:left;color:var(--d);text-transform:uppercase;font-size:9px;padding:6px 8px;border-bottom:1px solid var(--b)}td{padding:6px 8px;border-bottom:1px solid rgba(30,41,59,.3)}
.progress{height:6px;background:var(--s2);border-radius:3px}.progress-fill{height:100%;border-radius:3px}
.heatmap{display:grid;grid-template-columns:repeat(24,1fr);gap:1px}.hm-cell{aspect-ratio:1;border-radius:2px;display:flex;align-items:center;justify-content:center;font-size:7px;font-family:'JetBrains Mono',monospace;cursor:pointer}
.tz-bar{display:flex;gap:1px;margin-bottom:6px}.tz-segment{height:30px;border-radius:3px;display:flex;align-items:center;justify-content:center;font-size:8px;font-weight:600;color:#fff}
.toggle-btn{position:fixed;top:10px;right:56px;z-index:9999;background:rgba(17,24,39,.9);border:1px solid #1e293b;border-radius:50%;width:30px;height:30px;display:flex;align-items:center;justify-content:center;padding:0;cursor:pointer;font-size:13px;color:#e2e8f0}
@media(max-width:900px){.stats{grid-template-columns:repeat(3,1fr)}.grid2,.grid3{grid-template-columns:1fr}}
</style>
</head><body>
<!-- nav-pills-bar -->
<div class="hdr"><div><h1>📈 WEVADS • <span>Predictive Send Window</span></h1><span style="font-size:10px;color:var(--d)">Envoi prédictif IA — P(open) = ∫ Behavioral_Data(t) dt — Maximiser CTR par timing optimal</span></div><div style="display:flex;gap:8px;align-items:center"><span class="badge badge-gn">● PREDICTING</span><span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--d)" id="clock"></span></div></div>
<div class="wrap">
<div class="stats">
<div class="sc"><div class="n" style="color:var(--gn)">34.2%</div><div class="l">Open Rate (prédit)</div></div>
<div class="sc"><div class="n" style="color:var(--gn)">+8.7%</div><div class="l">vs envoi standard</div></div>
<div class="sc"><div class="n" style="color:var(--cy)">6</div><div class="l">Timezones</div></div>
<div class="sc"><div class="n" style="color:var(--am)">09:14</div><div class="l">Peak heure EU</div></div>
<div class="sc"><div class="n" style="color:var(--pu)">847K</div><div class="l">Profils analysés</div></div>
<div class="sc"><div class="n" style="color:var(--pk)">14j</div><div class="l">Historique appris</div></div>
</div>
<div class="tabs">
<div class="tab active" onclick="showTab('heatmap')">🔥 Heatmap</div>
<div class="tab" onclick="showTab('predict')">🧠 Prédiction</div>
<div class="tab" onclick="showTab('throttle')">⚡ Throttle IA</div>
<div class="tab" onclick="showTab('tz')">🌍 Timezones</div>
<div class="tab" onclick="showTab('drilldown')">📊 Drilldown</div>
</div>
<div class="panel active" id="tab-heatmap">
<h3 style="font-size:12px;margin-bottom:10px">🔥 Heatmap P(open) — Par heure × jour</h3>
<div style="display:flex;margin-bottom:4px;padding-left:30px"><div style="display:grid;grid-template-columns:repeat(24,1fr);gap:1px;flex:1;font-size:7px;color:var(--d);text-align:center" id="hm-hours"></div></div>
<div id="heatmap-container"></div>
<div style="display:flex;justify-content:space-between;margin-top:8px;font-size:9px;color:var(--d)">
<div>🟢 P(open) élevé (>30%)</div><div>🟡 Moyen (15-30%)</div><div>🔴 Faible (<15%)</div>
</div>
<div class="grid3" style="margin-top:16px">
<div style="background:var(--s2);border:1px solid var(--b);border-radius:8px;padding:12px;text-align:center"><div style="font-size:20px">🏆</div><div style="font-weight:700;color:var(--gn);margin-top:4px">Mardi 09:00-10:00</div><div style="font-size:9px;color:var(--d)">P(open) = 38.4% — Best window</div></div>
<div style="background:var(--s2);border:1px solid var(--b);border-radius:8px;padding:12px;text-align:center"><div style="font-size:20px">🥈</div><div style="font-weight:700;color:var(--gn);margin-top:4px">Jeudi 14:00-15:00</div><div style="font-size:9px;color:var(--d)">P(open) = 35.2%</div></div>
<div style="background:var(--s2);border:1px solid var(--b);border-radius:8px;padding:12px;text-align:center"><div style="font-size:20px">🥉</div><div style="font-weight:700;color:var(--gn);margin-top:4px">Mercredi 10:00-11:00</div><div style="font-size:9px;color:var(--d)">P(open) = 33.8%</div></div>
</div>
</div>
<div class="panel" id="tab-predict">
<div class="grid2">
<div>
<h3 style="font-size:12px;margin-bottom:10px;color:var(--gn)">🧠 Modèle prédictif</h3>
<div style="background:var(--bg);border:1px solid var(--b);border-radius:8px;padding:14px;font-family:'JetBrains Mono',monospace;font-size:10px;line-height:2;margin-bottom:12px">
<span style="color:var(--gn);font-weight:700">P(open|user,t) = Σᵢ wᵢ × fᵢ(user, t)</span><br>
<br>
<span style="color:var(--d)">Features:</span><br>
f₁ = <span style="color:var(--cy)">timezone_match(user.tz, send_time)</span> w=0.25<br>
f₂ = <span style="color:var(--cy)">historical_open_hour(user, hour)</span> w=0.30<br>
f₃ = <span style="color:var(--cy)">day_of_week_preference(user, dow)</span> w=0.15<br>
f₄ = <span style="color:var(--cy)">device_activity_pattern(user, t)</span> w=0.15<br>
f₅ = <span style="color:var(--cy)">isp_congestion(isp, t)</span> w=0.10<br>
f₆ = <span style="color:var(--cy)">recency_decay(last_open, t)</span> w=0.05<br>
<br>
<span style="color:var(--am)">Training: 847K profils × 14 jours = 11.8M datapoints</span>
</div>
<div class="form-row"><label>Simuler pour</label><select><option>Campagne FOMO — Hotmail US (4.1M)</option><option>Newsletter — Gmail DE (1.2M)</option><option>B2B — Mix EU</option></select></div>
<div class="form-row"><label>Objectif</label><select><option>Maximiser Open Rate</option><option>Maximiser CTR</option><option>Minimiser Spam Score</option></select></div>
<button class="btn btn-gn" style="width:100%" onclick="alert('Prédiction: Envoi optimal Mardi 09:14 CET → P(open)=34.2%')">🧠 Prédire meilleur créneau</button>
</div>
<div>
<h3 style="font-size:12px;margin-bottom:10px">📊 Résultat prédiction</h3>
<table><thead><tr><th>Créneau</th><th>P(open)</th><th>P(click)</th><th>ISP load</th><th>Score</th></tr></thead><tbody>
<tr style="background:rgba(52,211,153,.05)"><td style="font-weight:700;color:var(--gn)">Mar 09:00-10:00</td><td style="color:var(--gn)">38.4%</td><td>4.8%</td><td style="color:var(--gn)">Low</td><td style="color:var(--gn)">★★★★★</td></tr>
<tr><td>Jeu 14:00-15:00</td><td>35.2%</td><td>4.2%</td><td>Med</td><td>★★★★</td></tr>
<tr><td>Mer 10:00-11:00</td><td>33.8%</td><td>3.9%</td><td style="color:var(--gn)">Low</td><td>★★★★</td></tr>
<tr><td>Lun 08:00-09:00</td><td>31.5%</td><td>3.5%</td><td style="color:var(--am)">High</td><td>★★★</td></tr>
<tr><td>Ven 11:00-12:00</td><td>29.8%</td><td>3.2%</td><td>Med</td><td>★★★</td></tr>
<tr><td style="color:var(--rd)">Sam 02:00-03:00</td><td style="color:var(--rd)">8.2%</td><td style="color:var(--rd)">0.4%</td><td style="color:var(--gn)">Low</td><td></td></tr>
</tbody></table>
</div>
</div>
</div>
<div class="panel" id="tab-throttle">
<h3 style="font-size:12px;margin-bottom:12px">⚡ Throttle IA — Débit adaptatif en temps réel</h3>
<div class="grid2">
<div>
<div style="background:var(--bg);border:1px solid var(--b);border-radius:8px;padding:14px;font-size:10px;line-height:2;margin-bottom:10px">
<div style="font-weight:700;color:var(--gn);margin-bottom:6px">Débit actuel : <span style="font-family:'JetBrains Mono',monospace;font-size:18px">47 emails/min</span></div>
Le throttle IA ajuste le débit en temps réel :<br>
<strong style="color:var(--gn)">Fenêtre optimale</strong> (09-10h) → 80-100 emails/min<br>
<strong style="color:var(--am)">Fenêtre moyenne</strong> (14-16h) → 40-60 emails/min<br>
<strong style="color:var(--rd)">Fenêtre basse</strong> (22-06h) → 10-20 emails/min<br>
<strong style="color:var(--pu)">ISP congestion</strong> détectée → auto-reduce -30%
</div>
<div class="form-row"><label>Mode throttle</label><select><option>🧠 Full IA (auto-adaptatif)</option><option>📈 Progressif (montée douce)</option><option>⚡ Burst (rapide puis pause)</option><option>🔒 Fixe (vitesse constante)</option></select></div>
<div class="form-row"><label>Max emails/min</label><input type="number" value="100"></div>
<div class="form-row"><label>Réaction ISP throttle</label><select><option>Auto-reduce -30% pendant 5min</option><option>Pause 2min puis retry</option><option>Switch méthode d'envoi</option></select></div>
</div>
<div>
<h4 style="font-size:11px;margin-bottom:8px">Courbe de débit — Dernières 6h</h4>
<div style="display:flex;gap:2px;align-items:flex-end;height:120px;padding:0 4px">
<div style="flex:1;background:var(--s2);border-radius:2px 2px 0 0;height:20%"></div>
<div style="flex:1;background:var(--s2);border-radius:2px 2px 0 0;height:15%"></div>
<div style="flex:1;background:var(--gn);border-radius:2px 2px 0 0;height:45%"></div>
<div style="flex:1;background:var(--gn);border-radius:2px 2px 0 0;height:85%"></div>
<div style="flex:1;background:var(--gn);border-radius:2px 2px 0 0;height:95%"></div>
<div style="flex:1;background:var(--gn);border-radius:2px 2px 0 0;height:90%"></div>
<div style="flex:1;background:var(--am);border-radius:2px 2px 0 0;height:60%"></div>
<div style="flex:1;background:var(--am);border-radius:2px 2px 0 0;height:55%"></div>
<div style="flex:1;background:var(--gn);border-radius:2px 2px 0 0;height:70%"></div>
<div style="flex:1;background:var(--gn);border-radius:2px 2px 0 0;height:65%"></div>
<div style="flex:1;background:var(--am);border-radius:2px 2px 0 0;height:50%"></div>
<div style="flex:1;background:var(--s2);border-radius:2px 2px 0 0;height:30%"></div>
</div>
<div style="display:flex;justify-content:space-between;font-size:8px;color:var(--d);margin-top:4px"><span>-6h</span><span>-5h</span><span>-4h</span><span>-3h</span><span>-2h</span><span>-1h</span><span>Now</span></div>
</div>
</div>
</div>
<div class="panel" id="tab-tz">
<h3 style="font-size:12px;margin-bottom:10px">🌍 Envoi par timezone</h3>
<div class="tz-bar">
<div class="tz-segment" style="flex:3;background:var(--gn)" title="CET (UTC+1)">CET 🇩🇪🇫🇷🇮🇹 — 65%</div>
<div class="tz-segment" style="flex:1;background:var(--bl)" title="GMT (UTC+0)">GMT 🇬🇧 — 15%</div>
<div class="tz-segment" style="flex:1;background:var(--pu)" title="EET (UTC+2)">EET — 10%</div>
<div class="tz-segment" style="flex:0.5;background:var(--og)" title="EST (UTC-5)">EST — 5%</div>
<div class="tz-segment" style="flex:0.5;background:var(--pk)" title="Other">Other — 5%</div>
</div>
<table><thead><tr><th>Timezone</th><th>Leads</th><th>Best window (local)</th><th>P(open)</th><th>Envoi planifié</th></tr></thead><tbody>
<tr><td>CET (UTC+1) 🇩🇪🇫🇷🇮🇹🇪🇸🇳🇱</td><td>550K</td><td style="color:var(--gn)">09:00-10:00 local</td><td style="color:var(--gn)">38.4%</td><td>08:00 UTC</td></tr>
<tr><td>GMT (UTC+0) 🇬🇧🇵🇹</td><td>127K</td><td style="color:var(--gn)">09:30-10:30 local</td><td style="color:var(--gn)">36.1%</td><td>09:30 UTC</td></tr>
<tr><td>EET (UTC+2) 🇬🇷🇫🇮🇷🇴</td><td>85K</td><td style="color:var(--gn)">10:00-11:00 local</td><td>33.5%</td><td>08:00 UTC</td></tr>
<tr><td>EST (UTC-5) 🇺🇸</td><td>42K</td><td>14:00-15:00 local</td><td>31.2%</td><td>19:00 UTC</td></tr>
<tr><td>Autres</td><td>43K</td><td>Varies</td><td>28.0%</td><td>Mixed</td></tr>
</tbody></table>
</div>
<div class="panel" id="tab-drilldown">
<h3 style="font-size:12px;margin-bottom:12px">📊 Drilldown — Impact du Predictive Send</h3>
<div class="grid2">
<div>
<table><thead><tr><th>Métrique</th><th>Envoi standard</th><th>Predictive Send</th><th>Gain</th></tr></thead><tbody>
<tr><td>Open Rate</td><td>25.5%</td><td style="color:var(--gn)">34.2%</td><td style="color:var(--gn)">+8.7%</td></tr>
<tr><td>Click Rate</td><td>2.8%</td><td style="color:var(--gn)">4.6%</td><td style="color:var(--gn)">+1.8%</td></tr>
<tr><td>Conversion Rate</td><td>0.4%</td><td style="color:var(--gn)">0.7%</td><td style="color:var(--gn)">+75%</td></tr>
<tr><td>Unsubscribe Rate</td><td>0.8%</td><td style="color:var(--gn)">0.5%</td><td style="color:var(--gn)">-37%</td></tr>
<tr><td>Revenue / 100K sends</td><td>€4,200</td><td style="color:var(--gn)">€7,100</td><td style="color:var(--gn)">+69%</td></tr>
</tbody></table>
</div>
<div>
<h4 style="font-size:11px;margin-bottom:8px">ROI Predictive vs Standard</h4>
<div style="text-align:center;padding:20px;background:var(--bg);border:1px solid var(--b);border-radius:8px">
<div style="font-size:32px;font-family:'JetBrains Mono',monospace;font-weight:700;color:var(--gn)">+69%</div>
<div style="font-size:11px;color:var(--d);margin-top:4px">Revenue uplift avec Predictive Send</div>
<div style="font-size:9px;color:var(--d);margin-top:8px">Basé sur 847K envois × 14 jours d'historique</div>
</div>
</div>
</div>
</div>
</div>
<script>
function showTab(id){document.querySelectorAll('.tab').forEach(t=>t.classList.remove('active'));document.querySelectorAll('.panel').forEach(p=>p.classList.remove('active'));document.getElementById('tab-'+id).classList.add('active');event.target.classList.add('active')}
// Generate hours header
var hh=document.getElementById('hm-hours');for(var h=0;h<24;h++)hh.innerHTML+='<div>'+String(h).padStart(2,'0')+'</div>';
// Generate heatmap
var days=['Lun','Mar','Mer','Jeu','Ven','Sam','Dim'];
var hmc=document.getElementById('heatmap-container');
days.forEach(function(d){
var row='<div style="display:flex;align-items:center"><div style="width:30px;font-size:9px;color:var(--d)">'+d+'</div><div class="heatmap">';
for(var h=0;h<24;h++){
var c=p>30?'rgba(52,211,153,':p>20?'rgba(251,191,36,':p>10?'rgba(251,146,60,':'rgba(248,113,113,';
row+='<div class="hm-cell" style="background:'+c+(.3+p/50)+')">'+Math.round(p)+'</div>';
}
row+='</div></div>';hmc.innerHTML+=row;
});
setInterval(function(){document.getElementById('clock').textContent=new Date().toLocaleTimeString('fr-FR')},1000);
// === ARSENAL API INJECTION ===
async function arsenalLoad() {
try {
const r = await fetch('/api/predictive-send.php?action=windows');
const d = await r.json();
console.log('Arsenal API loaded:', d);
if (d.data) arsenalRender(d.data);
else if (d.results) arsenalRender(d.results);
else arsenalRender(d);
} catch(e) { console.error('Arsenal API error:', e); }
}
function arsenalRender(data) {
// Update any stat counters on the page
document.querySelectorAll('[data-stat]').forEach(el => {
const key = el.dataset.stat;
if (data[key] !== undefined) el.textContent = data[key];
});
// Update tables if present
const tbody = document.querySelector('tbody');
if (tbody && Array.isArray(data)) {
tbody.innerHTML = data.slice(0,50).map(row => {
const vals = Object.values(row);
return '<tr>' + vals.map(v => '<td>' + (v ?? '-') + '</td>').join('') + '</tr>';
}).join('');
}
}
arsenalLoad();
setInterval(arsenalLoad, 30000);
async function getHeatmap(){const r=await fetch('/api/predictive-send.php?action=heatmap');return r.json();}
async function getRecommend(isp){const r=await fetch('/api/predictive-send.php?action=recommend&isp='+encodeURIComponent(isp));return r.json();}
</script><script src="arsenal-common.js"></script>
</script>
</body></html>