운영 기능 및 GA4 대시보드 반영

This commit is contained in:
박성필
2026-08-18 10:53:58 +09:00
parent 612e87847c
commit b492abd3b4
24 changed files with 1521 additions and 77 deletions

View File

@@ -1 +1,38 @@
<header class="admin-page-heading"><div><span>OVERVIEW</span><h1>대시보드</h1><p>사이트 콘텐츠와 문의 현황입니다.</p></div></header><section class="metric-grid" aria-label="운영 현황"><a href="/admin/posts"><span>전체 </span><strong><?= e($counts['posts']) ?></strong></a><a href="/admin/posts"><span>공개 글</span><strong><?= e($counts['published']) ?></strong></a><a href="/admin/inquiries"><span>전체 문의</span><strong><?= e($counts['inquiries']) ?></strong></a><a href="/admin/inquiries"><span>처리 대기</span><strong><?= e($counts['pending']) ?></strong></a></section>
<?php
$summary = $analytics['summary'] ?? [];
$daily = $analytics['daily'] ?? [];
$maxViews = max(1, ...array_map(static fn(array $item): int => (int) ($item['views'] ?? 0), $daily ?: [['views' => 0]]));
$channelLabels = [
'Direct' => '직접 유입',
'Organic Search' => '검색 유입',
'Organic Social' => '소셜 유입',
'Referral' => '외부 링크',
'Unassigned' => '미분류',
];
?>
<header class="admin-page-heading"><div><span>OVERVIEW</span><h1>대시보드</h1><p>사이트 콘텐츠, 문의, 방문 현황입니다.</p></div></header>
<section class="metric-grid" aria-label="운영 현황"><a href="/admin/posts"><span>전체 글</span><strong><?= e($counts['posts']) ?></strong></a><a href="/admin/posts"><span>공개 글</span><strong><?= e($counts['published']) ?></strong></a><a href="/admin/inquiries"><span>전체 문의</span><strong><?= e($counts['inquiries']) ?></strong></a><a href="/admin/inquiries"><span>처리 대기</span><strong><?= e($counts['pending']) ?></strong></a></section>
<section class="analytics-section" aria-labelledby="analytics-heading">
<header class="analytics-heading"><div><span>GOOGLE ANALYTICS</span><h2 id="analytics-heading">방문 현황</h2><p>운영 사이트의 최근 30일 통계입니다. 관리자와 테스트 페이지는 제외됩니다.</p></div><?php if (!empty($analytics['cached_at'])): ?><small><?= e(date('Y.m.d H:i', (int) $analytics['cached_at'])) ?> 기준 · 15분 간격 갱신<?= !empty($analytics['stale']) ? ' · 마지막 정상 데이터' : '' ?></small><?php endif; ?></header>
<?php if (empty($analytics['available'])): ?>
<div class="analytics-unavailable" role="status"><strong>방문 통계를 표시할 수 없습니다.</strong><p><?= e($analytics['message'] ?? '잠시 후 다시 확인해 주세요.') ?></p></div>
<?php else: ?>
<div class="analytics-metrics" aria-label="방문 핵심 지표">
<article><span>최근 접속자</span><strong><?= e(number_format((int) ($analytics['realtime'] ?? 0))) ?></strong><small>최근 30분 내 활동</small></article>
<article><span>전체 방문자</span><strong><?= e(number_format((int) ($analytics['all_time_users'] ?? 0))) ?></strong><small>2026.08.12 측정 시작 이후</small></article>
<article><span>30일 방문자</span><strong><?= e(number_format((int) ($summary['active_users'] ?? 0))) ?></strong><small>최근 30일 내 활동</small></article>
<article><span>처음 온 방문자</span><strong><?= e(number_format((int) ($summary['new_users'] ?? 0))) ?></strong><small>최근 30일 첫 방문</small></article>
<article><span>페이지 열람 수</span><strong><?= e(number_format((int) ($summary['page_views'] ?? 0))) ?></strong><small>같은 페이지 반복 포함</small></article>
<article><span>사이트 방문 횟수</span><strong><?= e(number_format((int) ($summary['sessions'] ?? 0))) ?></strong><small>방문을 시작한 횟수</small></article>
</div>
<div class="analytics-panel analytics-chart-panel">
<div class="analytics-panel-heading"><h3>14일 페이지 열람 추이</h3><span><i></i> 열람 수</span></div>
<?php if ($daily): ?><div class="analytics-chart" role="img" aria-label="최근 14일 일별 페이지 열람 수 막대 차트"><?php foreach ($daily as $item): ?><div class="analytics-bar" title="<?= e($item['date']) ?> · 페이지 열람 <?= e($item['views']) ?> · 방문자 <?= e($item['users']) ?>"><span><?= e($item['views']) ?></span><i style="height:<?= e(max(3, (int) round(((int) $item['views'] / $maxViews) * 100))) ?>%"></i><small><?= e($item['date']) ?></small></div><?php endforeach; ?></div><?php else: ?><p class="analytics-empty">아직 집계된 방문 데이터가 없습니다.</p><?php endif; ?>
</div>
<div class="analytics-detail-grid">
<section class="analytics-panel"><div class="analytics-panel-heading"><h3>많이 본 페이지</h3><span>열람 수</span></div><?php if (!empty($analytics['pages'])): ?><ol class="analytics-ranking"><?php foreach ($analytics['pages'] as $page): ?><li><div><strong><?= e($page['title']) ?></strong><small><?= e($page['path']) ?></small></div><b><?= e(number_format((int) $page['views'])) ?></b></li><?php endforeach; ?></ol><?php else: ?><p class="analytics-empty">아직 집계된 페이지가 없습니다.</p><?php endif; ?></section>
<section class="analytics-panel"><div class="analytics-panel-heading"><h3>방문한 경로</h3><span>방문 횟수 / 방문자</span></div><?php if (!empty($analytics['channels'])): ?><ol class="analytics-ranking"><?php foreach ($analytics['channels'] as $channel): ?><li><div><strong><?= e($channelLabels[$channel['channel']] ?? $channel['channel']) ?></strong><small><?= e($channel['channel']) ?></small></div><b><?= e(number_format((int) $channel['sessions'])) ?> / <?= e(number_format((int) $channel['users'])) ?></b></li><?php endforeach; ?></ol><?php else: ?><p class="analytics-empty">아직 집계된 유입 데이터가 없습니다.</p><?php endif; ?></section>
</div>
<?php endif; ?>
</section>