---
name: blog-analytics
description: >-
ブログのアクセス解析・SEO分析スキル。scripts/analytics/ の取得パイプラインがローカル SQLite に蓄積した
GA4 + Search Console データを read-only で読み、アクセス数と検索順位の向上に直結する週次レポート
(前週比サマリー・リライト候補・タイトル改善候補・あと一歩のキーワード等)をチャットに出力する。
「アクセス解析して」「週次レポート出して」「リライト候補は?」「順位どうなった?」「検索キーワード調べて」
等の依頼時、および記事リライト前の現状把握・リライト後の効果測定に使う。
データ取得ツール自体の修正はこのスキルの担当外。
---
# blog-analytics(アクセス解析・SEO分析)
**目的**: アクセス数と検索順位を上げる。数字の羅列ではなく「次に何をリライト・修正すべきか」が分かる作業指示を出す。
最初に `config.yaml` を Read し、`site.key`(DB の `site` 列の値)と `analytics.*` を確認する。
## 鉄則
- **DB は必ず read-only 接続**: `sqlite3.connect("file:{analytics.database}?mode=ro", uri=True)`。書き込み・スキーマ変更はしない
- **数値はすべて SQL で実測**する。記憶や推測で書かない。データが無ければ「データ不足」と明記する
- 結果はチャットに出力する(求められたら `{paths.reports}` に MD 保存も可)。週の総クリックが `analytics.min_weekly_clicks_for_rates` 未満なら「サンプル不足のため変動率は参考値」と冒頭に注記する
- 分析から記事の新規執筆・大幅加筆に進むなら、公開前に `article-review` を通す
- **取得ツール側の修正はしない**。不具合や欲しいデータは、運営者に「scripts/analytics/ 側で対応が必要」と伝える
## データソース
DB は `{analytics.database}`。テーブル定義は `scripts/analytics/db_schema.sql` が正(下表は主なもの。存在しないテーブルに依存するセクションは「データなし」として省く)。全テーブルに `site` 列があり、特記が無ければ日次。
| テーブル | 内容 |
|---|---|
| `page_metrics` | 記事別 PV/ユーザー/エンゲージ率/直帰率。**`snapshot_date` ごとの7日ローリング**(日次ではない) |
| `channel_metrics` / `landing_metrics` / `user_type_metrics` / `device_geo_metrics` / `hourly_metrics` | 流入チャネル/ランディング/新規・再訪/デバイス×地域/時間帯 |
| `event_metrics` | イベント・キーイベント |
| `affiliate_click_metrics` | 広告リンクのクリック(記事×リンク先ホスト)。`config.yaml` の `analytics.sites` でサイトに `ga4_affiliate_event` を設定したときだけ入る |
| `gsc_query_metrics` / `gsc_page_metrics` / `gsc_page_query_metrics` | 検索クエリ別/ページ別/**ページ×クエリ**(記事ごとの流入キーワード) |
| `inspect_metrics` | インデックス状況(`coverage_state` 等)。週次 |
| `batch_runs` | バッチ実行ログ |
### 必ず守るデータ仕様
1. **鮮度**: GA4 は昨日まで(直近48時間は数値が動く)。Search Console は約3日遅れ。週次比較は `end = GSC の実際の MAX(date)`・`start = end-6`・前週は同じ幅で1週ずらす(今日の日付を基準に固定計算しない)
2. 分析前に `batch_runs` の直近の `run_date` / `status` を確認し、failed や欠落があれば冒頭に注記する
3. **URL 正規化**: `page_path` は正規化済みで GA4 と GSC を JOIN できる前提。同じ記事が複数のパスに分かれていたら、集計時に名寄せする(例: `/index.html` を `/` に寄せる):
```sql
CASE WHEN page_path='/index.html' THEN '/'
WHEN page_path LIKE '%/index.html' THEN substr(page_path, 1, length(page_path)-11)
ELSE page_path END
```
4. `page_metrics` は最新の `snapshot_date` を使う(`WHERE snapshot_date=(SELECT MAX(snapshot_date) ...)`)。上位N件しか保存されないので「載っていない=アクセス無し」と結論しない
5. Cookie 同意を Opt-in にしているサイトでは、GA4 は実態より少なく出る。流入の規模は GSC を主指標にし、GA4 は同意した読者の行動の質を見る用途に限る
6. 新しいサイトで `page_metrics` が0行でも不具合とは限らない(7日窓にセッションが無いだけ)。変動率は出さず、実数とサンプル不足の注記で報告する
## 標準レポート(週次・「アクセス解析して」の既定形)
各セクションの末尾に**推奨アクションを1行**付ける。
### 0. 下落の早期警告(任意)
`scripts/analytics/yellow_lamp.py` がある場合だけ、冒頭で `python -X utf8 scripts/analytics/yellow_lamp.py` を実行して結果を1行で示す(判定ロジックを SQL で手書きし直さない)。点灯していたら最上部に警告を置き、「即対応ではなく次回の定期見直しの議題に上げる」調子で伝える。データ不足なら「判定不能」。ファイルが無ければこの節は省く。
### 1. サマリー(前週比)【最優先】
GSC のクリック・表示回数と GA4 セッションの前週比。**±20%を超える変動は冒頭で強調**する(急落→検索エンジンのアップデート時期と照合/急増→伸びた記事を特定)。
### 2. 今週のリライト候補(主役)
`gsc_page_query_metrics` で **平均順位が `analytics.rewrite_band` の範囲**のクエリ×ページを表示回数の多い順に TOP10(あと一押しで上位)。続けて **`analytics.treasure_band` の範囲×表示の多い順** TOP10=あと一歩のキーワード。各行: クエリ/ページ/順位/表示/CTR。
### 3. タイトル改善候補(高表示×低CTR)
週の表示回数が100以上のクエリで、CTR が順位帯の目安(1〜3位 10%/4〜6位 4%/7〜10位 2%)を下回るものを、乖離の大きい順に TOP5。推奨: 数字・年号・具体語の追加。
### 4. 新記事・伸びている記事
検索表示が新しく出たページ(過去0→今週>0)と伸びているページ。公開から14日以上たって表示0なら「インデックス確認」と注記する。
### 5. PV×検索のギャップ(GA4×GSC JOIN)
PV が多く検索クリックが少ない=SEO の改善余地/検索表示が多く PV が少ない=CTR・タイトルの問題。
### 6. 新規出現クエリ(ネタ帳)
今週初めて表示されたクエリの一覧→新記事・追記の企画材料。
### 7. インデックス状況(`inspect_metrics` があるときだけ)
最新の `inspected_date` で `coverage_state LIKE '%not indexed%'` の**実記事**を一覧にする(タグ・フィード・アーカイブ等の記事でない URL は除く)。`coverage_state` は英語固定。前回と比べて**登録に変わった/新しく外れた**記事を差分で示す。本文が薄い記事が未登録なら加筆を勧める。
## オンデマンド分析
- 記事単体の深掘り: `gsc_page_query_metrics` で流入キーワードの全量と順位推移
- リライト効果測定: リライト日を聞き、前後で順位・CTR・クリックを比較する(最低2〜4週あける)
- 時系列・チャネル・曜日×時間帯・デバイス/地域: 該当テーブルを SQL で集計する。E-E-A-T・YMYL の観点の提案を添える
## レポート末尾(必須)
**TOP3 推奨アクション**(影響度×手間で優先度を付ける)+測定可能な目標(例: 順位24位→10位以内、CTR 1.4%→4%)。
MIT ライセンスで配布しています。