// ═══════════════════════════════════════════════════════ // Don't track admin pages or bots if (strpos($_SERVER['REQUEST_URI'] ?? '', '/superadmin214') !== false) return; $bot_patterns = ['bot','crawl','spider','slurp','mediapartners','facebookexternalhit','whatsapp','telegram','pinterest','curl','wget','python','ruby','java','go-http','axios','node']; $ua = strtolower($_SERVER['HTTP_USER_AGENT'] ?? ''); foreach ($bot_patterns as $b) { if (strpos($ua, $b) !== false) return; } // ── Visitor ID (anonymous journey tracking via cookie) ── $visitor_id = ''; if (isset($_COOKIE['_bvid'])) { $visitor_id = preg_replace('/[^a-f0-9]/', '', $_COOKIE['_bvid']); } else { $visitor_id = bin2hex(random_bytes(8)); setcookie('_bvid', $visitor_id, [ 'expires' => time() + (365 * 24 * 3600), 'path' => '/', 'httponly' => true, 'samesite' => 'Lax', ]); } // ── Collect data ── $ip = $_SERVER['HTTP_CF_CONNECTING_IP'] // Cloudflare ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? ''; $ip = trim(explode(',', $ip)[0]); $page = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH); $page = '/' . trim($page, '/'); $referrer = $_SERVER['HTTP_REFERER'] ?? ''; $ua_full = $_SERVER['HTTP_USER_AGENT'] ?? ''; $timestamp = date('Y-m-d H:i:s'); $date = date('Y-m-d'); // ── Device detection ── $device = 'Desktop'; if (preg_match('/Mobile|Android|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i', $ua_full)) $device = 'Mobile'; elseif (preg_match('/iPad|Tablet/i', $ua_full)) $device = 'Tablet'; // ── Browser detection ── $browser = 'Other'; if (strpos($ua, 'edg/') !== false) $browser = 'Edge'; elseif (strpos($ua, 'chrome') !== false && strpos($ua, 'safari') !== false) $browser = 'Chrome'; elseif (strpos($ua, 'firefox') !== false) $browser = 'Firefox'; elseif (strpos($ua, 'safari') !== false) $browser = 'Safari'; elseif (strpos($ua, 'opera') !== false || strpos($ua, 'opr/') !== false) $browser = 'Opera'; // ── OS detection ── $os = 'Other'; if (strpos($ua, 'windows') !== false) $os = 'Windows'; elseif (strpos($ua, 'mac os') !== false) $os = 'macOS'; elseif (strpos($ua, 'android') !== false) $os = 'Android'; elseif (strpos($ua, 'iphone') !== false || strpos($ua, 'ipad') !== false) $os = 'iOS'; elseif (strpos($ua, 'linux') !== false) $os = 'Linux'; // ── Referrer source ── $source = 'Direct'; if ($referrer) { $ref_host = parse_url($referrer, PHP_URL_HOST) ?? ''; $ref_host = str_replace('www.', '', $ref_host); $own_host = str_replace('www.', '', $_SERVER['HTTP_HOST'] ?? ''); if ($ref_host === $own_host) { $source = 'Internal'; } elseif (strpos($ref_host, 'google') !== false) $source = 'Google'; elseif (strpos($ref_host, 'facebook') !== false || strpos($ref_host, 'fb.') !== false) $source = 'Facebook'; elseif (strpos($ref_host, 'instagram') !== false) $source = 'Instagram'; elseif (strpos($ref_host, 'twitter') !== false || strpos($ref_host, 'x.com') !== false) $source = 'Twitter/X'; elseif (strpos($ref_host, 'linkedin') !== false) $source = 'LinkedIn'; elseif (strpos($ref_host, 'youtube') !== false) $source = 'YouTube'; elseif (strpos($ref_host, 'whatsapp') !== false) $source = 'WhatsApp'; elseif (strpos($ref_host, 'reddit') !== false) $source = 'Reddit'; else $source = $ref_host ?: 'Referral'; } // ── Geo lookup (cached per IP per day) ── $country = ''; $city = ''; $region = ''; $geo_cache_dir = __DIR__ . '/stats/geo_cache/'; if (!is_dir($geo_cache_dir)) mkdir($geo_cache_dir, 0755, true); $safe_ip = preg_replace('/[^a-f0-9\.\:]/', '', $ip); $cache_key = $geo_cache_dir . md5($safe_ip) . '_' . $date . '.json'; if (file_exists($cache_key)) { $geo = json_decode(file_get_contents($cache_key), true); } else { // Clean old cache files (keep last 2 days) foreach (glob($geo_cache_dir . '*.json') as $old) { if (filemtime($old) < time() - 172800) unlink($old); } $geo_raw = @file_get_contents("http://ip-api.com/json/{$safe_ip}?fields=country,regionName,city,status"); $geo = $geo_raw ? json_decode($geo_raw, true) : []; if (($geo['status'] ?? '') === 'success') { file_put_contents($cache_key, json_encode($geo)); } else { $geo = []; } } $country = $geo['country'] ?? ''; $region = $geo['regionName'] ?? ''; $city = $geo['city'] ?? ''; // ── Write log ── $log_dir = __DIR__ . '/stats/logs/'; if (!is_dir($log_dir)) mkdir($log_dir, 0755, true); $log_file = $log_dir . $date . '.csv'; $is_new = !file_exists($log_file); $row = implode(',', array_map(function($v) { $v = str_replace(['"', "\n", "\r"], ['""', '', ''], $v); return '"' . $v . '"'; }, [ $timestamp, $visitor_id, $ip, $page, $device, $browser, $os, $source, $referrer, $country, $region, $city, $ua_full, ])); $fp = fopen($log_file, 'a'); if ($fp) { if ($is_new) { fwrite($fp, "timestamp,visitor_id,ip,page,device,browser,os,source,referrer,country,region,city,user_agent\n"); } fwrite($fp, $row . "\n"); fclose($fp); }
✦ Latest Post
Most blogging platforms lock you in. Here
Read Post →