Creating A Stats Page In PureBlog
| 1 min read
I recently started using PureBlog for my main IndieWeb home and I really like it. It has every feature I need and it's simple and lightweight. I have been making some additions for it, such as an automatically updating sitemap, but here's a simple statistics page too. Basically copied from admin/dashboard.php with some alterations.
- Go to routes and enter this:
/stats | /content/includes/stats.php
- Make stats.php in content/includes on your server and the contents should be this:
require PUREBLOG_BASE_PATH . '/includes/header.php';
render_masthead_layout($config, ['page' => null]);
?>
<main>
<h1> Stats </h1>
<?php
$publishedPosts = array_values(array_filter(get_all_posts(true), static fn(array $post): bool => ($post['status'] ?? 'draft') === 'published'));
$publishedCount = count($publishedPosts);
$tz = site_timezone_object($config);
$now = new DateTimeImmutable('now', $tz);
$currentYear = (int) $now->format('Y');
$publishedThisYear = 0;
$totalWordsThisYear = 0;
$tagCounts = [];
$tagCountsThisYear = [];
$tagDisplayNames = [];
$totalWords = 0;
$allTimeMonthCounts = array_fill(1, 12, 0);
$allTimeDayCounts = array_fill(1, 7, 0); // 1=Mon … 7=Sun (ISO 8601)
$yearCounts = [];
$chartMonths = [];
$firstOfMonth = new DateTimeImmutable($now->format('Y-m-01'), $tz);
for ($i = 11; $i >= 0; $i--) {
$dt = $firstOfMonth->modify("-{$i} months");
$month = (int) $dt->format('n');
$chartMonths[] = [
'year' => (int) $dt->format('Y'),
'month' => $month,
'label' => t('date.months_short.' . ($month - 1)),
'count' => 0,
];
}
$chartIndex = [];
foreach ($chartMonths as $idx => $cm) {
$chartIndex[$cm['year'] . '-' . $cm['month']] = $idx;
}
$recentCutoff = $firstOfMonth->modify('-11 months')->getTimestamp();
foreach ($publishedPosts as $post) {
$content = (string) ($post['content'] ?? '');
$totalWords += str_word_count($content);
$timestamp = (int) ($post['timestamp'] ?? 0);
if ($timestamp > 0) {
$dt = (new DateTimeImmutable('@' . $timestamp))->setTimezone($tz);
$postYear = (int) $dt->format('Y');
$postMon = (int) $dt->format('n');
$postDay = (int) $dt->format('N'); // 1=Mon … 7=Sun
$chartKey = $postYear . '-' . $postMon;
if (isset($chartIndex[$chartKey])) {
$chartMonths[$chartIndex[$chartKey]]['count']++;
}
if ($timestamp >= $recentCutoff) {
$publishedThisYear++;
$totalWordsThisYear += str_word_count($content);
}
$allTimeMonthCounts[$postMon]++;
$allTimeDayCounts[$postDay]++;
$yearCounts[$postYear] = ($yearCounts[$postYear] ?? 0) + 1;
}
$tags = $post['tags'] ?? [];
if (!is_array($tags)) {
continue;
}
foreach ($tags as $tag) {
$name = trim((string) $tag);
if ($name !== '') {
$slug = normalize_tag($name);
$tagDisplayNames[$slug] ??= $name;
$tagCounts[$slug] = ($tagCounts[$slug] ?? 0) + 1;
if ($timestamp >= $recentCutoff) {
$tagCountsThisYear[$slug] = ($tagCountsThisYear[$slug] ?? 0) + 1;
}
}
}
}
ksort($yearCounts);
$maxYearCount = !empty($yearCounts) ? max($yearCounts) : 1;
$avgWordsAllTime = $publishedCount > 0 ? (int) round($totalWords / $publishedCount) : 0;
$avgWordsThisYear = $publishedThisYear > 0 ? (int) round($totalWordsThisYear / $publishedThisYear) : 0;
$booksEquivalent = $totalWords > 0 ? round($totalWords / 80000, 1) : 0;
$booksThisYear = $totalWordsThisYear > 0 ? round($totalWordsThisYear / 80000, 1) : 0;
$lastTimestamp = 0;
foreach ($publishedPosts as $post) {
$ts = (int) ($post['timestamp'] ?? 0);
if ($ts > $lastTimestamp) {
$lastTimestamp = $ts;
}
}
$lastPublishedAgo = $lastTimestamp > 0 ? relative_time($lastTimestamp) : t('admin.dashboard.no_posts_yet');
?>
</main>
<?php render_footer_layout($config, ['page' => null]); ?>
</body>
- Add the link to your site wherever (I have mine on the blog page)
There you go! Here's mine, for a live preview.