Core Media Lab記事一覧
開発・インフラ

【実践】GASで集めたSearch ConsoleデータとDify APIを連携!リライト改善案をスプレッドシートへ自動生成する手順

【実践】GASで集めたSearch ConsoleデータとDify APIを連携!リライト改善案をスプレッドシートへ自動生成する手順

ブログやWebメディアの検索流入を伸ばすうえで最も費用対効果が高い施策は、「現在8位〜20位(検索結果の2ページ目)につけている惜しい記事を見つけ出し、検索クエリの意図に合わせてタイトルや見出しをリライトすること」です。

前回の記事では、Google Apps Script(GAS)を使ってSearch ConsoleとGA4のデータを毎週自動でスプレッドシートへ集約し、条件に合致する行へ自動で「🔥最優先リライト」「✏️タイトル改善」とフラグを立てる仕組みを構築しました[span_4](start_span)[span_4](end_span)[span_5](start_span)[span_5](end_span)。

しかし、リライト候補のクエリがシート上に抽出されたあと、「具体的にタイトルをどう書き換えればクリック率(CTR)が上がるのか?」「どのH2・H3見出しを追記すれば1ページ目に浮上するのか?」を1記事ずつ人間が頭を捻って考えるのは、依然として大きな時間的コストがかかります。

そこで本記事では、前回作成したSEOデータ集約シートに「Dify(ディファイ)のワークフローAPI」を直結させ、リライト対象と判定された行の隣に『AIによる具体的な改善タイトル案と追加見出し案』を自動出力する完全手順を、コピペで動くGASコードとプロンプト付きで解説します。

なぜSEOリライトに「GAS(GSCデータ)× Dify API」の連携が最強なのか?

スプレッドシート上のデータをAIで処理する方法としては、GASからOpenAI(ChatGPT)のAPIを直接叩く方法や、スプレッドシート用のAI関数アドオンを使う方法もあります。しかし、実務のSEOリライト運用においては「GAS × 自前Dify API」の組み合わせが圧倒的に優れています。

比較項目 手動でChatGPT画面へコピペ GAS × OpenAI API直叩き GAS × DifyワークフローAPI
作業の手間 毎回URLやクエリ・順位を貼る手間が発生 シート上で自動化可能 週次トリガーで完全自動化可能
プロンプトとモデルの調整 チャット画面で毎回指示 GASコードの書き換えが必要で管理が煩雑 Difyのブラウザ画面上でノーコード調整可能
既存記事やナレッジの参照 記事本文を毎回手動で貼り付ける必要あり スクレイピングやRAGの実装が困難 HTTPリクエストやRAGで既存記事を自動参照できる

1. 「🔥最優先リライト」の行だけをピンポイントでAIに処理させられる

Search Consoleから取得した生データ(最大1,000行など)のすべてに対してAIを実行すると、APIの従量課金コストが無駄に膨らむうえ、GASの「実行時間6分制限」に引っかかってしまいます[span_6](start_span)[span_6](end_span)[span_7](start_span)[span_7](end_span)。

GAS側で「H列の判定フラグが『🔥最優先リライト』または『✏️タイトル改善』であり、かつまだAI提案が生成されていない行だけ」をフィルタリングしてDifyに送ることで、1回あたり数円〜十数円の最小コストで最も効果の高い改善案だけを手に入れることができます。

2. Dify側で「現在の記事内容」や「メディアの執筆ルール」を加味した提案が作れる

Difyのワークフロー機能を使えば、GASから渡された「記事URL」「検索クエリ」「平均順位」「CTR」を受け取るだけでなく、Dify内のノードで対象URLのWebページ情報を取得したり、自サイトの過去記事一覧(ナレッジベース)を参照したりしたうえで、「今の記事に足りない見出しは何か?」を的確に指摘させることが可能です。

💡 前提となる「Search Console × GA4自動集約シート」の構築手順はこちら:
本記事は、以下の記事で作成したスプレッドシート(シート名:SEO_RawData)をベースに機能を拡張していきます。まだ作成していない方は、先にこちらを10分でセットアップしてください[span_8](start_span)[span_8](end_span)[span_9](start_span)[span_9](end_span)。
・【コピペで動く】GASでSearch ConsoleとGA4をスプレッドシートに自動連携!リライト候補を自動抽出する手順

【Dify側の準備】検索クエリと順位・CTRから「改善タイトル&追加H2案」を作るワークフロー設計

まずはDifyの管理画面を開き、GASからSEOデータを受け取ってリライト改善案を返す「ワークフロー」を作成します。

💡 Difyのセルフホスト環境や基本的なGAS連携がまだの方はこちら:
・【完全ガイド】DifyをVPS(Docker)でセルフホスト構築する手順!無料枠の制限を突破し24時間AI自動化
・【コピペで動く】DifyのAPIをGASから叩いてスプレッドシート上でAI自動化する完全手順

STEP 1:Difyで新規「ワークフロー」を作成し、5つの入力変数を定義する

  1. Difyのスタジオ画面から「最初から作成」➔「ワークフロー(Workflow)」を選択し、アプリ名(例:SEOリライト改善案ジェネレーター)を入力して作成します。
  2. キャンバス上の「開始(Start)」ノードをクリックし、スプレッドシートから受け取る以下の5つの入力フィールド(すべて「短文:TextInput」または「段落:Paragraph」)を追加します。
変数名(Variable Name) フィールドタイプ GAS側から渡すデータ内容
page_url 短文(TextInput) 対象の記事URL(A列の値)
query 短文(TextInput) 実際に検索されたクエリ(B列の値)
ctr 短文(TextInput) 現在のCTR・クリック率(E列の値)
position 短文(TextInput) 現在の平均掲載順位(F列の値)
flag 短文(TextInput) 判定フラグ(H列の値:最優先リライト/タイトル改善)

STEP 2:LLMノードを接続し、SEOリライト専用プロンプトを設定する

「開始」ノードの次に「LLM」ノードを接続します。モデルには日本語の構成力と分析力が高い Claude 3.5 Sonnet、GPT-4o、または高速・低コストな Gemini 2.5 Flash / Pro などを選択し、SYSTEMプロンプト欄に以下のテンプレートを貼り付けます(変数部分は / キーを押して開始ノードの各変数を選択してください)。

あなたは専門的な技術WebメディアのSEO編集長です。
Google Search Consoleの実測データに基づき、対象記事の検索順位引き上げおよびCTR(クリック率)改善のための具体的なリライト案を作成してください。

【対象記事データ】
・記事URL(スラッグ):{{#start.page_url#}}
・対策すべき検索クエリ:{{#start.query#}}
・現在の平均掲載順位:{{#start.position#}} 位
・現在のCTR:{{#start.ctr#}}
・判定課題フラグ:{{#start.flag#}}

【出力フォーマット(スプレッドシートの1セル内で読みやすいよう簡潔に出力すること)】
■ 検索意図のギャップ仮説(1〜2行)
・このクエリで検索する読者が本当に求めている解決策の要点

■ クリック率(CTR)を高める新タイトル案(2案・各32〜45文字程度)
1. 
2. 

■ 順位を1ページ目(トップ5)へ押し上げる追加・強化H2/H3見出し案
・H2案:
  - H3案(具体的に記載すべき手順・コード・注意点):

STEP 3:終了ノードを設定して「公開」し、APIキーを取得する

  1. 「LLM」ノードの後ろに「終了(End)」ノードを繋ぎ、出力変数名を rewrite_plan として、LLMノードの出力テキスト(text)を割り当てます。
  2. 画面右上の「公開する」➔「更新」をクリックしてワークフローを確定させます。
  3. 左メニューの「APIアクセス」を開き、右上の「APIキー」から新しいシークレットキー(app-xxxxxxxx...)を発行してコピーしておきます。

これでDify側の受け皿が完成しました。次のセクションでは、スプレッドシートに列を追加し、GASからこのDifyワークフローを自動呼び出しするコードを実装します。

【スプレッドシート&GAS実装】「🔥最優先リライト」の行だけをDifyへ送る自動生成スクリプト

Dify側のワークフローが公開できたら、前回作成したGoogleスプレッドシート(SEO_RawData シート)に2つだけ列を追加し、GASの連携コードを組み込みます。

STEP 4:SEO_RawDataシートのI列・J列に見出しを追加する

SEO_RawData シートの1行目(A1〜H1)の右隣にある I1セル と J1セル に、以下の見出しを追加します。

A列〜G列 H列(既存) I列(新規追加) J列(新規追加)
記事URL / クエリ / 順位 等 判定フラグ AIリライト改善案 AI処理ステータス

STEP 5:GASの「スクリプトプロパティ」にDifyのURLとAPIキーを登録する

APIキーをコード内に直接書くと管理上危険なため、GASの「スクリプトプロパティ」に安全に保存します。

  1. スプレッドシートの「拡張機能」➔「Apps Script」を開きます。
  2. 左メニュー下部の「歯車アイコン(プロジェクトの設定)」をクリックします。
  3. 画面一番下の「スクリプト プロパティ」➔「スクリプト プロパティを追加」をクリックし、以下の2つを登録して保存します。
  • プロパティ1: DIFY_API_URL
    値: http://あなたのVPSのIPアドレス/v1/workflows/run (※独自ドメイン・SSL化済みの場合は https://あなたのドメイン/v1/workflows/run)
  • プロパティ2: DIFY_API_KEY
    値: STEP 3で発行したシークレットキー(app-xxxxxxxx...)

STEP 6:Dify連携用のGASコードを追加して実行する

Apps Scriptの「エディタ(<> アイコン)」に戻り、前回作成した コード.gs の一番下に以下のコードを追記(または新規ファイル dify_seo.gs を作成して貼り付け)して保存します。

/**
 * Core Media Lab: SEO_RawDataのリライト候補行をDify APIへ送信して改善案を自動生成するスクリプト
 */

const DIFY_SEO_CONFIG = {
  // 対象シート名(前回作成したGSC×GA4集約シート)
  SHEET_NAME: 'SEO_RawData',
  
  // 1回の実行でAI生成する最大件数(APIコスト保護&GASの6分制限対策)
  MAX_ITEMS_PER_RUN: 10,
  
  // 安全ブレーキ時間(4分30秒=270,000ミリ秒でループを安全停止)
  MAX_EXECUTION_TIME_MS: 270000,
  
  // Difyの終了ノードで設定した出力変数名
  OUTPUT_VARIABLE_NAME: 'rewrite_plan'
};

/**
 * スプレッドシート起動時にカスタムメニューを追加
 */
function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu('🤖 SEO自動化')
    .addItem('1. GSC×GA4データを最新化', 'syncSeoAndGa4Data')
    .addItem('2. リライト改善案をDifyで自動生成', 'generateRewritePlansWithDify')
    .addToUi();
}

/**
 * 「🔥最優先リライト」「✏️タイトル改善」の行だけを抽出してDify APIを呼び出す
 */
function generateRewritePlansWithDify() {
  const startTime = Date.now();
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName(DIFY_SEO_CONFIG.SHEET_NAME);
  if (!sheet) {
    throw new Error('シート「' + DIFY_SEO_CONFIG.SHEET_NAME + '」が見つかりません。');
  }

  const props = PropertiesService.getScriptProperties();
  const apiUrl = props.getProperty('DIFY_API_URL');
  const apiKey = props.getProperty('DIFY_API_KEY');

  if (!apiUrl || !apiKey) {
    throw new Error('スクリプトプロパティに DIFY_API_URL と DIFY_API_KEY を設定してください。');
  }

  const lastRow = sheet.getLastRow();
  if (lastRow < 2) {
    Logger.log('データが存在しません。');
    return;
  }

  // A列〜J列(1〜10列目)のデータを一括取得
  const range = sheet.getRange(2, 1, lastRow - 1, 10);
  const values = range.getValues();

  let processedCount = 0;

  for (let i = 0; i < values.length; i++) {
    // 1. 最大件数ガードレール
    if (processedCount >= DIFY_SEO_CONFIG.MAX_ITEMS_PER_RUN) {
      Logger.log('1回の上限件数(' + DIFY_SEO_CONFIG.MAX_ITEMS_PER_RUN + '件)に達したため停止します。');
      break;
    }

    // 2. 実行時間ガードレール(4分30秒経過で安全停止)
    if (Date.now() - startTime > DIFY_SEO_CONFIG.MAX_EXECUTION_TIME_MS) {
      Logger.log('制限時間(4分30秒)に近づいたため安全停止します。');
      break;
    }

    const row = values[i];
    const pageUrl = String(row[0] || '').trim();   // A列: 記事URL
    const query = String(row[1] || '').trim();     // B列: 検索クエリ
    const ctr = String(row[4] || '').trim();       // E列: CTR
    const position = String(row[5] || '').trim();  // F列: 平均掲載順位
    const flag = String(row[7] || '').trim();      // H列: 判定フラグ
    const currentPlan = String(row[8] || '').trim(); // I列: AIリライト改善案
    const status = String(row[9] || '').trim();    // J列: AI処理ステータス

    // 判定フラグが「最優先リライト」または「タイトル改善」以外ならスキップ
    const isTarget = (flag.indexOf('最優先リライト') !== -1 || flag.indexOf('タイトル改善') !== -1);
    if (!isTarget) continue;

    // すでに生成済み(完了)ならスキップして二重課金を防止
    if (status === '完了' && currentPlan !== '') continue;

    const targetRowNumber = i + 2;
    Logger.log('Dify生成開始(' + targetRowNumber + '行目): ' + query);

    const inputs = {
      page_url: pageUrl,
      query: query,
      ctr: ctr,
      position: position,
      flag: flag
    };

    const result = callDifyWorkflowForSeo(apiUrl, apiKey, inputs);

    if (result.success) {
      sheet.getRange(targetRowNumber, 9).setValue(result.text); // I列へ改善案を出力
      sheet.getRange(targetRowNumber, 10).setValue('完了');      // J列へステータス出力
      processedCount++;
    } else {
      sheet.getRange(targetRowNumber, 10).setValue('エラー: ' + result.error);
    }

    // APIレート制限回避のため1.5秒待機
    Utilities.sleep(1500);
  }

  Logger.log('AIリライト案の生成完了: ' + processedCount + ' 件');
}

/**
 * DifyのワークフローAPI(/v1/workflows/run)を呼び出す共通関数
 */
function callDifyWorkflowForSeo(apiUrl, apiKey, inputs) {
  const payload = {
    inputs: inputs,
    response_mode: 'blocking',
    user: 'gsc-seo-automation'
  };

  const options = {
    method: 'post',
    contentType: 'application/json',
    headers: {
      Authorization: 'Bearer ' + apiKey
    },
    payload: JSON.stringify(payload),
    muteHttpExceptions: true
  };

  try {
    const response = UrlFetchApp.fetch(apiUrl, options);
    const code = response.getResponseCode();
    const text = response.getContentText();

    if (code !== 200) {
      return { success: false, error: 'HTTP ' + code + ' ' + text.substring(0, 100) };
    }

    const json = JSON.parse(text);
    const outputs = (json.data && json.data.outputs) ? json.data.outputs : {};
    const planText = outputs[DIFY_SEO_CONFIG.OUTPUT_VARIABLE_NAME] || outputs.text || JSON.stringify(outputs);

    return { success: true, text: planText };
  } catch (e) {
    return { success: false, error: e.message };
  }
}

保存したら、上部ツールバーの関数選択ドロップダウンを generateRewritePlansWithDify に切り替えて「実行」ボタンをクリックします(またはスプレッドシートを再読み込みして、上部メニューの「🤖 SEO自動化」➔「2. リライト改善案をDifyで自動生成」をクリックします)。

実行後、スプレッドシートのH列が「🔥最優先リライト」または「✏️タイトル改善」になっている行のI列に、Difyが生成した「検索意図のギャップ仮説」「新タイトル案2つ」「追加すべきH2/H3見出し案」が自動入力され、J列が「完了」になれば大成功です!

APIコストの無駄遣いとGAS「6分制限」を防ぐ3つの運用ガードレール

この自動生成パイプラインを毎週安全に回し続けるために、上記のコードにはあらかじめ3つの実務ガードレールを組み込んでいます。運用時は以下のポイントを意識しておきましょう。

1. 「MAX_ITEMS_PER_RUN(1回10件上限)」でAPI従量課金の暴走を防ぐ

サイトの規模が大きくなると、「🔥最優先リライト」に該当するクエリが100件以上出てくることがあります。これらを一度にすべてLLMへ投げると、APIトークンを大量に消費してしまいます。

上記コードでは MAX_ITEMS_PER_RUN: 10 を設定し、1回の実行あたり上から最大10件までで自動ストップするように設計しています。さらにJ列に 完了 と記録された行は次回以降スキップされるため、2回目・3回目と実行するごとに「未処理の次の10件」へと安全に処理が進みます。

2. 前回のデータ更新時に「AI生成済みの列(I列・J列)」を消さない工夫

前回の記事で作成した syncSeoAndGa4Data() では、毎週データを書き直す際にシート全体をクリアしていました。もしAIが生成した改善案を消したくない場合は、週次バッチの直後に自動で generateRewritePlansWithDify() を連続実行するトリガーを組むか、気に入った改善案を別シート(例:リライト作業管理表)へコピーしてストックしていく運用がおすすめです。

3. Dify側で「HTTP 502 / 504エラー」が出る場合の対処法

GASを実行した際、J列に エラー: HTTP 502 や HTTP 504 と出力される場合は、GAS側のプログラムミスではなく、受け手であるVPS上のDifyコンテナがメモリ不足(OOM Killer)で落ちているか、プロンプト処理が重すぎてタイムアウトしているサインです。

特にセルフホスト版のDifyをメモリ1GB〜2GBのVPSで動かしている場合、連続してAPIリクエストを送ると高確率で502エラーが発生します。詳しい診断コマンドと復旧手順は以下の記事で解説しています。

🛠️ DifyのAPI呼び出し時に「502 Bad Gateway」が出る場合の解決手順:
・【Difyエラー解決】VPS(Docker)環境で「502 Bad Gateway」が出る4大原因と復旧手順!メモリ不足・Nginx設定の直し方

まとめ:データ収集からリライト案作成までを自動化し、記事の順位を最短で引き上げよう

本記事では、Google Apps Script(GAS)で集約したSearch Console・GA4データとDifyのワークフローAPIを連携させ、スプレッドシート上にリライト改善案を自動生成する手順を解説しました。

  • ピンポイント抽出で高コスパ: シート全行ではなく「🔥最優先リライト」「✏️タイトル改善」の行だけをフィルタリングしてDifyへ送信するため、APIコストを最小限に抑えられる。
  • プロンプト調整はDify画面で完結: GASのコードを触ることなく、Difyのブラウザ画面上でAIモデルの切り替えやリライト指示のブラッシュアップが自在に行える。
  • 安全ガードレール内蔵: 1回あたりの最大生成件数(10件)と4分30秒の安全ブレーキにより、GASの6分制限エラーや二重課金を確実に回避できる。

これで「①Looker Studioでの全体監視」➔「②GASによるリライト候補の自動抽出」➔「③Difyによる改善タイトル・追加見出しの自動立案」という一気通貫のSEO自動化システムが完成しました。あとは毎週出力される改善案をもとに記事をブラッシュアップし、検索1ページ目(トップ5)への浮上を加速させていきましょう!

🚀 【2026年最新】Dify・AI自動化を安定稼働できるおすすめ国内VPS 3選を見る