# 画面設計書 21-統計（Analytics）画面

## 概要

Ghost管理画面におけるサイト全体の統計分析ダッシュボードを提供するReactアプリケーション（apps/stats）のメイン画面設計書である。

### 本画面の処理概要

統計（Analytics）画面は、Ghostサイト全体のパフォーマンスを可視化・分析するためのダッシュボード画面である。

**業務上の目的・背景**：サイト運営者がコンテンツのパフォーマンスを把握し、データに基づいた意思決定を行うために必要な統計情報を一元的に提供する。Webトラフィック、メンバー成長、ニュースレターの配信状況など、サイト運営に必要な主要KPIを確認できる。Tinybirdとの連携により、大量のアナリティクスデータをリアルタイムに処理・表示することが可能。

**画面へのアクセス方法**：Ghost管理画面のサイドバーから「Analytics」をクリックすることでアクセスする。URLは `/ghost/analytics` となり、Ember.js管理画面からReactアプリ（apps/stats）がマイクロフロントエンドとして埋め込まれる形で表示される。

**主要な操作・処理内容**：
1. 日付範囲の選択（今日、過去7日、過去30日、過去90日、全期間など）
2. Overview（概要）、Web（トラフィック）、Growth（成長）、Newsletters（ニュースレター）の各タブへの切り替え
3. 各種KPI（訪問者数、メンバー数、MRRなど）のチャート表示
4. 人気コンテンツ・トップソースの一覧表示

**画面遷移**：
- 遷移元：ホーム画面、サイドバーナビゲーション
- 遷移先：統計概要画面（/analytics）、Webトラフィック画面（/analytics/web）、成長分析画面（/analytics/growth）、ニュースレター分析画面（/analytics/newsletters）、投稿分析画面（/posts/analytics/:postId）

**権限による表示制御**：統計画面へのアクセスは管理者（Administrator）および編集者（Editor）ロールを持つスタッフユーザーに限定される。一般の投稿者（Author/Contributor）はアクセスできない。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 51 | サイト統計 | 主機能 | サイト全体の統計分析ダッシュボード |
| 55 | Tinybird連携 | 補助機能 | Tinybirdからのアナリティクスデータ取得 |

## 画面種別

ダッシュボード / 一覧

## URL/ルーティング

| パス | コンポーネント | 説明 |
|------|---------------|------|
| `/ghost/#/stats-x` | AdminX::Stats | Ember側のエントリーポイント（stats-x.hbs） |
| `/analytics` | Overview | 統計概要画面（デフォルト） |
| `/analytics/web` | Web | Webトラフィック分析画面 |
| `/analytics/growth` | Growth | 成長分析画面 |
| `/analytics/newsletters` | Newsletters | ニュースレター分析画面 |

## 入出力項目

### 入力項目

| 項目名 | 項目ID | データ型 | 必須 | 説明 |
|--------|--------|----------|------|------|
| 日付範囲 | range | number | Yes | 統計の表示期間（7, 30, 90, -1など） |
| ニュースレターID | selectedNewsletterId | string | No | 選択されたニュースレター |

### 出力項目

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| 訪問者数 | number | 期間内の総訪問者数 |
| ページビュー数 | number | 期間内の総ページビュー数 |
| メンバー数 | number | 期間内のメンバー数 |
| MRR | number | 月間経常収益 |

## 表示項目

### グローバルデータ

| 項目名 | データ型 | 説明 | 取得元 |
|--------|----------|------|--------|
| statsConfig | StatsConfig | Tinybird統計設定 | useBrowseConfig |
| tinybirdToken | string | Tinybird APIトークン | useTinybirdToken |
| site | object | サイト情報（URL、アイコン等） | useBrowseSite |
| settings | Setting[] | サイト設定 | useBrowseSettings |

## イベント仕様

### 1-日付範囲変更

ユーザーが日付範囲セレクターで期間を変更した際、GlobalDataProviderのstateが更新され、すべての子コンポーネントが新しい期間でデータを再取得する。

**処理フロー**：
1. DateRangeSelectコンポーネントで期間を選択
2. setRange関数が呼び出される
3. GlobalDataContext経由で全コンポーネントにrange値が伝播
4. 各コンポーネントのuseTinybirdQueryが新しいparamsで再実行

### 2-タブ切り替え

ナビゲーションタブをクリックすると、React Routerにより対応する子ルートに遷移する。

**処理フロー**：
1. ナビゲーションリンクをクリック
2. RouterProviderがURLを更新
3. 対応するコンポーネント（Overview/Web/Growth/Newsletters）がレンダリング

### 3-投稿分析への遷移

トップコンテンツ一覧から特定の投稿をクリックすると、投稿分析画面に遷移する。

**処理フロー**：
1. 投稿タイトルをクリック
2. navigate関数で `/posts/analytics/:postId` に遷移
3. PostAnalyticsProviderが対象投稿のデータを取得

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | - | SELECT（Tinybird） | Tinybirdからアナリティクスデータを取得 |

### テーブル別更新項目詳細

統計画面は参照専用のため、Ghostデータベースへの更新は発生しない。データはTinybird APIから取得される。

#### Tinybird API

| エンドポイント | パラメータ | 説明 |
|---------------|-----------|------|
| api_kpis | site_uuid, date_from, date_to, timezone | KPIデータ取得 |
| api_top_sources | site_uuid, date_from, date_to, timezone | トップソース取得 |
| api_top_locations | site_uuid, date_from, date_to, timezone | トップロケーション取得 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| MSG-001 | 情報 | No data available | データが存在しない場合 |
| MSG-002 | エラー | Failed to load analytics | API取得失敗時 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| Tinybird設定なし | 統計機能が無効の旨を表示 |
| APIエラー | StatsErrorBoundaryでキャッチし、エラーページを表示 |
| 認証エラー | ログイン画面にリダイレクト |

## 備考

- 統計データはTinybird（外部サービス）に保存されており、Ghost本体のデータベースとは別管理
- Webアナリティクス機能が無効の場合、Web画面は表示されずリダイレクトされる
- ニュースレター機能が無効の場合、Newsletters画面は表示されずリダイレクトされる

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、アプリケーション全体で共有されるグローバルデータの構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | global-data-provider.tsx | `apps/stats/src/providers/global-data-provider.tsx` | GlobalData型の定義、statsConfig/tinybirdTokenの取得方法 |
| 1-2 | constants.ts | `apps/stats/src/utils/constants.ts` | STATS_RANGE_OPTIONS等の定数定義 |

**読解のコツ**: GlobalDataContextが提供するdata, statsConfig, range, settingsがすべてのビューで使用される。useGlobalDataフックの戻り値を確認すること。

#### Step 2: エントリーポイントを理解する

処理の起点となるファイルを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | app.tsx | `apps/stats/src/app.tsx` | Appコンポーネントの構造、Provider階層 |
| 2-2 | routes.tsx | `apps/stats/src/routes.tsx` | ルーティング定義、遅延ロード設定 |
| 2-3 | stats-x.hbs | `ghost/admin/app/templates/stats-x.hbs` | Ember側のテンプレート |

**主要処理フロー**:
1. **9-31行目（app.tsx）**: FrameworkProvider -> AppProvider -> RouterProvider -> GlobalDataProviderの階層でラップ
2. **10-31行目（routes.tsx）**: /analyticsパス配下の子ルート定義

#### Step 3: レイアウトコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | stats-layout.tsx | `apps/stats/src/views/Stats/layout/stats-layout.tsx` | 統計画面共通レイアウト |
| 3-2 | stats-header.tsx | `apps/stats/src/views/Stats/layout/stats-header.tsx` | ヘッダーコンポーネント |
| 3-3 | stats-view.tsx | `apps/stats/src/views/Stats/layout/stats-view.tsx` | ビューのローディング制御 |

**主要処理フロー**:
- **4-16行目（stats-layout.tsx）**: MainLayoutでラップし、px-8のパディングを持つコンテナを提供

#### Step 4: 各画面ビューを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | overview.tsx | `apps/stats/src/views/Stats/Overview/overview.tsx` | 概要画面のKPI/チャート取得ロジック |
| 4-2 | web.tsx | `apps/stats/src/views/Stats/Web/web.tsx` | Webトラフィック画面のフィルタリングロジック |
| 4-3 | growth.tsx | `apps/stats/src/views/Stats/Growth/growth.tsx` | 成長分析画面のソート・タブ切替 |
| 4-4 | newsletters.tsx | `apps/stats/src/views/Stats/Newsletters/newsletters.tsx` | ニュースレター画面の統計取得 |

### プログラム呼び出し階層図

```
App (app.tsx)
    │
    ├─ FrameworkProvider
    │      └─ AppProvider
    │             └─ RouterProvider
    │                    └─ StatsErrorBoundary
    │                           └─ GlobalDataProvider
    │                                  └─ ShadeApp
    │                                         └─ Outlet (React Router)
    │                                                │
    │                                                ├─ Overview
    │                                                │      ├─ useTinybirdQuery (api_kpis)
    │                                                │      ├─ useGrowthStats
    │                                                │      ├─ useLatestPostStats
    │                                                │      └─ useTopPostsViews
    │                                                │
    │                                                ├─ Web
    │                                                │      ├─ useTinybirdQuery (api_kpis)
    │                                                │      ├─ useTinybirdQuery (api_top_sources)
    │                                                │      └─ useTinybirdQuery (api_top_locations)
    │                                                │
    │                                                ├─ Growth
    │                                                │      ├─ useGrowthStats
    │                                                │      └─ useTopPostsStatsWithRange
    │                                                │
    │                                                └─ Newsletters
    │                                                       ├─ useBrowseNewsletters
    │                                                       ├─ useSubscriberCountWithRange
    │                                                       └─ useNewsletterStatsWithRangeSplit
```

### データフロー図

```
[入力]                        [処理]                           [出力]

日付範囲選択 ───────────▶ GlobalDataProvider ─────────▶ range state更新
                               │
                               ▼
                        useTinybirdQuery
                               │
                               ▼
Tinybird API ◀────────── HTTPリクエスト ──────────▶ chartData
(api_kpis等)                   │
                               ▼
                        データ加工・正規化
                               │
                               ▼
                        React コンポーネント
                               │
                               ▼
                        Chart/Table表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| app.tsx | `apps/stats/src/app.tsx` | ソース | アプリケーションルート |
| routes.tsx | `apps/stats/src/routes.tsx` | ソース | ルーティング定義 |
| global-data-provider.tsx | `apps/stats/src/providers/global-data-provider.tsx` | ソース | グローバルデータ管理 |
| stats-layout.tsx | `apps/stats/src/views/Stats/layout/stats-layout.tsx` | ソース | 共通レイアウト |
| stats-header.tsx | `apps/stats/src/views/Stats/layout/stats-header.tsx` | ソース | ヘッダー |
| overview.tsx | `apps/stats/src/views/Stats/Overview/overview.tsx` | ソース | 概要画面 |
| web.tsx | `apps/stats/src/views/Stats/Web/web.tsx` | ソース | Webトラフィック画面 |
| growth.tsx | `apps/stats/src/views/Stats/Growth/growth.tsx` | ソース | 成長分析画面 |
| newsletters.tsx | `apps/stats/src/views/Stats/Newsletters/newsletters.tsx` | ソース | ニュースレター画面 |
| stats-x.hbs | `ghost/admin/app/templates/stats-x.hbs` | テンプレート | Ember側エントリーポイント |
| use-growth-stats.ts | `apps/stats/src/hooks/use-growth-stats.ts` | ソース | 成長統計取得フック |
| use-newsletter-stats-with-range.ts | `apps/stats/src/hooks/use-newsletter-stats-with-range.ts` | ソース | ニュースレター統計取得フック |
