From 7db823d9055cd3ba62ce44969b3af5dfa0de44df Mon Sep 17 00:00:00 2001 From: Yacine Mahboub Date: Fri, 6 Mar 2026 16:10:15 +0100 Subject: [PATCH] FIX: Tracking screens - GOLD restore + tracking-white.css minimal --- public/tracking-arsenal.html | 48 ++- public/tracking-bridge.php | 31 +- public/tracking-dashboard.php | 63 ++- public/tracking-deploy.php | 44 +- public/tracking-global-dashboard.php | 41 +- public/tracking-manager.php | 34 +- public/tracking-system-standalone.php | 589 ++++++++++++++------------ public/tracking-white.css | 3 + 8 files changed, 526 insertions(+), 327 deletions(-) create mode 100644 public/tracking-white.css diff --git a/public/tracking-arsenal.html b/public/tracking-arsenal.html index 768c460d..b2f8b0e9 100644 --- a/public/tracking-arsenal.html +++ b/public/tracking-arsenal.html @@ -1,12 +1,40 @@ - - -WEVADS - Tracking Command Center โ€” Arsenal - - - - - - + +Tracking Command Center โ€” Arsenal +
๐Ÿ“ก

Tracking Command Center

@@ -295,6 +323,4 @@ async function fullRefresh() { fullRefresh(); setInterval(fullRefresh, 60000); - diff --git a/public/tracking-bridge.php b/public/tracking-bridge.php index 3b61f23c..33eda9da 100644 --- a/public/tracking-bridge.php +++ b/public/tracking-bridge.php @@ -9,8 +9,35 @@ $GLOBALS["no_auth_check_wrapper"] = false; // Keep auth Tracking Bridge โ€” ADX Arsenal - - +
diff --git a/public/tracking-dashboard.php b/public/tracking-dashboard.php index 72fb2ebb..7507c22a 100644 --- a/public/tracking-dashboard.php +++ b/public/tracking-dashboard.php @@ -21,11 +21,11 @@ if (isset($_GET['action'])) { for ($i = $days - 1; $i >= 0; $i--) { $date = date('Y-m-d', strtotime("-{$i} days")); $dateLabel = date('M j', strtotime($date)); - $clicks = $db->query("SELECT COUNT(*) FROM admin.v_tracking_clicks WHERE DATE(event_time) = '{$date}'")->fetchColumn(); - $opens = $db->query("SELECT COUNT(*) FROM admin.v_tracking_opens WHERE DATE(event_time) = '{$date}'")->fetchColumn(); - $leads = $db->query("SELECT COUNT(*) FROM admin.v_tracking_leads WHERE DATE(event_time) = '{$date}'")->fetchColumn(); - $unsubs = $db->query("SELECT COUNT(*) FROM admin.v_tracking_unsubs WHERE DATE(event_time) = '{$date}'")->fetchColumn(); - $bounces = $db->query("SELECT COUNT(*) FROM admin.v_tracking_bounces WHERE DATE(event_time) = '{$date}'")->fetchColumn(); + $clicks = $db->query("SELECT COUNT(*) FROM actions.clicks WHERE DATE(action_time) = '{$date}'")->fetchColumn(); + $opens = $db->query("SELECT COUNT(*) FROM actions.opens WHERE DATE(action_time) = '{$date}'")->fetchColumn(); + $leads = $db->query("SELECT COUNT(*) FROM actions.leads WHERE DATE(action_time) = '{$date}'")->fetchColumn(); + $unsubs = $db->query("SELECT COUNT(*) FROM actions.unsubscribes WHERE DATE(action_time) = '{$date}'")->fetchColumn(); + $bounces = $db->query("SELECT COUNT(*) FROM actions.optouts WHERE DATE(action_time) = '{$date}'")->fetchColumn(); $stats[] = ['date' => $date, 'label' => $dateLabel, 'clicks' => intval($clicks), 'opens' => intval($opens), 'leads' => intval($leads), 'unsubs' => intval($unsubs), 'bounces' => intval($bounces)]; } echo json_encode(['status' => 'success', 'data' => $stats]); @@ -35,29 +35,29 @@ if (isset($_GET['action'])) { if ($_GET['action'] === 'global_stats') { $period = $_GET['period'] ?? 'all'; $where = ''; - if ($period === 'today') { $where = "WHERE DATE(event_time) = CURRENT_DATE"; } - elseif ($period === 'week') { $where = "WHERE event_time >= NOW() - INTERVAL '7 days'"; } - elseif ($period === 'month') { $where = "WHERE event_time >= NOW() - INTERVAL '30 days'"; } - $clicks = $db->query("SELECT COUNT(*) FROM admin.v_tracking_clicks {$where}")->fetchColumn(); - $opens = $db->query("SELECT COUNT(*) FROM admin.v_tracking_opens {$where}")->fetchColumn(); - $leads = $db->query("SELECT COUNT(*) FROM admin.v_tracking_leads {$where}")->fetchColumn(); - $unsubs = $db->query("SELECT COUNT(*) FROM admin.v_tracking_unsubs {$where}")->fetchColumn(); - $bounces = $db->query("SELECT COUNT(*) FROM admin.v_tracking_bounces {$where}")->fetchColumn(); + if ($period === 'today') { $where = "WHERE DATE(action_time) = CURRENT_DATE"; } + elseif ($period === 'week') { $where = "WHERE action_time >= NOW() - INTERVAL '7 days'"; } + elseif ($period === 'month') { $where = "WHERE action_time >= NOW() - INTERVAL '30 days'"; } + $clicks = $db->query("SELECT COUNT(*) FROM actions.clicks {$where}")->fetchColumn(); + $opens = $db->query("SELECT COUNT(*) FROM actions.opens {$where}")->fetchColumn(); + $leads = $db->query("SELECT COUNT(*) FROM actions.leads {$where}")->fetchColumn(); + $unsubs = $db->query("SELECT COUNT(*) FROM actions.unsubscribes {$where}")->fetchColumn(); + $bounces = $db->query("SELECT COUNT(*) FROM actions.optouts {$where}")->fetchColumn(); echo json_encode(['status' => 'success', 'data' => ['clicks' => intval($clicks), 'opens' => intval($opens), 'leads' => intval($leads), 'unsubs' => intval($unsubs), 'bounces' => intval($bounces)], 'period' => $period]); exit; } if ($_GET['action'] === 'today_comparison') { - $todayClicks = $db->query("SELECT COUNT(*) FROM admin.v_tracking_clicks WHERE DATE(event_time) = CURRENT_DATE")->fetchColumn(); - $todayOpens = $db->query("SELECT COUNT(*) FROM admin.v_tracking_opens WHERE DATE(event_time) = CURRENT_DATE")->fetchColumn(); - $todayLeads = $db->query("SELECT COUNT(*) FROM admin.v_tracking_leads WHERE DATE(event_time) = CURRENT_DATE")->fetchColumn(); - $todayUnsubs = $db->query("SELECT COUNT(*) FROM admin.v_tracking_unsubs WHERE DATE(event_time) = CURRENT_DATE")->fetchColumn(); - $todayBounces = $db->query("SELECT COUNT(*) FROM admin.v_tracking_bounces WHERE DATE(event_time) = CURRENT_DATE")->fetchColumn(); - $yestClicks = $db->query("SELECT COUNT(*) FROM admin.v_tracking_clicks WHERE DATE(event_time) = CURRENT_DATE - INTERVAL '1 day'")->fetchColumn(); - $yestOpens = $db->query("SELECT COUNT(*) FROM admin.v_tracking_opens WHERE DATE(event_time) = CURRENT_DATE - INTERVAL '1 day'")->fetchColumn(); - $yestLeads = $db->query("SELECT COUNT(*) FROM admin.v_tracking_leads WHERE DATE(event_time) = CURRENT_DATE - INTERVAL '1 day'")->fetchColumn(); - $yestUnsubs = $db->query("SELECT COUNT(*) FROM admin.v_tracking_unsubs WHERE DATE(event_time) = CURRENT_DATE - INTERVAL '1 day'")->fetchColumn(); - $yestBounces = $db->query("SELECT COUNT(*) FROM admin.v_tracking_bounces WHERE DATE(event_time) = CURRENT_DATE - INTERVAL '1 day'")->fetchColumn(); + $todayClicks = $db->query("SELECT COUNT(*) FROM actions.clicks WHERE DATE(action_time) = CURRENT_DATE")->fetchColumn(); + $todayOpens = $db->query("SELECT COUNT(*) FROM actions.opens WHERE DATE(action_time) = CURRENT_DATE")->fetchColumn(); + $todayLeads = $db->query("SELECT COUNT(*) FROM actions.leads WHERE DATE(action_time) = CURRENT_DATE")->fetchColumn(); + $todayUnsubs = $db->query("SELECT COUNT(*) FROM actions.unsubscribes WHERE DATE(action_time) = CURRENT_DATE")->fetchColumn(); + $todayBounces = $db->query("SELECT COUNT(*) FROM actions.optouts WHERE DATE(action_time) = CURRENT_DATE")->fetchColumn(); + $yestClicks = $db->query("SELECT COUNT(*) FROM actions.clicks WHERE DATE(action_time) = CURRENT_DATE - INTERVAL '1 day'")->fetchColumn(); + $yestOpens = $db->query("SELECT COUNT(*) FROM actions.opens WHERE DATE(action_time) = CURRENT_DATE - INTERVAL '1 day'")->fetchColumn(); + $yestLeads = $db->query("SELECT COUNT(*) FROM actions.leads WHERE DATE(action_time) = CURRENT_DATE - INTERVAL '1 day'")->fetchColumn(); + $yestUnsubs = $db->query("SELECT COUNT(*) FROM actions.unsubscribes WHERE DATE(action_time) = CURRENT_DATE - INTERVAL '1 day'")->fetchColumn(); + $yestBounces = $db->query("SELECT COUNT(*) FROM actions.optouts WHERE DATE(action_time) = CURRENT_DATE - INTERVAL '1 day'")->fetchColumn(); $comparison = []; $metrics = ['clicks' => [$todayClicks, $yestClicks], 'opens' => [$todayOpens, $yestOpens], 'leads' => [$todayLeads, $yestLeads], 'unsubs' => [$todayUnsubs, $yestUnsubs], 'bounces' => [$todayBounces, $yestBounces]]; foreach ($metrics as $name => $vals) { @@ -69,11 +69,11 @@ if (isset($_GET['action'])) { } if ($_GET['action'] === 'recent_activity') { - $clicks = $db->query("SELECT id, 'click' as action_name, tracking_id as process_id, 0 as vmta_id, COALESCE(click_url,'') as offer_id, event_time FROM admin.v_tracking_clicks ORDER BY event_time DESC LIMIT 5")->fetchAll(PDO::FETCH_ASSOC); - $opens = $db->query("SELECT id, 'open' as action_name, tracking_id as process_id, 0 as vmta_id, '' as offer_id, event_time FROM admin.v_tracking_opens ORDER BY event_time DESC LIMIT 5")->fetchAll(PDO::FETCH_ASSOC); - $leads = $db->query("SELECT id, 'lead' as action_name, tracking_id as process_id, 0 as vmta_id, '' as offer_id, event_time FROM admin.v_tracking_leads ORDER BY event_time DESC LIMIT 5")->fetchAll(PDO::FETCH_ASSOC); + $clicks = $db->query("SELECT id, 'click' as action_name, process_id, vmta_id, offer_production_id as offer_id, action_time FROM actions.clicks ORDER BY action_time DESC LIMIT 5")->fetchAll(PDO::FETCH_ASSOC); + $opens = $db->query("SELECT id, 'open' as action_name, process_id, vmta_id, offer_production_id as offer_id, action_time FROM actions.opens ORDER BY action_time DESC LIMIT 5")->fetchAll(PDO::FETCH_ASSOC); + $leads = $db->query("SELECT id, 'lead' as action_name, process_id, vmta_id, offer_production_id as offer_id, action_time FROM actions.leads ORDER BY action_time DESC LIMIT 5")->fetchAll(PDO::FETCH_ASSOC); $activities = array_merge($clicks, $opens, $leads); - usort($activities, function($a, $b) { return strtotime($b['event_time']) - strtotime($a['event_time']); }); + usort($activities, function($a, $b) { return strtotime($b['action_time']) - strtotime($a['action_time']); }); echo json_encode(['status' => 'success', 'data' => array_slice($activities, 0, 10)]); exit; } @@ -97,10 +97,10 @@ if (isset($_GET['action'])) { Tracking Dashboard - WEVAL - + - - @@ -128,11 +128,10 @@ if (isset($_GET['action'])) { function loadToday(){$.get('?action=today_comparison',function(r){if(r.status!=='success')return;['clicks','opens','leads','unsubs','bounces'].forEach(function(m){var d=r.data[m];$('#'+m+'-value').text(fmt(d.today));$('#'+m+'-yesterday').text('vs yesterday: '+fmt(d.yesterday));var el=$('#'+m+'-change').removeClass('up down neutral');if(d.diff>0)el.addClass('up').text('+'+d.pct+'%');else if(d.diff<0)el.addClass('down').text(d.pct+'%');else el.addClass('neutral').text('0%')})})} function loadDaily(days){$.get('?action=daily_stats&days='+days,function(r){if(r.status!=='success')return;var labels=r.data.map(function(d){return d.label});var ds=[{label:'Clicks',data:r.data.map(function(d){return d.clicks}),borderColor:'#2563eb',backgroundColor:'rgba(37,99,235,0.1)',tension:0.3,fill:true},{label:'Opens',data:r.data.map(function(d){return d.opens}),borderColor:'#10b981',backgroundColor:'rgba(16,185,129,0.1)',tension:0.3,fill:true},{label:'Leads',data:r.data.map(function(d){return d.leads}),borderColor:'#f59e0b',backgroundColor:'rgba(245,158,11,0.1)',tension:0.3,fill:true}];if(dailyChart){dailyChart.data.labels=labels;dailyChart.data.datasets=ds;dailyChart.update()}else{dailyChart=new Chart(document.getElementById('dailyChart').getContext('2d'),{type:'line',data:{labels:labels,datasets:ds},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{position:'top'}},scales:{y:{beginAtZero:true},x:{}}}})}})} function loadGlobal(p){$.get('?action=global_stats&period='+p,function(r){if(r.status!=='success')return;$('#global-clicks').text(fmt(r.data.clicks));$('#global-opens').text(fmt(r.data.opens));$('#global-leads').text(fmt(r.data.leads));$('#global-unsubs').text(fmt(r.data.unsubs));$('#global-bounces').text(fmt(r.data.bounces))})} - function loadActivity(){$.get('?action=recent_activity',function(r){if(r.status!=='success')return;var html='';if(r.data.length===0){html='
No activity
'}else{r.data.forEach(function(i){var ic=i.action_name==='click'?'click':(i.action_name==='open'?'open':'lead');var ico=ic==='click'?'fa-mouse-pointer':(ic==='open'?'fa-envelope-open':'fa-user-plus');html+='
'+i.action_name+'
Process: '+i.process_id+'
'+new Date(i.event_time).toLocaleTimeString()+'
'})}$('#activity-feed').html(html)})} + function loadActivity(){$.get('?action=recent_activity',function(r){if(r.status!=='success')return;var html='';if(r.data.length===0){html='
No activity
'}else{r.data.forEach(function(i){var ic=i.action_name==='click'?'click':(i.action_name==='open'?'open':'lead');var ico=ic==='click'?'fa-mouse-pointer':(ic==='open'?'fa-envelope-open':'fa-user-plus');html+='
'+i.action_name+'
Process: '+i.process_id+'
'+new Date(i.action_time).toLocaleTimeString()+'
'})}$('#activity-feed').html(html)})} $(document).ready(function(){loadStatus();loadToday();loadDaily(14);loadGlobal('month');loadActivity();$('.period-btn:not(.global-btn)').click(function(){$(this).siblings().removeClass('active');$(this).addClass('active');loadDaily($(this).data('days'))});$('.global-btn').click(function(){$(this).siblings().removeClass('active');$(this).addClass('active');loadGlobal($(this).data('period'))});setInterval(function(){loadStatus();loadToday();loadActivity()},30000)}); - diff --git a/public/tracking-deploy.php b/public/tracking-deploy.php index baae9c06..75d46562 100644 --- a/public/tracking-deploy.php +++ b/public/tracking-deploy.php @@ -198,10 +198,43 @@ echo "DEPLOY_SUCCESS"'; WEVAL | Tracking Deployment - + - -
@@ -394,12 +427,11 @@ function deployServer() { $(document).ready(function() { testCurrent(); - // Auto-check consent.wevup.app - $('#check-domain').val('consent.wevup.app'); + // Auto-check culturellemejean.charity + $('#check-domain').val('culturellemejean.charity'); checkDomain(); }); - diff --git a/public/tracking-global-dashboard.php b/public/tracking-global-dashboard.php index 86be97d9..decb9e0d 100644 --- a/public/tracking-global-dashboard.php +++ b/public/tracking-global-dashboard.php @@ -30,7 +30,7 @@ foreach($tables as $table) { # Get recent actions from all apps $recent_actions = []; try { - $stmt = $pdo->query("SELECT 'OPEN' as type, created_at, process_id, client_id FROM admin.v_tracking_opens ORDER BY created_at DESC LIMIT 100"); + $stmt = $pdo->query("SELECT 'OPEN' as type, created_at, process_id, client_id FROM actions.opens ORDER BY created_at DESC LIMIT 100"); $recent_actions = $stmt->fetchAll(PDO::FETCH_ASSOC); } catch(Exception $e) { $recent_actions = []; @@ -42,10 +42,42 @@ try { ๐Ÿ“Š GLOBAL Tracking Dashboard - + - -
@@ -121,6 +153,5 @@ try {
- diff --git a/public/tracking-manager.php b/public/tracking-manager.php index 7207db90..d48fd643 100644 --- a/public/tracking-manager.php +++ b/public/tracking-manager.php @@ -11,10 +11,37 @@ try { $stats['unsubs'] = $pdo->query("SELECT COUNT(*) FROM actions.unsubscribes" Tracking Manager - Opens, Clicks, Leads + - - - Retour aux System Flows @@ -55,5 +82,4 @@ try { $stats['unsubs'] = $pdo->query("SELECT COUNT(*) FROM actions.unsubscribes"

Domains: Tracking domains configurรฉs pour redirections

- diff --git a/public/tracking-system-standalone.php b/public/tracking-system-standalone.php index c9e3ec08..c8d23745 100644 --- a/public/tracking-system-standalone.php +++ b/public/tracking-system-standalone.php @@ -1,297 +1,352 @@ "http://{$tracking_ip}/", CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5]); curl_exec($ch); $trackingCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); + $trackingTime = round((microtime(true) - $start) * 1000); + + $trackingMetrics = ['cpu' => 0, 'mem' => 0, 'disk' => 0]; + $sshCmd = "sshpass -p '{$tracking_ssh_pass}' ssh -o StrictHostKeyChecking=no -o ConnectTimeout=3 ubuntu@{$tracking_ip} \"cat /proc/loadavg && free -m && df -h /\" 2>/dev/null"; + $sshOutput = shell_exec($sshCmd); + if ($sshOutput) { + $lines = explode("\n", $sshOutput); + if (isset($lines[0])) { $loadParts = explode(' ', $lines[0]); $trackingMetrics['cpu'] = round(floatval($loadParts[0]) * 100 / 2, 1); } + foreach ($lines as $line) { + if (strpos($line, 'Mem:') !== false) { $parts = preg_split('/\s+/', trim($line)); if (count($parts) >= 3) $trackingMetrics['mem'] = round(($parts[2] / $parts[1]) * 100, 1); } + if (strpos($line, '/dev/') !== false && strpos($line, '%') !== false) { preg_match('/(\d+)%/', $line, $diskMatch); if (isset($diskMatch[1])) $trackingMetrics['disk'] = intval($diskMatch[1]); } + } } - // Green if all critical pass, yellow if non-critical fail, red if critical fail - $indicator = $criticalFailed ? 'red' : ($totalPassed < $totalChecks ? 'yellow' : 'green'); - echo json_encode([ - 'status' => $criticalFailed ? 'unhealthy' : 'healthy', - 'indicator' => $indicator, - 'passed' => $totalPassed, - 'total' => $totalChecks, - 'timestamp' => date('c'), - 'checks' => $results - ], JSON_PRETTY_PRINT); + echo json_encode(['wevads' => ['cpu' => $cpuPercent, 'mem' => $memPercent, 'disk' => $diskPercent], 'tracking' => ['cpu' => $trackingMetrics['cpu'], 'mem' => $trackingMetrics['mem'], 'disk' => $trackingMetrics['disk'], 'response_time' => $trackingTime, 'status' => $trackingCode > 0 ? 'online' : 'offline']]); exit; } -// โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• CHECKS โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• -function runAllChecks() { - return [ - checkDatabase(), - checkTrackingTCP(), - checkTrackingHTTPS(), - checkOpenPixel(), - checkClickRedirect(), - checkTrackingBridge(), - checkConversionsCron(), - checkS3Redirect(), - checkTrackingStats(), - ]; +// Generate Click - INSERT with geolocation +if (isset($_GET['action']) && $_GET['action'] === 'generate_click') { + header('Content-Type: application/json'); + try { + $db = new PDO('pgsql:host=localhost;dbname=adx_system', 'admin', 'admin123'); + $stmt = $db->query("SELECT id, name, affiliate_network_id FROM affiliate.offers WHERE status = 'Activated' ORDER BY RANDOM() LIMIT 1"); + $offer = $stmt->fetch(PDO::FETCH_ASSOC); + if (!$offer) { echo json_encode(['success' => false, 'message' => 'No active offers']); exit; } + + $stmt2 = $db->query("SELECT id FROM production.mta_processes WHERE status = 'Completed' ORDER BY id DESC LIMIT 1"); + $process = $stmt2->fetch(PDO::FETCH_ASSOC); + $processId = $process ? $process['id'] : 999; + + $stmtId = $db->query("SELECT COALESCE(MAX(id), 0) + 1 FROM actions.clicks"); + $nextId = $stmtId->fetchColumn(); + + $locations = [['US', 'United States', 'New York', 'New York City'], ['DE', 'Germany', 'Bavaria', 'Munich'], ['FR', 'France', 'Ile-de-France', 'Paris'], ['GB', 'United Kingdom', 'England', 'London'], ['SE', 'Sweden', 'Stockholm', 'Stockholm'], ['MA', 'Morocco', 'Casablanca-Settat', 'Casablanca'], ['ES', 'Spain', 'Madrid', 'Madrid'], ['IT', 'Italy', 'Lazio', 'Rome']]; + $loc = $locations[rand(0, count($locations)-1)]; + $browsers = ['Google Chrome', 'Firefox', 'Safari', 'Edge']; + $devices = ['Computer', 'Mobile', 'Tablet']; + $ips = ['45.'.rand(1,255).'.'.rand(1,255).'.'.rand(1,255), '92.'.rand(1,255).'.'.rand(1,255).'.'.rand(1,255)]; + + $insert = $db->prepare("INSERT INTO actions.clicks (id, unique_token, process_id, process_type, user_production_id, user_full_name, vmta_id, smtp_user_id, affiliate_network_id, offer_production_id, list_id, client_id, action_time, process_updated, agent, action_ip, country_code, country, region, city, device_type, device_name, operating_system, browser_name, browser_version) VALUES (?, ?, ?, 'md', 1, 'Simulated User', ?, 0, ?, ?, 0, 0, NOW(), false, 'Mozilla/5.0', ?, ?, ?, ?, ?, ?, 'PC', 'Windows 10.0', ?, '120.0')"); + $insert->execute([$nextId, $processId.rand(1000,9999), $processId, rand(1,10), $offer['affiliate_network_id'] ?? 1, $offer['id'], $ips[rand(0,1)], $loc[0], $loc[1], $loc[2], $loc[3], $devices[rand(0,2)], $browsers[rand(0,3)]]); + + echo json_encode(['success' => true, 'message' => 'Click generated!', 'offer_id' => $offer['id'], 'offer_name' => $offer['name'], 'location' => $loc[3].', '.$loc[1], 'click_id' => $nextId]); + } catch (Exception $e) { echo json_encode(['success' => false, 'message' => $e->getMessage()]); } + exit; } -function checkDatabase() { - $start = microtime(true); - $db = getDB(); - if (!$db) { - return ['name' => 'PostgreSQL Database', 'status' => false, 'critical' => true, - 'message' => 'Connection failed', 'time_ms' => ms($start)]; +// Recent activity +if (isset($_GET['action']) && $_GET['action'] === 'recent_activity') { + header('Content-Type: application/json'); + try { + $db = new PDO('pgsql:host=localhost;dbname=adx_system', 'admin', 'admin123'); + $stmt = $db->query("SELECT id, action_time, offer_production_id as offer_id, process_id, country, city, device_type, browser_name, action_ip FROM actions.clicks ORDER BY action_time DESC LIMIT 15"); + echo json_encode(['success' => true, 'clicks' => $stmt->fetchAll(PDO::FETCH_ASSOC)]); + } catch (Exception $e) { echo json_encode(['success' => false, 'message' => $e->getMessage()]); } + exit; +} + +// Repair actions +if (isset($_GET['action']) && $_GET['action'] === 'repair') { + header('Content-Type: application/json'); + $type = $_POST['type'] ?? ''; + switch ($type) { + case 'tracking_server': $output = shell_exec("sshpass -p '{$tracking_ssh_pass}' ssh -o StrictHostKeyChecking=no ubuntu@{$tracking_ip} 'sudo systemctl restart nginx php8.1-fpm' 2>&1"); echo json_encode(['success' => true, 'message' => 'Nginx restarted', 'output' => $output]); break; + case 'wevads_api': shell_exec('sudo systemctl restart apache2'); echo json_encode(['success' => true, 'message' => 'Apache restarted']); break; + case 'database': shell_exec('sudo systemctl restart postgresql'); echo json_encode(['success' => true, 'message' => 'PostgreSQL restarted']); break; + case 'e2e_click': $output = shell_exec("sshpass -p '{$tracking_ssh_pass}' ssh -o StrictHostKeyChecking=no ubuntu@{$tracking_ip} 'tail -20 /var/log/nginx/error.log' 2>&1"); echo json_encode(['success' => true, 'message' => 'Logs', 'output' => $output]); break; + case 's3_bucket': echo json_encode(['success' => true, 'message' => 'Check AWS Console', 'url' => 'https://s3.console.aws.amazon.com/']); break; + default: echo json_encode(['success' => false, 'message' => 'Unknown']); } - $r = pg_fetch_assoc(pg_query($db, "SELECT COUNT(*) as cnt FROM affiliate.offers WHERE status='Activated'")); - $offers = $r['cnt'] ?? 0; - $r2 = pg_fetch_assoc(pg_query($db, "SELECT COUNT(*) as cnt FROM admin.unified_tracking")); - $events = $r2['cnt'] ?? 0; - return ['name' => 'PostgreSQL Database', 'status' => true, 'critical' => true, - 'message' => "$offers offres actives, $events tracking events", 'time_ms' => ms($start)]; + exit; } -function checkTrackingTCP() { - $start = microtime(true); - $p80 = @fsockopen(TRACKING_SERVER_IP, 80, $en, $es, 3); - $p443 = @fsockopen(TRACKING_SERVER_IP, 443, $en, $es, 3); - $ok80 = $p80 ? true : false; - $ok443 = $p443 ? true : false; - if ($p80) fclose($p80); - if ($p443) fclose($p443); - $both = $ok80 && $ok443; - return ['name' => 'Tracking Server TCP (80+443)', 'status' => $both, 'critical' => true, - 'message' => 'Port 80: ' . ($ok80?'โœ…':'โŒ') . ' | Port 443: ' . ($ok443?'โœ…':'โŒ') . ' (' . TRACKING_SERVER_IP . ')', - 'time_ms' => ms($start)]; -} - -function checkTrackingHTTPS() { - $start = microtime(true); - $ch = curl_init('https://' . TRACKING_DOMAIN . '/op/1_md/1/1/1/0/0'); - curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 8, CURLOPT_FOLLOWLOCATION => false, CURLOPT_NOBODY => true]); - curl_exec($ch); - $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); - $ssl = curl_getinfo($ch, CURLINFO_SSL_VERIFYRESULT); - $err = curl_error($ch); - curl_close($ch); - $ok = $code > 0 && $code < 500; - return ['name' => 'HTTPS via Cloudflare (' . TRACKING_DOMAIN . ')', 'status' => $ok, 'critical' => true, - 'message' => $ok ? "HTTP $code, SSL OK" : "Erreur: $err (HTTP $code)", 'time_ms' => ms($start)]; -} - -function checkOpenPixel() { - $start = microtime(true); - $ch = curl_init('https://' . TRACKING_DOMAIN . '/op/1_md/1/1/1/0/0'); - curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, CURLOPT_HEADER => true]); - $resp = curl_exec($ch); - $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); - $ct = curl_getinfo($ch, CURLINFO_CONTENT_TYPE); - curl_close($ch); - $isGif = ($code == 200 && strpos($ct, 'image') !== false); - return ['name' => 'Open Pixel (1x1 GIF)', 'status' => $isGif, 'critical' => true, - 'message' => $isGif ? "HTTP 200, Content-Type: $ct โœ…" : "HTTP $code, Content-Type: $ct", 'time_ms' => ms($start)]; -} - -function checkClickRedirect() { - $start = microtime(true); - $ch = curl_init('https://' . TRACKING_DOMAIN . '/cl/1_md/1/1/1/0/0'); - curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 12, CURLOPT_FOLLOWLOCATION => false]); - $resp = curl_exec($ch); - $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); - curl_close($ch); - // Check if redirect contains offer link (e36lbat.com) or any redirect - $hasRedirect = (strpos($resp, 'window.location') !== false || strpos($resp, 'http-equiv="refresh"') !== false); - $hasOffer = (strpos($resp, 'e36lbat.com') !== false || strpos($resp, 'rivoweb') !== false); - $toGoogle = (strpos($resp, 'google.com') !== false); - if ($toGoogle) { - return ['name' => 'Click Redirect', 'status' => false, 'critical' => true, - 'message' => "โš ๏ธ Redirige vers Google! Vรฉrifier offer_id/vmta_id", 'time_ms' => ms($start)]; - } - $ok = $hasRedirect || $code == 302; - return ['name' => 'Click Redirect', 'status' => $ok, 'critical' => true, - 'message' => $ok ? "HTTP $code, redirect " . ($hasOffer ? "โ†’ offre sponsor โœ…" : "dรฉtectรฉ") : "HTTP $code, pas de redirect", - 'time_ms' => ms($start)]; -} - -function checkTrackingBridge() { - $start = microtime(true); - $ch = curl_init('http://127.0.0.1:' . WEVADS_PORT . '/tracking-bridge.php'); - curl_setopt_array($ch, [ - CURLOPT_POST => true, - CURLOPT_POSTFIELDS => http_build_query([ - 'controller' => 'Tracking', 'action' => 'getAdxRtl', - 'parameters' => ['type'=>'preview','process-id'=>'1','process-type'=>'md','user-id'=>'1', - 'vmta-id'=>'1','offer-id'=>'9','list-id'=>'0','client-id'=>'0','ip'=>'127.0.0.1'] - ]), - CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10 - ]); - $resp = curl_exec($ch); - $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); - curl_close($ch); - $data = json_decode($resp, true); - $ok = ($data && isset($data['status']) && $data['status'] == 200); - $link = $data['data']['link'] ?? ''; - return ['name' => 'API tracking-bridge.php', 'status' => $ok, 'critical' => true, - 'message' => $ok ? "API OK, lien: " . substr($link, 0, 60) . "..." : "HTTP $code โ€” " . ($data['message'] ?? substr($resp,0,80)), - 'time_ms' => ms($start)]; -} - -function checkConversionsCron() { - $start = microtime(true); - $crons = shell_exec('crontab -l 2>/dev/null | grep -i "conversion" | grep -v "^#"'); - $active = !empty(trim($crons)); - return ['name' => 'Conversions Collector (Cron)', 'status' => $active, 'critical' => false, - 'message' => $active ? "Cron actif: " . trim($crons) : "Aucun cron conversion trouvรฉ", - 'time_ms' => ms($start)]; -} - -function checkS3Redirect() { - $start = microtime(true); - // Check if AmazonCloud.php has correct tracking IP - $file = '/opt/wevads/app/libraries/AmazonCloud.php'; - if (!file_exists($file)) { - return ['name' => 'S3 Redirect Config', 'status' => false, 'critical' => false, - 'message' => "AmazonCloud.php non trouvรฉ", 'time_ms' => ms($start)]; - } - $content = file_get_contents($file); - $hasIP = (strpos($content, TRACKING_SERVER_IP) !== false); - $isHTTPS = (strpos($content, 'https://' . TRACKING_DOMAIN) !== false); - $mode = $isHTTPS ? 'HTTPS (domaine)' : ($hasIP ? 'HTTP (IP directe)' : 'IP inconnue'); - return ['name' => 'S3 Redirect Config', 'status' => ($hasIP || $isHTTPS), 'critical' => false, - 'message' => "Mode: $mode", 'time_ms' => ms($start)]; -} - -function checkTrackingStats() { - $start = microtime(true); - $db = getDB(); - if (!$db) return ['name' => 'Tracking Stats (24h)', 'status' => false, 'critical' => false, 'message' => 'DB error', 'time_ms' => ms($start)]; +// Diagnose +if (isset($_GET['action']) && $_GET['action'] === 'diagnose') { + header('Content-Type: application/json'); + $results = ['timestamp' => date('Y-m-d H:i:s'), 'overall_status' => 'ok', 'checks' => []]; - $stats = []; - foreach (['open'=>'opens','click'=>'clicks','unsubscribe'=>'unsubscribes'] as $type => $label) { - $r = pg_fetch_assoc(pg_query($db, "SELECT COUNT(*) as cnt FROM admin.unified_tracking WHERE event_type='$type' AND created_at > NOW() - INTERVAL '24 hours'")); - $stats[$label] = $r['cnt'] ?? 0; - } - $r = pg_fetch_assoc(pg_query($db, "SELECT COUNT(*) as cnt FROM actions.leads WHERE action_time > NOW() - INTERVAL '24 hours'")); - $stats['leads'] = $r['cnt'] ?? 0; + $ch = curl_init(); curl_setopt_array($ch, [CURLOPT_URL => "http://{$tracking_ip}/", CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10]); curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); + $results['checks']['tracking_server'] = ['name' => 'Tracking Server', 'status' => $code > 0 ? 'ok' : 'error', 'message' => "HTTP {$code}", 'repair' => 'tracking_server', 'repair_label' => 'Restart Nginx']; - $total = array_sum($stats); - $msg = implode(' | ', array_map(fn($k,$v) => "$k: $v", array_keys($stats), array_values($stats))); - return ['name' => 'Tracking Stats (24h)', 'status' => true, 'critical' => false, - 'message' => $msg . " (total: $total)", 'time_ms' => ms($start)]; + $ch = curl_init(); curl_setopt_array($ch, [CURLOPT_URL => $wevads_api, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query(['controller' => 'Tracking', 'action' => 'getAdxRtl', 'parameters' => []])]); $apiResponse = curl_exec($ch); $apiCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); + $results['checks']['wevads_api'] = ['name' => 'WEVAL API', 'status' => ($apiCode == 200 && json_decode($apiResponse)) ? 'ok' : 'error', 'message' => "HTTP {$apiCode}", 'repair' => 'wevads_api', 'repair_label' => 'Restart Apache']; + + try { $db = new PDO('pgsql:host=localhost;dbname=adx_system', 'admin', 'admin123'); $stmt = $db->query("SELECT COUNT(*) FROM actions.clicks WHERE action_time > NOW() - INTERVAL '24 hours'"); $results['checks']['database'] = ['name' => 'Database', 'status' => 'ok', 'message' => $stmt->fetchColumn().' clicks/24h', 'repair' => 'database', 'repair_label' => 'Restart PostgreSQL']; } catch (Exception $e) { $results['checks']['database'] = ['name' => 'Database', 'status' => 'error', 'message' => 'Failed', 'repair' => 'database', 'repair_label' => 'Restart PostgreSQL']; } + + $ch = curl_init(); curl_setopt_array($ch, [CURLOPT_URL => "http://{$tracking_ip}/cl/999_md/1/1/6/0/0", CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15]); $e2eResponse = curl_exec($ch); $e2eCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); + $results['checks']['e2e_click'] = ['name' => 'E2E Click', 'status' => ($e2eCode == 200 && strlen($e2eResponse) > 10) ? 'ok' : 'warning', 'message' => "HTTP {$e2eCode}", 'repair' => 'e2e_click', 'repair_label' => 'View Logs']; + + $ch = curl_init(); curl_setopt_array($ch, [CURLOPT_URL => "https://ff6970ea5261c1fb821273.s3.eu-north-1.amazonaws.com/", CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, CURLOPT_NOBODY => true]); curl_exec($ch); $s3Code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); + $results['checks']['s3_bucket'] = ['name' => 'S3 Bucket', 'status' => ($s3Code > 0 && $s3Code < 500) ? 'ok' : 'error', 'message' => "HTTP {$s3Code}", 'repair' => 's3_bucket', 'repair_label' => 'Check AWS']; + + foreach ($results['checks'] as $c) { if ($c['status'] === 'error') $results['overall_status'] = 'error'; } + echo json_encode($results); + exit; } -function ms($start) { return round((microtime(true) - $start) * 1000, 1); } - -// โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• RUN โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• -$results = runAllChecks(); -$criticalFailed = false; -$totalPassed = 0; -$totalChecks = count($results); -$totalTime = 0; -foreach ($results as $r) { - if ($r['status']) $totalPassed++; - if (!$r['status'] && ($r['critical'] ?? false)) $criticalFailed = true; - $totalTime += $r['time_ms']; +// Get test URL +if (isset($_GET['action']) && $_GET['action'] === 'get_test_url') { + header('Content-Type: application/json'); + try { + $db = new PDO('pgsql:host=localhost;dbname=adx_system', 'admin', 'admin123'); + $stmt = $db->query("SELECT id, name FROM affiliate.offers WHERE status = 'Activated' ORDER BY id LIMIT 1"); + $offer = $stmt->fetch(PDO::FETCH_ASSOC); + $stmt2 = $db->query("SELECT id FROM production.mta_processes WHERE status = 'Completed' ORDER BY id DESC LIMIT 1"); + $process = $stmt2->fetch(PDO::FETCH_ASSOC); + $processId = $process ? $process['id'] : 999; + $url = "http://{$tracking_ip}/cl/{$processId}_md/1/1/{$offer['id']}/0/0"; + echo json_encode(['success' => true, 'url' => $url, 'offer_id' => $offer['id'], 'offer_name' => $offer['name']]); + } catch (Exception $e) { echo json_encode(['success' => false]); } + exit; } -$indicator = $criticalFailed ? 'red' : ($totalPassed < $totalChecks ? 'yellow' : 'green'); -$statusText = $criticalFailed ? 'CRITICAL ISSUES' : ($totalPassed < $totalChecks ? 'MINOR ISSUES' : 'ALL SYSTEMS GO'); -$statusEmoji = $criticalFailed ? '๐Ÿ”ด' : ($totalPassed < $totalChecks ? '๐ŸŸก' : '๐ŸŸข'); ?> - + -WEVADS Tracking โ€” Health Check - + + + Tracking Diagnostic - WEVAL + + - -
-
-

๐Ÿ” WEVADS TRACKING โ€” E2E HEALTH CHECK

-
Serveur : โ†’ Tracking ()
-
- - - -
-
PASSED
-
FAILED
-
ms
TOTAL TIME
-
- -
- -
-
- - +
+ Back to Dashboard + + +
+
+
WEVAL Server
+
+
-
CPU
+
-
Memory
+
-
Disk
+
-
-
- โฑ ms - +
+
Tracking
+
+
-
CPU
+
-
Memory
+
-
Disk
+
+
+
+
Response
+
-ms
- + + +
+
+

Simulate Click

+ +
+

Inserts a real click with random location into the database

+
+
+ + +
+

Recent Clicks

+
Loading...
+
+ + +
+

Test Redirect

+
+
+

Open Tracking Link

+

Click to open a tracking URL and see where it redirects (no click recorded)

+ +
+
+
+ + +
+

System Diagnostic

Health check with repair tools

+
Checking...
+
+
+
-
Passed
+
-
Errors
+
-
Total
+
-
Diag Time
+
+
+

System Checks

+
Loading...
+
+ + + + + + -
-

๐Ÿ“ก Infrastructure

- - - - - - -
ComposantAdresseRรดle
WEVADS Server:API + BDD + Pipeline
Tracking ServerOVH โ€” tracking.php, open/click/unsub
Tracking DomainHTTPS via Cloudflare โ†’
Sponsorse36lbat.com (CX3) / rivoweb (DoubleM)Offres affiliรฉes
-
- -
- API pour Dashboard principal: - - โ†’ {"status":"","indicator":""} -
- - -
diff --git a/public/tracking-white.css b/public/tracking-white.css new file mode 100644 index 00000000..c649b896 --- /dev/null +++ b/public/tracking-white.css @@ -0,0 +1,3 @@ +body { background: #f8fafc; color: #1e293b; } +nav, header, .navbar, .top-nav, .sidebar { display: none; } +.main-content { padding: 20px; }