prefix . self::TABLE; } public static function maybe_install() { if (get_option(self::DB_OPTION) === self::DB_VERSION) { return; } global $wpdb; $table = self::table_name(); $charset = $wpdb->get_charset_collate(); $sql = "CREATE TABLE {$table} ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, session_id VARCHAR(32) NOT NULL DEFAULT '', url VARCHAR(255) NOT NULL DEFAULT '', referrer VARCHAR(255) NOT NULL DEFAULT '', device VARCHAR(20) NOT NULL DEFAULT 'desktop', browser VARCHAR(40) NOT NULL DEFAULT '', country VARCHAR(2) NOT NULL DEFAULT '', created_at DATETIME NOT NULL, PRIMARY KEY (id), KEY idx_created (created_at), KEY idx_session (session_id) ) {$charset};"; require_once ABSPATH . "wp-admin/includes/upgrade.php"; dbDelta($sql); update_option(self::DB_OPTION, self::DB_VERSION); } /** * Records the current front-end request as a pageview, skipping admin, * AJAX/REST/cron, bots, and logged-in administrators. */ public static function record() { // Tracking is on unless explicitly disabled in Settings > General. $enabled = \AuroraAdmin\Options\Settings::get("enable_analytics", true); if ($enabled === false || $enabled === 0 || $enabled === "0") { return; } if (is_admin() || wp_doing_ajax() || wp_doing_cron() || is_robots() || is_feed()) { return; } if (defined("REST_REQUEST") && REST_REQUEST) { return; } // Admins browsing their own site are skipped unless Settings > // Analytics > "Track logged-in admins" is enabled. $track_admins = \AuroraAdmin\Options\Settings::get("track_admins", false); if (!$track_admins && current_user_can("manage_options")) { return; } $ua = isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : ""; if (self::is_bot($ua)) { return; } global $wpdb; $wpdb->insert(self::table_name(), [ "session_id" => self::session_id(), "url" => substr(self::current_path(), 0, 255), "referrer" => substr(self::referrer(), 0, 255), "device" => self::device($ua), "browser" => self::browser($ua), "country" => self::country(), "created_at" => current_time("mysql"), ]); } private static function session_id() { if (!empty($_COOKIE[self::COOKIE])) { return preg_replace("/[^a-f0-9]/", "", substr($_COOKIE[self::COOKIE], 0, 32)); } $sid = md5(uniqid("", true)); // 30-minute rolling session window if (!headers_sent()) { setcookie(self::COOKIE, $sid, time() + 1800, COOKIEPATH ?: "/", COOKIE_DOMAIN); } $_COOKIE[self::COOKIE] = $sid; return $sid; } private static function current_path() { $uri = isset($_SERVER["REQUEST_URI"]) ? $_SERVER["REQUEST_URI"] : "/"; return wp_parse_url($uri, PHP_URL_PATH) ?: "/"; } private static function referrer() { $ref = isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : ""; if (!$ref) { return ""; } $host = wp_parse_url($ref, PHP_URL_HOST); // Ignore self-referrals if ($host && $host === wp_parse_url(home_url(), PHP_URL_HOST)) { return ""; } return $host ?: ""; } private static function device($ua) { $ua = strtolower($ua); if (preg_match("/(ipad|tablet|playbook|silk)|(android(?!.*mobile))/", $ua)) { return "tablet"; } if (preg_match("/(mobile|iphone|ipod|android|blackberry|opera mini|iemobile)/", $ua)) { return "mobile"; } return "desktop"; } private static function browser($ua) { $map = [ "Edg" => "Edge", "OPR" => "Opera", "Chrome" => "Chrome", "Firefox" => "Firefox", "Safari" => "Safari", ]; foreach ($map as $needle => $name) { if (stripos($ua, $needle) !== false) { return $name; } } return "Other"; } private static function country() { // Use a CDN-provided country header if available; otherwise leave blank. foreach (["HTTP_CF_IPCOUNTRY", "GEOIP_COUNTRY_CODE", "HTTP_X_COUNTRY_CODE"] as $h) { if (!empty($_SERVER[$h]) && strlen($_SERVER[$h]) === 2) { return strtoupper(sanitize_text_field($_SERVER[$h])); } } return ""; } private static function is_bot($ua) { if (!$ua) { return true; } return (bool) preg_match( "/bot|crawl|slurp|spider|mediapartners|facebookexternalhit|embedly|quora|pingdom|monitor|headless|lighthouse|gtmetrix/i", $ua ); } }