format('M j, Y • g:i A'); } catch (Exception $e) { return htmlspecialchars($value, ENT_QUOTES, 'UTF-8'); } } function bind_named_values(PDOStatement $stmt, array $params): void { foreach ($params as $name => $value) { $stmt->bindValue($name, $value, is_int($value) ? PDO::PARAM_INT : PDO::PARAM_STR); } } $message = admin_get_flash(); $pdo = db(); $records_per_page = 15; $page = isset($_GET['page']) && is_numeric($_GET['page']) ? max(1, (int) $_GET['page']) : 1; $selected_webinar_id = isset($_GET['webinar_id']) && is_numeric($_GET['webinar_id']) ? max(0, (int) $_GET['webinar_id']) : 0; $webinars = $pdo->query('SELECT id, title, scheduled_at FROM webinars ORDER BY scheduled_at DESC, id DESC')->fetchAll(PDO::FETCH_ASSOC); $where_parts = ['a.deleted_at IS NULL']; $params = []; if ($selected_webinar_id > 0) { $where_parts[] = 'a.webinar_id = :webinar_id'; $params[':webinar_id'] = $selected_webinar_id; } $where_sql = 'WHERE ' . implode(' AND ', $where_parts); $count_stmt = $pdo->prepare("SELECT COUNT(*) FROM attendees a {$where_sql}"); bind_named_values($count_stmt, $params); $count_stmt->execute(); $total_records = (int) $count_stmt->fetchColumn(); $total_pages = max(1, (int) ceil($total_records / $records_per_page)); if ($page > $total_pages) { $page = $total_pages; } $offset = ($page - 1) * $records_per_page; $today_stmt = $pdo->prepare("SELECT COUNT(*) FROM attendees a {$where_sql} AND DATE(a.created_at) = CURDATE()"); bind_named_values($today_stmt, $params); $today_stmt->execute(); $today_count = (int) $today_stmt->fetchColumn(); $last7_stmt = $pdo->prepare("SELECT COUNT(*) FROM attendees a {$where_sql} AND a.created_at >= (NOW() - INTERVAL 7 DAY)"); bind_named_values($last7_stmt, $params); $last7_stmt->execute(); $last_7_days_count = (int) $last7_stmt->fetchColumn(); $latest_stmt = $pdo->prepare("SELECT MAX(a.created_at) FROM attendees a {$where_sql}"); bind_named_values($latest_stmt, $params); $latest_stmt->execute(); $latest_registration_at = $latest_stmt->fetchColumn(); $company_stmt = $pdo->prepare("SELECT COUNT(DISTINCT NULLIF(TRIM(a.company), '')) FROM attendees a {$where_sql}"); bind_named_values($company_stmt, $params); $company_stmt->execute(); $unique_companies = (int) $company_stmt->fetchColumn(); $attendees_sql = "SELECT a.id, a.webinar_id, a.first_name, a.last_name, a.email, a.company, a.how_did_you_hear, a.timezone, a.consented, a.created_at, w.title AS webinar_title, w.scheduled_at AS webinar_scheduled_at FROM attendees a LEFT JOIN webinars w ON w.id = a.webinar_id {$where_sql} ORDER BY a.created_at DESC, a.id DESC LIMIT :limit OFFSET :offset"; $attendees_stmt = $pdo->prepare($attendees_sql); bind_named_values($attendees_stmt, $params); $attendees_stmt->bindValue(':limit', $records_per_page, PDO::PARAM_INT); $attendees_stmt->bindValue(':offset', $offset, PDO::PARAM_INT); $attendees_stmt->execute(); $attendees = $attendees_stmt->fetchAll(PDO::FETCH_ASSOC); $chart_stmt = $pdo->prepare("SELECT DATE(a.created_at) AS registration_day, COUNT(*) AS user_count FROM attendees a {$where_sql} GROUP BY DATE(a.created_at) ORDER BY DATE(a.created_at)"); bind_named_values($chart_stmt, $params); $chart_stmt->execute(); $chart_data = $chart_stmt->fetchAll(PDO::FETCH_ASSOC); $selected_webinar = null; foreach ($webinars as $webinar) { if ((int) $webinar['id'] === $selected_webinar_id) { $selected_webinar = $webinar; break; } } $chart_labels = json_encode(array_column($chart_data, 'registration_day')); $chart_values = json_encode(array_column($chart_data, 'user_count')); $export_link = 'export_csv.php' . ($selected_webinar_id > 0 ? '?webinar_id=' . urlencode((string) $selected_webinar_id) : ''); ?> Admin Dashboard | Webinar Registrations

Webinar registrations dashboard

Welcome, . Review attendee data, edit registrations, export CSV, and monitor daily signup volume.

Reset
Total registrations
Active attendees.
Registered today
New signups recorded on format('M j, Y'); ?>.
Last 7 days
Rolling weekly registrations based on created_at.
Companies represented
Unique non-empty company names among active attendees.
Latest registration
Most recent active attendee creation timestamp.

Daily registrations

Chart based on attendee created_at, grouped by registration day.

Registered attendees

Showing active records for . Showing active records for all webinars, newest registrations first.

ID Attendee Email Company Source Timezone Webinar Registered at Actions
No attendees found for this filter yet.
Consent:
Edit
1): ?>