Files
easystream-main/f_core/f_classes/class.analytics.enhanced.php
SamiAhmed7777 d22b3e1c0d feat: Add complete Docker deployment with web-based setup wizard
Major additions:
- Web-based setup wizard (setup.php, setup_wizard.php, setup-wizard.js)
- Production Docker configuration (docker-compose.prod.yml, .env.production)
- Database initialization SQL files (deploy/init_settings.sql)
- Template builder system with drag-and-drop UI
- Advanced features (OAuth, CDN, enhanced analytics, monetization)
- Comprehensive documentation (deployment guides, quick start, feature docs)
- Design system with accessibility and responsive layout
- Deployment automation scripts (deploy.ps1, generate-secrets.ps1)

Setup wizard allows customization of:
- Platform name and branding
- Domain configuration
- Membership tiers and pricing
- Admin credentials
- Feature toggles

Database includes 270+ tables for complete video streaming platform with
advanced features for analytics, moderation, template building, and monetization.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 01:42:31 -07:00

241 lines
8.0 KiB
PHP

<?php
/**
* EasyStream Enhanced Analytics System
* Event tracking, retention graphs, heatmaps, demographics
* Version: 1.0
*/
defined('_ISVALID') or header('Location: /error');
class VAnalyticsEnhanced {
private static $db;
public static function init() {
self::$db = VDatabase::getInstance();
}
/**
* Track event
* @param string $event_type Event type (view, play, pause, seek, etc.)
* @param string $file_key File key
* @param array $data Additional event data
*/
public static function trackEvent($event_type, $file_key, $data = []) {
self::init();
$usr_id = isset($_SESSION['USER_ID']) ? (int)$_SESSION['USER_ID'] : 'NULL';
$session_id = session_id();
$event_type_safe = VDatabase::escape($event_type);
$file_key_safe = VDatabase::escape($file_key);
$session_safe = VDatabase::escape($session_id);
$data_json = VDatabase::escape(json_encode($data));
$timestamp = isset($data['timestamp']) ? (int)$data['timestamp'] : 'NULL';
$ip = VDatabase::escape($_SERVER['REMOTE_ADDR'] ?? '');
$ua = VDatabase::escape($_SERVER['HTTP_USER_AGENT'] ?? '');
$referrer = VDatabase::escape($_SERVER['HTTP_REFERER'] ?? '');
// Get file type
$typeResult = self::$db->execute("SELECT file_type FROM db_videofiles WHERE file_key = '$file_key_safe'");
$file_type = 'NULL';
if ($typeResult && $typeResult->RecordCount() > 0) {
$row = $typeResult->FetchRow();
$file_type = "'" . VDatabase::escape($row['file_type']) . "'";
}
$sql = "INSERT INTO db_analytics_events
(usr_id, session_id, event_type, file_key, file_type, event_data, timestamp_sec, ip_address, user_agent, referrer, created_at)
VALUES ($usr_id, '$session_safe', '$event_type_safe', '$file_key_safe', $file_type, '$data_json', $timestamp, '$ip', '$ua', '$referrer', NOW())";
self::$db->execute($sql);
// Update retention data for video events
if ($event_type == 'play' || $event_type == 'pause') {
self::updateRetention($file_key, $timestamp);
}
}
/**
* Update retention data
*/
private static function updateRetention($file_key, $timestamp_sec) {
if (!$timestamp_sec) return;
$file_key_safe = VDatabase::escape($file_key);
$timestamp = (int)$timestamp_sec;
$sql = "INSERT INTO db_analytics_retention
(file_key, timestamp_sec, viewers, updated_at)
VALUES ('$file_key_safe', $timestamp, 1, NOW())
ON DUPLICATE KEY UPDATE viewers = viewers + 1, updated_at = NOW()";
self::$db->execute($sql);
}
/**
* Get retention graph data
* @param string $file_key File key
* @return array Retention data by second
*/
public static function getRetentionGraph($file_key) {
self::init();
$file_key_safe = VDatabase::escape($file_key);
$sql = "SELECT timestamp_sec, viewers
FROM db_analytics_retention
WHERE file_key = '$file_key_safe'
ORDER BY timestamp_sec ASC";
$result = self::$db->execute($sql);
$data = [];
if ($result) {
while ($row = $result->FetchRow()) {
$data[] = [
'time' => (int)$row['timestamp_sec'],
'viewers' => (int)$row['viewers']
];
}
}
return $data;
}
/**
* Get traffic sources
* @param string $file_key File key
* @param string $date_from Start date
* @param string $date_to End date
* @return array Traffic sources
*/
public static function getTrafficSources($file_key, $date_from, $date_to) {
self::init();
$file_key_safe = VDatabase::escape($file_key);
$from_safe = VDatabase::escape($date_from);
$to_safe = VDatabase::escape($date_to);
// Analyze referrers from events
$sql = "SELECT
CASE
WHEN referrer = '' THEN 'direct'
WHEN referrer LIKE '%google%' OR referrer LIKE '%bing%' THEN 'search'
WHEN referrer LIKE '%facebook%' OR referrer LIKE '%twitter%' OR referrer LIKE '%instagram%' THEN 'social'
WHEN referrer LIKE '%{$_SERVER['HTTP_HOST']}%' THEN 'internal'
ELSE 'external'
END as source_type,
COUNT(*) as visits
FROM db_analytics_events
WHERE file_key = '$file_key_safe'
AND event_type = 'view'
AND DATE(created_at) BETWEEN '$from_safe' AND '$to_safe'
GROUP BY source_type";
$result = self::$db->execute($sql);
$sources = [];
if ($result) {
while ($row = $result->FetchRow()) {
$sources[] = [
'source' => $row['source_type'],
'visits' => (int)$row['visits']
];
}
}
return $sources;
}
/**
* Get analytics summary
* @param string $file_key File key
* @param string $date_from Start date
* @param string $date_to End date
* @return array Summary data
*/
public static function getSummary($file_key, $date_from, $date_to) {
self::init();
$file_key_safe = VDatabase::escape($file_key);
$from_safe = VDatabase::escape($date_from);
$to_safe = VDatabase::escape($date_to);
$sql = "SELECT
COUNT(DISTINCT session_id) as unique_viewers,
COUNT(*) as total_views,
SUM(CASE WHEN event_type = 'like' THEN 1 ELSE 0 END) as likes,
SUM(CASE WHEN event_type = 'comment' THEN 1 ELSE 0 END) as comments,
SUM(CASE WHEN event_type = 'share' THEN 1 ELSE 0 END) as shares
FROM db_analytics_events
WHERE file_key = '$file_key_safe'
AND DATE(created_at) BETWEEN '$from_safe' AND '$to_safe'";
$result = self::$db->execute($sql);
if ($result && $result->RecordCount() > 0) {
return $result->FetchRow();
}
return [];
}
/**
* Track heatmap click
* @param string $file_key File key
* @param float $x X coordinate (0-1)
* @param float $y Y coordinate (0-1)
* @param string $type Type (click or hover)
*/
public static function trackHeatmap($file_key, $x, $y, $type = 'click') {
self::init();
$file_key_safe = VDatabase::escape($file_key);
$x = (float)$x;
$y = (float)$y;
$date = date('Y-m-d');
$field = $type == 'hover' ? 'hovers' : 'clicks';
$sql = "INSERT INTO db_analytics_heatmaps
(file_key, x_coord, y_coord, $field, date)
VALUES ('$file_key_safe', $x, $y, 1, '$date')
ON DUPLICATE KEY UPDATE $field = $field + 1";
self::$db->execute($sql);
}
/**
* Get heatmap data
* @param string $file_key File key
* @param string $date Date
* @return array Heatmap coordinates
*/
public static function getHeatmap($file_key, $date) {
self::init();
$file_key_safe = VDatabase::escape($file_key);
$date_safe = VDatabase::escape($date);
$sql = "SELECT x_coord, y_coord, clicks, hovers
FROM db_analytics_heatmaps
WHERE file_key = '$file_key_safe' AND date = '$date_safe'";
$result = self::$db->execute($sql);
$heatmap = [];
if ($result) {
while ($row = $result->FetchRow()) {
$heatmap[] = [
'x' => (float)$row['x_coord'],
'y' => (float)$row['y_coord'],
'clicks' => (int)$row['clicks'],
'hovers' => (int)$row['hovers'],
'intensity' => (int)$row['clicks'] + ((int)$row['hovers'] / 10)
];
}
}
return $heatmap;
}
}