# 機能設計書 38-SEO設定

## 概要

本ドキュメントは、GhostのSEO（検索エンジン最適化）設定機能に関する設計仕様を定義する。この機能により、サイト全体および個別コンテンツのメタタイトル、メタディスクリプション、OGP（Open Graph Protocol）設定を管理できる。

### 本機能の処理概要

SEO設定は、検索エンジンやソーシャルメディアでの表示を最適化するためのメタデータを管理する機能である。サイトレベル（settings）、投稿/ページレベル（posts）、タグレベル（tags）、ユーザーレベル（users）でそれぞれ設定可能。

**業務上の目的・背景**：検索エンジンの検索結果やソーシャルメディアでのシェア時に、適切なタイトル、説明文、画像が表示されるようにする。これにより、クリック率の向上、ブランド認知の強化、トラフィックの増加を実現する。

**機能の利用シーン**：
- サイト全体のSEO設定を行う場合
- 記事ごとに検索結果での表示をカスタマイズする場合
- Twitterカードの表示内容を設定する場合
- Facebook/OGPの表示内容を設定する場合
- タグページのメタ情報を設定する場合

**主要な処理内容**：
1. サイトレベルのSEO設定（meta_title, meta_description, og_*, twitter_*）
2. 投稿/ページレベルのSEO設定
3. タグ/ユーザーレベルのSEO設定
4. ghost_headヘルパーによるメタタグ出力

**関連システム・外部連携**：
- テーマエンジン：ghost_headヘルパーでメタタグ出力
- 検索エンジン：メタタグの読み取り
- ソーシャルメディア：OGP/Twitter Cardsの読み取り

**権限による制御**：サイト設定は管理者以上、コンテンツのSEO設定は著者以上が編集可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 37 | SEOメタデータ設定 | 主画面 | サイト全体のSEOメタデータ設定 |
| 13 | エディタ画面 | 参照画面 | 記事のメタタイトル・ディスクリプション設定 |
| 16 | タグ編集画面 | 参照画面 | タグのメタデータ設定 |

## 機能種別

設定管理 / メタデータ出力

## 入力仕様

### 入力パラメータ（サイトレベル）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| meta_title | String | No | サイトのメタタイトル | 最大300文字 |
| meta_description | String | No | サイトのメタディスクリプション | 最大500文字 |
| og_image | String | No | OGP用画像URL | 最大2000文字 |
| og_title | String | No | OGPタイトル | 最大300文字 |
| og_description | String | No | OGP説明文 | 最大300文字 |
| twitter_image | String | No | Twitterカード用画像URL | 最大2000文字 |
| twitter_title | String | No | Twitterカードタイトル | 最大300文字 |
| twitter_description | String | No | Twitterカード説明文 | 最大300文字 |

### 入力パラメータ（コンテンツレベル）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| meta_title | String | No | コンテンツのメタタイトル | 最大300文字 |
| meta_description | String | No | コンテンツのメタディスクリプション | 最大500文字 |
| og_image | String | No | OGP用画像URL | 最大2000文字 |
| og_title | String | No | OGPタイトル | 最大300文字 |
| og_description | String | No | OGP説明文 | 最大500文字 |
| twitter_image | String | No | Twitterカード用画像URL | 最大2000文字 |
| twitter_title | String | No | Twitterカードタイトル | 最大300文字 |
| twitter_description | String | No | Twitterカード説明文 | 最大500文字 |

### 入力データソース

- 管理画面（Settings > Meta data）
- エディタ画面（Post settings > Meta data）
- タグ編集画面（Tag settings > Meta data）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| meta_title | String | メタタイトル |
| meta_description | String | メタディスクリプション |
| og:title | String | OGPタイトル |
| og:description | String | OGP説明文 |
| og:image | String | OGP画像URL |
| twitter:title | String | Twitterカードタイトル |
| twitter:description | String | Twitterカード説明文 |
| twitter:image | String | Twitterカード画像URL |

### 出力先

- HTMLの`<head>`内（メタタグ）
- settingsテーブル / postsテーブル / tagsテーブル / usersテーブル

## 処理フロー

### 処理シーケンス

```
1. SEO設定の保存
   └─ API経由で設定値を受け取り
   └─ バリデーション（長さチェック）
   └─ 対応テーブルに保存

2. メタタグの出力
   └─ ghost_headヘルパー呼び出し
   └─ 各レベルの設定を取得（コンテンツ > サイト）
   └─ 設定値がある場合はメタタグとして出力
   └─ フォールバック処理（タイトル、説明文等）
```

### フローチャート

```mermaid
flowchart TD
    A[ページ表示] --> B[ghost_head呼び出し]
    B --> C{コンテンツ設定あり?}
    C -->|Yes| D[コンテンツのSEO設定を使用]
    C -->|No| E{サイト設定あり?}
    E -->|Yes| F[サイトのSEO設定を使用]
    E -->|No| G[デフォルト値を使用]
    D --> H[メタタグ出力]
    F --> H
    G --> H
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-38-01 | 優先順位 | コンテンツ設定 > サイト設定 > デフォルト値 | メタタグ出力時 |
| BR-38-02 | 文字数制限 | meta_title最大300文字、meta_description最大500文字 | 設定保存時 |
| BR-38-03 | OGPフォールバック | og_titleがない場合はmeta_titleまたはタイトルを使用 | メタタグ出力時 |
| BR-38-04 | 画像フォールバック | og_imageがない場合はfeature_imageを使用 | メタタグ出力時 |

### 計算ロジック

- メタタイトルのフォールバック: `og_title || meta_title || title`
- メタ説明のフォールバック: `og_description || meta_description || excerpt`

## データベース操作仕様

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| サイトSEO取得 | settings | SELECT | meta_*, og_*, twitter_*設定の取得 |
| サイトSEO更新 | settings | UPDATE | meta_*, og_*, twitter_*設定の更新 |
| 投稿SEO取得/更新 | posts | SELECT/UPDATE | 投稿のSEOフィールド |
| タグSEO取得/更新 | tags | SELECT/UPDATE | タグのSEOフィールド |
| ユーザーSEO取得/更新 | users | SELECT/UPDATE | ユーザーのSEOフィールド |

### テーブル別操作詳細

#### settings

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | value | key IN ('meta_title', 'meta_description', 'og_*', 'twitter_*') | サイトSEO設定 |
| UPDATE | value | ユーザー入力値 | バリデーション後 |

#### posts

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT/UPDATE | meta_title, meta_description, og_*, twitter_* | id = {post_id} | 投稿SEO設定 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ValidationError | 文字数制限超過 | 「Validation failed for meta_title」等のエラー返却 |

### リトライ仕様

リトライは不要。バリデーションエラーの場合は文字数を減らして再試行。

## トランザクション仕様

- 設定更新は単一レコードの更新のため、標準的なトランザクション制御

## パフォーマンス要件

- 設定値はsettingsキャッシュに保存され、高速参照可能
- コンテンツのSEO設定はコンテンツ取得時に一緒に取得

## セキュリティ考慮事項

- メタタグはHTMLエスケープされて出力
- 画像URLは適切に検証

## 備考

- SEO設定が空の場合、タイトルや説明文は自動生成される
- Twitter Cards: summary_large_image形式を使用
- OGP: og:typeはwebsite（サイト）またはarticle（投稿）

---

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

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

### 推奨読解順序

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

まず、SEO関連フィールドのスキーマ定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | default-settings.json | `ghost/core/core/server/data/schema/default-settings/default-settings.json` | **161-232行目**: meta_*, og_*, twitter_*設定のバリデーション定義 |
| 1-2 | schema.js | `ghost/core/core/server/data/schema/schema.js` | **108-116行目**: postsテーブルのSEOカラム定義 |

**読解のコツ**:
- validations.isLength.maxで文字数制限を確認
- postsとusersで同様のSEOフィールドがある

#### Step 2: モデルを理解する

SEOフィールドの保存・取得を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | settings.js | `ghost/core/core/server/models/settings.js` | **166-189行目**: SEO画像URLの変換処理（formatOnWrite, parse） |

**主要処理フロー**:
1. **166行目**: formatOnWriteでog_image, twitter_imageのURL変換
2. **188行目**: parseでURL変換の逆処理

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

```
[設定保存]
Settings/Posts/Tags API edit
    │
    └─ Model.edit()
           │
           ├─ バリデーション (isLength)
           │
           └─ DB保存 (formatOnWrite でURL変換)

[メタタグ出力]
テーマテンプレート
    │
    └─ {{ghost_head}}
           │
           ├─ settingsCache.get() (サイトSEO)
           │
           ├─ コンテンツのSEOフィールド参照
           │
           └─ フォールバック処理
                  │
                  └─ <meta>タグ出力
```

### データフロー図

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

管理画面入力 ───────▶ API edit
                              │
                              ▼
                        バリデーション
                              │
                              ▼
                        URL変換 (formatOnWrite)
                              │
                              ▼
                        DB保存
                              │
                              │
ページ表示 ──────────▶ ghost_head
                              │
                              ▼
                        SEO設定取得
                              │
                              ▼
                        フォールバック処理
                              │
                              ▼
                        メタタグHTML ───▶ <head>内に出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| default-settings.json | `ghost/core/core/server/data/schema/default-settings/default-settings.json` | 設定 | サイトSEO設定定義 |
| schema.js | `ghost/core/core/server/data/schema/schema.js` | 設定 | テーブルスキーマ |
| settings.js | `ghost/core/core/server/models/settings.js` | ソース | Settingsモデル |
| post.js | `ghost/core/core/server/models/post.js` | ソース | Postモデル |
| ghost_head.js | `ghost/core/core/frontend/helpers/ghost_head.js` | ソース | メタタグ出力ヘルパー |
