bbizinets.life
n8nとGA4でリライト優先度を自動判定した実践ログ|Claude APIまでの流れ
実践ログ

n8nとGA4でリライト優先度を自動判定した実践ログ|Claude APIまでの流れ

# n8nとGA4でリライト優先度を自動判定した実践ログ|Claude APIまでの流れ

記事が増えるほど、どの記事から直すべきか分からなくなります。n8nでGA4データを使ってリライト優先度を自動判定するには、GA4指標をJSON化し、Codeノードで直帰率・スクロール率・CTA率をもとにintro/body/ctaへ分類する流れを作ります。私はGA4データをPythonで取得し、n8nでリライト優先度を自動判定する仕組みを作りました。この記事では、performance_cache.jsonからClaude APIリライトまでの流れを整理します。

手動リライトでは限界が来る

どの記事から手をつければいいか、毎回迷っていませんか?

私がそうでした。bizinets.bizの記事数が100本を超えたとき、「どれを直すべきか」の判断基準がなく、何となく「アクセスが少ない記事」や「古い記事」から手をつけていました。ただ、それでは改善のサイクルが回っている感覚がありませんでした。

記事を1本直すのに30〜60分かかります。判断基準がなければ、その時間が正しく使われているかどうかも分かりません。感覚でリライトを繰り返しても、サイト全体の数字が動く気配がなく、途中で手が止まってしまいました。

問題は「リライトする気力がないこと」ではなく、「どれを直せば効果が出るかの判断基準がないこと」でした。そこで、GA4データをもとにリライト優先度を自動で判定する仕組みを設計することにしました。

確認ポイント:

  • リライト対象を毎回感覚で決めている → GA4指標ベースの判定ロジックを先に設計する
  • 改善しても数字が動かない → 修正タイプ(intro/body/cta)が正しく特定できているか確認する

GA4データをperformance_cache.jsonに保存する

GA4のデータをn8nで使うには、まずどこかに保存する必要があります。どうやってGA4のデータをn8nに渡せばよいのでしょうか?

私は fetch_metrics_json.py というPythonスクリプトをVPS(/root/metrics/)に置いて、GA4 APIからデータを取得しています。このスクリプトが出力する performance_cache.json が、n8nのリライト判定の材料になります。

スクリプトが取得する指標は以下のとおりです。

# GA4から取得する主要指標
metrics=[
    Metric(name="sessions"),
    Metric(name="totalUsers"),
    Metric(name="averageSessionDuration"),
    Metric(name="engagedSessions"),
    Metric(name="bounceRate"),
]

# GTMカスタムイベント(スクロール率)
# scroll_50 / scroll_75 / scroll_90 を個別に取得
# cta_click(cta_idパラメータで top / article_bottom を区別)
# view_0pdf(LP到達)
# pdf_register_complete(登録完了)

出力される performance_cache.json の構造は以下のようになっています。

{
  "generated_at": "2026-05-15",
  "site": "bizinets.biz",
  "funnel_summary": {
    "cta_click_total": 142,
    "lp_sessions": 98,
    "pdf_registers": 31,
    "lp_cvr": 31.6
  },
  "articles": [
    {
      "slug": "rewrite-decision-criteria",
      "ga4_sessions": 61,
      "ga4_bounce_rate": 42.3,
      "ga4_scroll_50": 68.0,
      "ga4_scroll_75": 51.0,
      "ga4_scroll_90": 33.0,
      "ga4_cta_click_rate": 11.5
    }
  ]
}

このJSONがあれば、n8nのCodeノードで記事ごとのリライト優先度を機械的に判定できます。

確認ポイント:

  • fetch_metrics_json.py を実行してもエラーになる → GA4 APIのサービスアカウントキーが /root/metrics/gsc_ga4_key.json に置かれているか確認する
  • ga4_scroll_50 が全記事 null になっている → GTMのスクロール計測が未設定か、GTM公開から3〜5日待つ必要がある
ここまでで「GA4のどのデータをどう取得するか」の構造は見えてきました。
ただし、このままだと取得したデータをどの記事のリライトに使うかは判断できません。
なぜなら、「どの数値がどの修正タイプに対応するか」の判断軸がまだ整理されていないからです。

→ リライトすべき記事の見分け方を読む

n8nでperformance_cache.jsonを読み込む

JSONファイルをn8nで使うには、どうやって読み込めばよいのでしょうか?

私はn8nの Execute Command ノードを使って、VPS上のファイルを直接読み込んでいます。

ノード名:performance_cache取得
タイプ:Execute Command
コマンド:cat /root/metrics/performance_cache.json

このノードの出力は stdout フィールドに文字列として入ってきます。次のCodeノードでJSONとしてパースします。

// ノード名:performance_cacheパース
const raw = $input.first().json.stdout;
const data = JSON.parse(raw);
return [{ json: data }];

パースが完了すると、data.articles に全記事の指標が配列で入った状態になります。この時点で data.articles[0].ga4_scroll_50 のようにアクセスできます。

フロー内での配置は以下のとおりです。

Cron Trigger(毎朝6時)
  ↓
performance_cache取得(Execute Command)
  ↓
performance_cacheパース(Code)
  ↓
キーワードスコアリング(Code)← 新規記事とリライト候補を同時に判定
  ↓
リライト候補あり?(IF)
  ↓ true
リライト候補展開(Code)← 配列を1件ずつに展開
  ↓
リライトループ(SplitInBatches)

確認ポイント:

  • Execute Command の出力が空になっている → VPS上に performance_cache.json が存在するか確認する(cat /root/metrics/performance_cache.json で手動確認)
  • JSON.parse でエラーになる → performance_cache.json の内容が正常なJSONか確認する

n8nでGA4データからリライト優先度を自動判定する

データが読み込めたとして、どのロジックでリライト対象と修正タイプを決めればよいのでしょうか?

私はキーワードスコアリングのCodeノード内に、GA4指標ベースのリライト優先度判定ロジックを書いています。

※以下は私の環境で使っている判定ロジックの抜粋です。ノード名やJSON構造は環境に合わせて調整してください。

const rewrite_candidates = (perfData.articles ?? [])
  .filter(a => a.ga4_sessions !== null && a.ga4_sessions >= 10)
  .map(article => {
    const b   = article.ga4_bounce_rate     ?? 999;
    const s50 = article.ga4_scroll_50       ?? 0;
    const s90 = article.ga4_scroll_90       ?? 0;
    const cta = article.ga4_cta_click_rate  ?? 0;

    let priority     = 5;
    let rewrite_type = 'none';
    let rewrite_axis = '対応不要';

    if (b > 70 && s50 < 40) {
      priority     = 1;
      rewrite_type = 'intro';
      rewrite_axis = `直帰率${b}%・scroll_50が${s50}%。冒頭を再設計する。`;
    } else if (s90 > 20 && cta < 5) {
      priority     = 2;
      rewrite_type = 'cta';
      rewrite_axis = `scroll_90が${s90}%まで読まれているがCTA率${cta}%。CTA直前を見直す。`;
    } else if (s50 > 60 && s90 < 20) {
      priority     = 3;
      rewrite_type = 'body';
      rewrite_axis = `scroll_50は${s50}%だがscroll_90が${s90}%。中盤H2を強化する。`;
    }

    return { ...article, priority, rewrite_type, rewrite_axis };
  })
  .filter(a => a.rewrite_type !== 'none')
  .sort((a, b) => a.priority - b.priority);

判定ロジックは3タイプに分かれています。

intro(冒頭問題): 直帰率70%超かつscroll_50が40%未満 → 記事冒頭で離脱している。H1直下の導入を再設計する。

cta(末尾問題): scroll_90が20%超かつCTA率5%未満 → 最後まで読まれているのにCTAを踏んでいない。CTA直前の誘導文を見直す。

body(中盤問題): scroll_50が60%超かつscroll_90が20%未満 → 中盤で離脱している。H2構成を再構成する。

この判定により rewrite_type と rewrite_axis(修正軸の説明文)が各記事に付与されます。これが次のリライトプロセスへの引き継ぎ情報になります。

確認ポイント:

  • rewrite_candidates が空配列になっている → ga4_sessions >= 10 の条件を満たす記事がない可能性。GTMデータが溜まる前は正常な動作
  • 全記事が intro に分類される → 直帰率・スクロール率の値が正しく取れているか performance_cache.json を直接確認する

Claude APIで本文リライトへつなげる

リライト優先度が判定できたら、どうやってClaudeに渡して実際にリライトするのでしょうか?

rewrite_type と rewrite_axis をリライトデータ統合ノードで既存のarticle.mdと結合し、構成案生成→本文生成の順でClaudeに渡します。

リライト構成案生成(OpenAI GPT-4o)のUSERプロンプトには以下を含めています。

## リライトタイプ
{{ $json.rewrite_type }}

## 修正軸(判定根拠)
{{ $json.rewrite_axis }}

## GA4行動指標
- 直帰率:{{ $json.ga4_bounce_rate }}%
- scroll_50:{{ $json.ga4_scroll_50 }}%
- scroll_75:{{ $json.ga4_scroll_75 }}%
- scroll_90:{{ $json.ga4_scroll_90 }}%
- CTAクリック率:{{ $json.ga4_cta_click_rate }}%

構成案が出たら、次のClaude APIノード(リライト本文生成)のUSERプロンプトにもリライトタイプと修正軸を渡します。

## リライトタイプ
{{ $json.rewrite_type }}

## 修正軸
{{ $json.rewrite_axis }}

## リライト構成案
修正セクション:{{ $json.rewrite_sections.join('\n') }}
修正方針:{{ $json.rewrite_policy }}

Claude APIはこの情報をもとに、指定されたセクションのみを書き直した article.md の全文を返します。リライト前後の差分をSlackに通知してから、Google DriveのCSVに書き込み・WordPressへ投稿するという流れです。

全体のフローをまとめると以下のようになります。

performance_cache.json(GA4データ)
  ↓
キーワードスコアリング(intro/body/ctaに判定)
  ↓
リライトループ(1件ずつ処理)
  ↓
article.md取得 + meta.json取得
  ↓
リライトデータ統合(rewrite_type + article_md を結合)
  ↓
リライト構成案生成(OpenAI)
  ↓
Slack通知(草稿確認・承認待ち)
  ↓
リライト本文生成(Claude API)
  ↓
article.md書き込み → meta.json書き込み → WordPress投稿

確認ポイント:

  • Claude APIがリライトタイプを無視して全文を書き直す → SYSTEMプロンプトに「指定セクションのみ修正」の絶対制約を明示する
  • Slack通知が来ないままリライトが実行される → 承認待ちのWebhookトリガーが正しく設定されているか確認する

この後どうなったか

n8nのリライトフローを設計・実装したのは2026年5月です。現時点ではGTMデータが溜まり始めたばかりで、GA4の ga4_scroll_50 や ga4_cta_click_rate に意味のある数値が入るまでもう少し時間がかかります。

rewrite_candidates が現在空配列になっているのは正常な状態で、セッション数10件以上・スクロール率データあり、という条件を満たす記事が出てくれば自動的に動き始める設計になっています。

3〜4週間後にperformance_cache.jsonを確認して、実際にリライトが自動判定されたかどうかを検証する予定です。その記録は別の記事でまとめます。

まとめ

GA4データをn8nでリライトに使う仕組みの全体構成は以下のとおりです。

  1. fetch_metrics_json.py でGA4指標(直帰率・スクロール率・CTA率)を取得 → performance_cache.json に保存
  2. n8nの Execute Command でJSONをVPSから読み込み → Codeノードでパース
  3. キーワードスコアリングノードでintro/body/ctaに自動判定
  4. リライトデータ統合 → OpenAIで構成案生成 → Claude APIで本文リライト
  5. Slack承認 → WordPress投稿

設計が整っていれば、「どれを直すか」の判断をn8nに任せて、自分はリライト結果の確認だけに集中できます。ただし、この仕組みが正しく動くのはGA4データが溜まってからです。まず計測設定を整えることが先決です。

今日できる一歩: performance_cache.json をテキストエディタで開いて、ga4_scroll_50 に数値が入っている記事があるか確認してください。数値が入っていれば、リライト優先度の自動判定はすぐ動かせる状態です。

この仕組みは、単なる自動化ではなく「どの記事を直すべきか」を判断するための設計です。その判断軸そのものは、bizinets.bizで整理しています。

ここまでの内容で、GA4データをn8nでリライト判定に使う仕組みの流れは整理できたと思います。
ただし、このままだとなぜその数値でその修正タイプになるかの根拠は判断できません。
なぜなら、直帰率・スクロール率・CTA率の閾値をどう設定するかの判断軸が、まだ整理されていないからです。

→ リライトすべき記事の見分け方を読む

bizinets.biz

記事を読んで「もっと知りたい」と思ったあなたへ

bizinets.biz では、ビジネスの仕組みづくりを体系的に学べるコンテンツを用意しています。まずは一度、覗いてみてください。

bizinets.biz へ行く →

関連記事