0, 'This Week' => 0, 'This Month' => 0, '30-90 Days' => 0, '90+ Days' => 0, 'Unknown' => 0 ]; $createdByMonth = []; $memberCountRanges = ['1-5' => 0, '6-10' => 0, '11-25' => 0, '26-50' => 0, '51-100' => 0, '100+' => 0]; $userCoverage = []; $topSpaces = []; $dormantSpaces = []; // Additional derived stats $totalMembers = 0; $threadedCount = 0; $externalCount = 0; $noDescCount = 0; $avgMembersSpace = 0; $avgMembersGroup = 0; $avgMembersDM = 0; $spaceMembersTotal = 0; $groupMembersTotal = 0; $dmMembersTotal = 0; // User overlap matrix $impersonatedUsers = [ 'admin@livetimelapse.com.au', 'ben@livetimelapse.com.au', 'kerri@livetimelapse.com.au', 'paige@livetimelapse.com.au', 'adam@livetimelapse.com.au', 'reece@livetimelapse.com.au', 'billy@livetimelapse.com.au', 'cameron@livetimelapse.com.au' ]; foreach ($impersonatedUsers as $email) { $userCoverage[ucfirst(explode('@', $email)[0])] = 0; } // Space age distribution $ageBuckets = ['< 1 month' => 0, '1-3 months' => 0, '3-6 months' => 0, '6-12 months' => 0, '1-2 years' => 0, '2+ years' => 0]; foreach ($spaces as $space) { // Type distribution switch ($space['type'] ?? '') { case 'Space': $typeSpaces++; break; case 'Group Chat': $typeGroupChats++; break; case 'Direct Message': $typeDMs++; break; } // Member counts by type $mc = $space['member_count'] ?? 0; $totalMembers += $mc; if ($space['type'] === 'Space') { $spaceMembersTotal += $mc; } elseif ($space['type'] === 'Group Chat') { $groupMembersTotal += $mc; } else { $dmMembersTotal += $mc; } // Threaded/External/Description counts if (!empty($space['threaded'])) $threadedCount++; if (!empty($space['external_user_allowed'])) $externalCount++; if (empty($space['description']) || $space['description'] === '[No Description]') $noDescCount++; // Activity analysis $lastActive = !empty($space['last_active_time']) ? strtotime($space['last_active_time']) : 0; if ($lastActive > 0) { $daysSinceActive = ($now - $lastActive) / 86400; if ($daysSinceActive < 1) { $activeToday++; $activityBuckets['Today']++; } elseif ($daysSinceActive < 7) { $activeWeek++; $activityBuckets['This Week']++; } elseif ($daysSinceActive < 30) { $activeMonth++; $activityBuckets['This Month']++; } elseif ($daysSinceActive < 90) { $activityBuckets['30-90 Days']++; $dormant30++; } else { $activityBuckets['90+ Days']++; } if ($daysSinceActive >= 30) { $dormantSpaces[] = [ 'name' => $space['display_name'], 'space_id' => $space['space_id'], 'type' => $space['type'], 'last_active' => $space['last_active_time'], 'days_dormant' => round($daysSinceActive), 'member_count' => $mc ]; } } else { $activityBuckets['Unknown']++; } // Creation timeline if (!empty($space['create_time']) && $space['create_time'] !== 'Unknown') { $createTs = strtotime($space['create_time']); if ($createTs > 0) { $monthKey = date('Y-m', $createTs); $createdByMonth[$monthKey] = ($createdByMonth[$monthKey] ?? 0) + 1; // Age distribution $ageMonths = ($now - $createTs) / (86400 * 30); if ($ageMonths < 1) $ageBuckets['< 1 month']++; elseif ($ageMonths < 3) $ageBuckets['1-3 months']++; elseif ($ageMonths < 6) $ageBuckets['3-6 months']++; elseif ($ageMonths < 12) $ageBuckets['6-12 months']++; elseif ($ageMonths < 24) $ageBuckets['1-2 years']++; else $ageBuckets['2+ years']++; } } // Member count ranges if ($mc > 100) $memberCountRanges['100+']++; elseif ($mc > 50) $memberCountRanges['51-100']++; elseif ($mc > 25) $memberCountRanges['26-50']++; elseif ($mc > 10) $memberCountRanges['11-25']++; elseif ($mc > 5) $memberCountRanges['6-10']++; else $memberCountRanges['1-5']++; // Top spaces by member count if ($mc > 0 && $space['type'] !== 'Direct Message') { $topSpaces[] = ['name' => $space['display_name'], 'space_id' => $space['space_id'], 'member_count' => $mc, 'type' => $space['type']]; } // User coverage if (isset($space['users']) && is_array($space['users'])) { foreach ($space['users'] as $email) { $userName = ucfirst(explode('@', $email)[0]); if (isset($userCoverage[$userName])) $userCoverage[$userName]++; } } } // Averages $avgMembersSpace = $typeSpaces > 0 ? round($spaceMembersTotal / $typeSpaces, 1) : 0; $avgMembersGroup = $typeGroupChats > 0 ? round($groupMembersTotal / $typeGroupChats, 1) : 0; $avgMembersDM = $typeDMs > 0 ? round($dmMembersTotal / $typeDMs, 1) : 0; // Sort collections usort($topSpaces, function($a, $b) { return $b['member_count'] - $a['member_count']; }); $topSpaces = array_slice($topSpaces, 0, 20); usort($dormantSpaces, function($a, $b) { return $b['days_dormant'] - $a['days_dormant']; }); $dormantTop = array_slice($dormantSpaces, 0, 30); ksort($createdByMonth); $recentMonths = array_slice($createdByMonth, -24, 24, true); // ========== JSON ENCODE FOR JS ========== $activityBucketsJson = json_encode(array_values($activityBuckets)); $activityLabelsJson = json_encode(array_keys($activityBuckets)); $typeDataJson = json_encode([$typeSpaces, $typeGroupChats, $typeDMs]); $createdLabelsJson = json_encode(array_keys($recentMonths)); $createdDataJson = json_encode(array_values($recentMonths)); $userLabelsJson = json_encode(array_keys($userCoverage)); $userDataJson = json_encode(array_values($userCoverage)); $memberRangeLabelsJson = json_encode(array_keys($memberCountRanges)); $memberRangeDataJson = json_encode(array_values($memberCountRanges)); $ageBucketLabelsJson = json_encode(array_keys($ageBuckets)); $ageBucketDataJson = json_encode(array_values($ageBuckets)); // Message stats for JS $msgByUserLabelsJson = '[]'; $msgByUserDataJson = '[]'; $msgByMonthLabelsJson = '[]'; $msgByMonthDataJson = '[]'; $msgByDowLabelsJson = '[]'; $msgByDowDataJson = '[]'; $msgByHourDataJson = json_encode(array_fill(0, 24, 0)); $msgTopSpacesJson = '[]'; $msgUserActivityJson = '{}'; if ($hasMsgStats) { $msgByUser = $msgStats['messages_by_user'] ?? []; arsort($msgByUser); $msgByUserLabelsJson = json_encode(array_keys($msgByUser)); $msgByUserDataJson = json_encode(array_values($msgByUser)); $msgByMonth = $msgStats['messages_by_month'] ?? []; ksort($msgByMonth); $msgByMonthLabelsJson = json_encode(array_keys($msgByMonth)); $msgByMonthDataJson = json_encode(array_values($msgByMonth)); $msgByDow = $msgStats['messages_by_day_of_week'] ?? []; $msgByDowLabelsJson = json_encode(array_keys($msgByDow)); $msgByDowDataJson = json_encode(array_values($msgByDow)); $msgByHourDataJson = json_encode(array_values($msgStats['messages_by_hour'] ?? array_fill(0, 24, 0))); // Top spaces by message count $topMsgSpaces = []; foreach (($msgStats['messages_by_space'] ?? []) as $sn => $info) { $topMsgSpaces[] = $info; } $msgTopSpacesJson = json_encode(array_slice($topMsgSpaces, 0, 20)); // User space activity $msgUserActivityJson = json_encode($msgStats['user_space_activity'] ?? []); } ?> Analytics - TLC Space Manager

Analytics Dashboard

spaces | Cache

Total Spaces
Active Today
Active This Week
Dormant 30+ Days
Messages (d)
Avg Msgs/Space
%
Thread Reply Rate
Spaces Scanned

Space Breakdown

Spaces (avg members)
Group Chats (avg members)
Direct Messages
Threaded ( 0 ? round($threadedCount / $totalSpaces * 100, 1) : 0; ?>%)
External Allowed ( 0 ? round($externalCount / $totalSpaces * 100, 1) : 0; ?>%)
Have Descriptions ( 0 ? round(($totalSpaces - $noDescCount) / $totalSpaces * 100, 1) : 0; ?>%)
Total Memberships
0 ? round($totalMembers / $totalSpaces, 1) : 0; ?> Avg Members/Space

Message Analytics (Last Days)

Collected from spaces in minutes

Messages by User

Messages by Month

Messages by Day of Week

Messages by Hour of Day (AEST)

Most Active Spaces by Messages

#Space NameTypeMessagesUnique SendersMembersLink

User Messaging Summary

UserTotal Messages% of TotalMost Active In

Busiest Days

$count): $rank++; $pct = $maxDayMsgs > 0 ? round($count / $maxDayMsgs * 100) : 0; $dayName = date('l', strtotime($date)); $dateFormatted = date('M j, Y', strtotime($date)); ?>
#DateDayMessagesVisual

Message Statistics Not Yet Collected

Run the message stats collection to see messaging analytics including volume by user, time patterns, and activity breakdown.

Collect Message Stats

Activity Breakdown

Type Distribution

Spaces Created Per Month (Last 24 Months)

User Coverage (Spaces per User)

Member Count Distribution

Space Age Distribution

Engagement Rates

$count) { $pct = $totalSpaces > 0 ? round($count / $totalSpaces * 100, 1) : 0; $barWidth = min($pct * 2, 100); echo "
" . "$user" . "
" . "
" . "$pct%" . "
"; } ?>

Top Spaces by Member Count

$s): ?>
#Space NameTypeMembersLink
View
No data available.

Dormant Spaces (30+ Days Inactive)

spaces with no activity in 30+ days

Space NameTypeMembersLast ActiveDays DormantLink
0 ? number_format($s['member_count']) : '-'; ?> days View
No dormant spaces found.