n8nのCodeノードでSEOスコアリングロジックを組む方法【リライト優先度を数値化する】

柴田

サチコ(Googleサーチコンソール)のデータ、引っ張ってくるだけ引っ張ってきたけど…「で?どうする?」状態ですぅ…

AI

…まずはリライトの優先順位をつけるために、データのスコアリング(どれが優先度が高いか)をシマショウカ

柴田

やっぱりデータを準備するだけじゃダメだね。データをどう活かすか、を考えねば…

AI

それ、前回ワタシが言ったヨ?

このブログで進めているGSC自動解析ワークフローの第2回です。

前回の記事(データ取得編)では、Google Search Console APIに接続してデータを引っ張ってくる設定を解説しました。

今回はその次のステップ、n8nのCodeノードを使って、大量のデータからリライト優先度を自動でスコアリングするロジックの実装を解説します。

【この記事でわかること】

  • n8nのCodeノードでデータを処理するための基本設定
  • 実際に動かすSEOスコアリング用のJavaScriptコード
  • Codeノード特有のハマりやすいポイントと解決策
目次

事前準備

必要なもの

  • 前回作成した、GSCデータが取得できるn8nのワークフロー
  • スコアリングの基準となる簡単な条件のイメージ(例:11位〜20位の惜しいキーワードを狙う、など)

Step1:n8nにCodeノードを配置して設定する

STEP
Codeノードを追加する

前回作った「HTTP Requestノード」の後ろに、新しく「Codeノード」を追加して矢印を繋ぎます。

node1
STEP
ノードの実行モードを変更する

Codeノードの設定画面を開き、右上の「Mode」を変更します。ここを間違えるとデータがバラバラに処理されてしまうので注意してください。

項目設定値
ModeRun Once for All Items
LanguageJavaScript
node2

⚠️ ハマりポイント①

Modeをデフォルトの「Run Once for Each Item」のままにしておくと、データ1行ごとにコードが実行されてしまい、全体の並び替え(ソート)や一括フィルタリングが全く動きません。必ず Run Once for All Items にしてください。

Step2:スコアリングロジックのコードを書く

柴田

ここがこのノード最大のポイントです!以下の採点基準で得点をつけて、リライトすべき記事をあぶり出しましょう!

スコアリングの方針

今回は「リライトしたら成果が出やすい記事」を見つけることが目的なので、こういう優先順位で設計します。

最優先(スコア高め):コスパが高い記事

  • 順位11〜20位:あと少しで1ページ目に入れる
  • 表示回数が多いのにCTRが低い:タイトル改善だけで伸びる可能性がある

次点(スコア中程度):伸びしろがある記事

  • 順位21〜30位:改善余地あり
  • 順位4〜10位でCTRが低い:上位表示されているのに読まれていない

対象外:リライトしても効果が薄い記事

  • 順位1〜3位:すでに十分
  • 順位31位以下:改善コストが高すぎる
  • 表示回数が極端に少ない:そもそも検索需要がない

コードを貼り付ける

Codeノードの入力エリアに、以下のJavaScriptコードをコピーして貼り付けます。

const rows = $input.first().json.rows || [];

const urlMap = {};

for (const row of rows) {
  const url = row.keys[0];
  const keyword = row.keys[1];

  if (!urlMap[url]) {
    urlMap[url] = {
      url,
      keywords: [],
      totalClicks: 0,
      totalImpressions: 0,
      positionSum: 0,
      rowCount: 0
    };
  }

  urlMap[url].keywords.push(keyword);
  urlMap[url].totalClicks += row.clicks;
  urlMap[url].totalImpressions += row.impressions;
  urlMap[url].positionSum += row.position;
  urlMap[url].rowCount += 1;
}

const results = [];

for (const url in urlMap) {
  const d = urlMap[url];
  const avgPosition = d.positionSum / d.rowCount;
  const avgCtr = d.totalImpressions > 0 ? d.totalClicks / d.totalImpressions : 0;

  if (d.totalImpressions < 50) continue;

  let score = 0;
  const reasons = [];

  if (avgPosition >= 11 && avgPosition <= 20) {
    score += 3;
    reasons.push('順位11〜20位');
  } else if (avgPosition >= 21 && avgPosition <= 30) {
    score += 2;
    reasons.push('順位21〜30位');
  } else if (avgPosition >= 4 && avgPosition <= 10) {
    score += 1;
    reasons.push('順位4〜10位');
  } else {
    continue;
  }

  const expectedCtr = avgPosition <= 3 ? 0.10
    : avgPosition <= 10 ? 0.02
    : avgPosition <= 20 ? 0.005
    : 0.002;

  if (avgCtr < expectedCtr * 0.5) {
    score += 2;
    reasons.push('CTRが低い');
  } else if (avgCtr < expectedCtr * 0.8) {
    score += 1;
    reasons.push('CTRがやや低め');
  }

  if (d.totalImpressions >= 1000) {
    score += 2;
    reasons.push('表示回数1000回以上');
  } else if (d.totalImpressions >= 300) {
    score += 1;
    reasons.push('表示回数300回以上');
  }

  results.push({
    url: d.url,
    topKeyword: d.keywords[0],
    totalClicks: d.totalClicks,
    totalImpressions: d.totalImpressions,
    avgCtr: Math.round(avgCtr * 10000) / 100 + '%',
    avgPosition: Math.round(avgPosition * 10) / 10,
    score,
    reasons: reasons.join(' / '),
    keywordCount: d.keywords.length
  });
}

results.sort((a, b) => b.score - a.score);
return results.slice(0, 10).map(item => ({ json: item }));
コードの概要

ステップ1:データの集計(urlMap)

GSCから返ってくるデータは「記事URL×キーワード」の組み合わせで1行ずつになっています。同じ記事が複数のキーワードで登場するので、まずURL単位でクリック数・表示回数・順位を合算します。

ステップ2:スコアリング

URL単位に集計したデータに対して3つの観点でスコアを付けます。

順位帯(11〜20位が最高点の+3)、CTRの低さ(順位の割にクリックされていない記事に+1〜2)、表示回数の多さ(検索需要が大きい記事に+1〜2)です。

表示回数が50回未満の記事と、順位1〜3位・31位以下の記事は最初から対象外にしています。コスパが低いからです。

ステップ3:並べ替えと出力

スコアが高い順に並べ替えて上位10記事だけを返します。各記事にはURL・主要キーワード・クリック数・表示回数・CTR・平均順位・スコア・スコアの理由が含まれます。

最終的に「今週リライトすべき記事トップ10」がスプシに出力される、というイメージです。

Step3:スコアリングされたデータの確認

1. ノードの実行と結果確認

ノードの「Execute Node」をクリックして実行します。右側の出力画面(OUTPUT)に、計算されたスコア(score)が付与され、点数が高い順に綺麗に並んだデータが返ってくれば成功です。

[
  {
    "url": "https://math-journal.bear-fruit.online/geometricsequences/",
    "topKeyword": "等比数列",
    "totalClicks": 5,
    "totalImpressions": 6126,
    "avgCtr": "0.08%",
    "avgPosition": 11.6,
    "score": 7,
    "reasons": "順位11〜20位 / CTRが低い / 表示回数1000回以上",
    "keywordCount": 2
  },
  {
    "url": "https://math-journal.bear-fruit.online/countingcircularpermutations/",
    "topKeyword": "円順列",
    "totalClicks": 52,
    "totalImpressions": 14340,
    "avgCtr": "0.36%",
    "avgPosition": 7.4,
    "score": 5,
    "reasons": "順位4〜10位 / CTRが低い / 表示回数1000回以上",
    "keywordCount": 6
  },
  …
result
柴田

なるほど…自分のブログのマズイところが一目でわかるね…

実際に詰まったこと

今回はあまり詰まるところはないかな…と思います。

表示回数が1000回以上、とかは私のブログの規模感なので、ご自身のブログで「表示回数が多いな」と思う数字で設定してください。

次のステップ

データに点数をつけて並び替えたら、次回はいよいよAIに自動でリライト案を考えてもらいます!

完成版ワークフローは公式ラインで配布します

今回全部を統合した完成版ワークフローを公式ラインで配布します。

公式LINEに登録して、「GSC自動解析」とメッセージをください。ワークフローのJSONファイルへのリンクを送信します!

柴田

完全無料配布です!このブログ記事を参考にセットアップしてみてください!

【公式ラインQRコード】

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次