管理画面 — ダッシュボード仕様 (FR-014)
| 項目 | 内容 |
|---|---|
| 対象FR | FR-014(管理画面 — ダッシュボード) |
| 優先度 | 低 |
| ステータス | 詳細化済み |
| フェーズ | Phase 6 |
概要
運用担当者は管理画面のダッシュボードでシステム統計を確認できる。表示形式は数値カード(主要KPIのスナップショット)と時系列グラフ(推移データ)の2種類を提供する。機能利用状況の収集・コホート分析・A/Bテスト用のセグメント分析にも対応し、プロダクトの実験計画を立てられる基盤とする。
前提条件(依存FR)
| 依存FR | 必要な機能 | 用途 |
|---|---|---|
| FR-012(ユーザー管理) | 管理者認証・RBAC | ダッシュボードへのアクセス制御 |
数値カード(サマリー)
画面上部に主要KPIをカード形式で表示する。
| カード | 値 | 前期比 |
|---|---|---|
| 総ユーザー数 | users テーブルの有効ユーザー数 | 前月比 |
| アクティブユーザー数 | 直近30日にログインしたユーザー数 | 前月比 |
| 総ペット数 | pets テーブルの有効ペット数 | 前月比 |
| 新規登録数(今月) | 今月の新規ユーザー登録数 | 前月比 |
前期比は増減率(%)と増減数で表示する。
時系列グラフ(トレンド)
表示可能な指標
| 指標 | キー | 説明 |
|---|---|---|
| 新規ユーザー | newUsers | 日別の新規ユーザー登録数 |
| アクティブユーザー | activeUsers | 日別のアクティブユーザー数(ログインベース) |
| 新規ペット | newPets | 日別の新規ペット登録数 |
| 記録数 | newRecords | 日別の全健康記録作成数 |
期間指定
| パラメータ | デフォルト | 選択肢 |
|---|---|---|
| period | 30d | 7d / 30d / 90d / 180d / 1y |
| granularity | 自動 | day / week / month(7d/30d→day、90d/180d→week、1y→month) |
機能利用状況
各機能の利用頻度を集計し、どの機能がどれだけ使われているかを可視化する。
収集対象イベント
| イベント | event_name | 説明 |
|---|---|---|
| 体重記録作成 | weight.created | 体重記録の新規作成 |
| 食事記録作成 | meal.created | 食事記録の新規作成 |
| 通院記録作成 | vetVisit.created | 通院記録の新規作成 |
| ワクチン記録作成 | vaccination.created | ワクチン記録の新規作成 |
| 体調ログ作成 | healthLog.created | 体調ログの新規作成 |
| 投薬記録作成 | medication.created | 投薬スケジュールの新規作成 |
| 投薬ログ記録 | medicationLog.created | 投薬ログの新規作成 |
| ペット共有 | share.created | ペット共有の新規作成 |
表示形式
- 期間別集計テーブル: 各イベントの発生回数とユニークユーザー数
- 機能別棒グラフ: 各機能の利用回数比較
- 時系列折れ線グラフ: 指定期間の機能別利用推移
コホート分析
ユーザーを登録月で分類し、月ごとのリテンション率を計算する。
コホートテーブル
| 月0 | 月1 | 月2 | 月3 | … | |
|---|---|---|---|---|---|
| 2026年1月(100人) | 100% | 60% | 45% | 40% | … |
| 2026年2月(120人) | 100% | 55% | - | - | … |
- 「アクティブ」の定義: 当該月にログインしたユーザー
- 月0 は登録月(常に100%)
パラメータ
| パラメータ | 型 | デフォルト | 説明 |
|---|---|---|---|
| months | integer | 6 | 表示する月数(最大12) |
| activityType | varchar | login | login(ログイン) / record(記録作成) |
セグメント分析(実験計画基盤)
ユーザーをセグメントに分けて指標を比較でき、A/Bテストや施策の効果測定に利用する。
セグメント条件
| 条件 | キー | 型 | 例 |
|---|---|---|---|
| 登録日範囲 | registeredBetween | date[] | ["2026-01-01", "2026-01-31"] |
| ペット数 | petCountRange | integer[] | [1, 3](1〜3匹のユーザー) |
| 利用機能 | usedFeatures | varchar[] | ["weight", "meal"](体重と食事を利用) |
| 未利用機能 | unusedFeatures | varchar[] | ["medication"](投薬未利用) |
| アクティブ状態 | isActive | boolean | 直近30日にログインしたか |
比較指標
| 指標 | 説明 |
|---|---|
| ユーザー数 | セグメントに該当するユーザー数 |
| リテンション率 | 直近30日のリテンション率 |
| 平均ペット数 | セグメント内の平均ペット数 |
| 平均記録頻度 | 週あたりの平均記録作成数 |
| 機能利用率 | 各機能を使ったユーザーの割合 |
レスポンス例
{ "data": { "segmentA": { "name": "体重記録ユーザー", "conditions": { "usedFeatures": ["weight"] }, "metrics": { "userCount": 80, "retentionRate": 0.65, "avgPetCount": 1.8, "avgRecordsPerWeek": 4.2, "featureUsage": { "weight": 1.0, "meal": 0.45, "vetVisit": 0.30, "vaccination": 0.25, "healthLog": 0.20, "medication": 0.15 } } }, "segmentB": { "name": "体重記録未使用ユーザー", "conditions": { "unusedFeatures": ["weight"] }, "metrics": { "userCount": 40, "retentionRate": 0.30, "avgPetCount": 1.2, "avgRecordsPerWeek": 1.1, "featureUsage": { "weight": 0.0, "meal": 0.20, "vetVisit": 0.15, "vaccination": 0.10, "healthLog": 0.10, "medication": 0.05 } } } }}APIエンドポイント
全エンドポイントで管理者認証必須。
| メソッド | パス | 概要 | 必要権限 |
|---|---|---|---|
| GET | /api/admin/dashboard/summary | サマリーカード | dashboard.view |
| GET | /api/admin/dashboard/trends | 時系列データ | dashboard.view |
| GET | /api/admin/dashboard/feature-usage | 機能利用状況 | dashboard.view |
| GET | /api/admin/dashboard/cohorts | コホート分析 | dashboard.view |
| POST | /api/admin/dashboard/segments/compare | セグメント比較 | dashboard.view |
| GET | /api/admin/dashboard/export | データエクスポート | dashboard.export |
GET /api/admin/dashboard/summary — サマリーカード
{ "data": { "totalUsers": { "value": 150, "previousValue": 120, "changeRate": 0.25, "changeCount": 30 }, "activeUsers": { "value": 85, "previousValue": 70, "changeRate": 0.214, "changeCount": 15 }, "totalPets": { "value": 230, "previousValue": 180, "changeRate": 0.278, "changeCount": 50 }, "newUsersThisMonth": { "value": 30, "previousValue": 25, "changeRate": 0.20, "changeCount": 5 } }}GET /api/admin/dashboard/trends — 時系列データ
| パラメータ | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
| metric | varchar | ○ | - | newUsers / activeUsers / newPets / newRecords |
| period | varchar | - | 30d | 7d / 30d / 90d / 180d / 1y |
| granularity | varchar | - | 自動 | day / week / month |
{ "data": { "metric": "newUsers", "period": "30d", "granularity": "day", "points": [ { "date": "2026-02-01", "value": 5 }, { "date": "2026-02-02", "value": 3 }, { "date": "2026-02-03", "value": 8 } ] }}GET /api/admin/dashboard/feature-usage — 機能利用状況
| パラメータ | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
| period | varchar | - | 30d | 集計期間 |
{ "data": { "period": "30d", "features": [ { "name": "weight", "label": "体重記録", "totalCount": 450, "uniqueUsers": 80 }, { "name": "meal", "label": "食事記録", "totalCount": 320, "uniqueUsers": 55 }, { "name": "vetVisit", "label": "通院履歴", "totalCount": 45, "uniqueUsers": 30 } ] }}GET /api/admin/dashboard/cohorts — コホート分析
| パラメータ | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
| months | integer | - | 6 | 表示月数(最大12) |
| activityType | varchar | - | login | login / record |
{ "data": { "activityType": "login", "cohorts": [ { "month": "2026-01", "size": 100, "retention": [1.0, 0.60, 0.45, 0.40] }, { "month": "2026-02", "size": 120, "retention": [1.0, 0.55] } ] }}POST /api/admin/dashboard/segments/compare — セグメント比較
// リクエスト{ "segmentA": { "name": "体重記録ユーザー", "conditions": { "usedFeatures": ["weight"] } }, "segmentB": { "name": "体重記録未使用ユーザー", "conditions": { "unusedFeatures": ["weight"] } }}レスポンスは「セグメント分析」セクションのレスポンス例を参照。
GET /api/admin/dashboard/export — データエクスポート
| パラメータ | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
| type | varchar | ○ | - | summary / trends / feature-usage / cohorts |
| format | varchar | - | csv | csv / json |
| period | varchar | - | 30d | 集計期間 |
- 成功時:
200 OK、Content-Type に応じたファイルダウンロード - Content-Disposition:
attachment; filename="dashboard-{type}-{date}.{format}"
DBテーブル(追加)
analytics_events
機能利用状況の収集とセグメント分析の基盤データ。
| カラム | 型 | 備考 |
|---|---|---|
| id | serial | 主キー |
| user_id | integer | FK → users.id |
| event_name | varchar | イベント名(例: weight.created) |
| properties | jsonb | 追加データ(nullable) |
| created_at | timestamptz | 発生日時 |
(user_id, event_name, created_at)にインデックス- 各健康記録の作成時にイベントを自動記録する
- 古いイベントデータの保持期間: 1年(1年経過後にバッチで物理削除)
認可ルール
- 全エンドポイントで
users.role = 'admin'であること dashboard.view権限でサマリー・トレンド・機能利用・コホート・セグメント比較にアクセス可能dashboard.export権限でデータエクスポートにアクセス可能- 権限がない操作:
403 Forbidden
エッジケース
- データが存在しない期間 → 値
0のポイントを返す(欠損させない) - コホート分析で登録月のデータがない場合 → 該当月をスキップ
- セグメント条件に該当するユーザーが0人 →
userCount: 0で他の指標も0/nullを返す - 大量データでの集計パフォーマンス → 日次バッチで中間テーブル(集計テーブル)に事前集計し、APIはそこから読む
- アナリティクスイベントの書き込み失敗 → 本体処理には影響させない(非同期 + best-effort)
拡張予定(現時点ではスコープ外)
- リアルタイムダッシュボード(WebSocket)
- カスタムダッシュボード(ウィジェットの配置変更)
- アラート設定(KPIが閾値を超えた場合の通知)
- ファネル分析(登録→ペット登録→記録開始の完了率)
- ユーザーセグメントの保存・再利用
- 外部BIツール連携(Metabase等)
検証方法
- サマリーカードの値が正しく集計されていること
- 前期比(増減率・増減数)が正しく計算されること
- 時系列グラフのデータが指定期間・粒度で返ること
- データが存在しない日でも値
0のポイントが含まれること - 機能利用状況が正しく集計されること(totalCount、uniqueUsers)
- コホートテーブルのリテンション率が正しく計算されること
- セグメント比較で2つのセグメントの指標が正しく計算されること
- 条件に該当するユーザーが0人の場合にエラーにならないこと
- データエクスポートが正しいフォーマットでダウンロードできること
- 一般ユーザーが管理者APIにアクセスした場合に
403が返ること - アナリティクスイベントが健康記録作成時に自動記録されること