GASでブログ記事からAIで
SNS投稿文を自動生成する方法
スプレッドシートに並べた記事のタイトルと要点をClaude APIに渡し、X(旧Twitter)・Instagram・Facebook向けの投稿文を、SNSごとの文字数と口調に合わせてまとめて自動生成する仕組みを、動くコードで解説します。 「投稿文を書く」下ごしらえをAIに任せ、人は「選ぶ・整えて投稿する」に集中する、記事拡散のためのレシピです。
Table of Contents
なぜSNS投稿文づくりをAIで自動化するのか
ブログ記事を書いても、SNSで告知しなければ読まれる機会は増えません。 とはいえ、記事1本ごとにX・Instagram・Facebookそれぞれ用の文章を考えるのは、意外と手間がかかります。 媒体ごとに最適な長さと口調が違うので、1本の文章を使い回すだけでは反応が伸びにくいのが悩みどころです。
そこで、スプレッドシートに並べた記事のタイトルと要点をClaude APIに渡し、SNSごとに文字数と口調を分けた投稿文をまとめて生成します。 人は出そろった下書きから選び、必要なら一言足して投稿するだけ。 「書く」作業をAIに任せることで、記事を出すたびの告知を無理なく続けられます。
媒体ごとに作り分け
X・Instagram・Facebookの文字数と口調をSNSごとに指定して生成する
要点から一気に
記事の要点を渡すだけで、複数SNSの投稿文をまとめて受け取れる
文字数の上限を担保
各SNSの目安文字数を指示し、GAS側でも超過に印を付ける
一覧で管理
記事とSNSごとの投稿文をシートに横並びで残し、投稿前の確認をしやすくする
APIキーを安全に保管する
使うのはClaude APIキーです。コードに直接書くと共有時に漏れる恐れがあるため、PropertiesService(スクリプトごとの設定値を安全に保管する仕組み)のスクリプトプロパティに保存します。 コードからはgetProperty()で読み込みます。
// スクリプトプロパティにAPIキーを保存(初回1回だけ実行)
function saveApiKey() {
PropertiesService.getScriptProperties()
.setProperty("CLAUDE_API_KEY", "sk-ant-xxxxxxxx");
}
function getApiKey() {
const key = PropertiesService.getScriptProperties().getProperty("CLAUDE_API_KEY");
if (!key) throw new Error("APIキーが未設定です。saveApiKey を実行してください。");
return key;
}Claude APIの基本的な呼び出し方は、GASからClaude APIを呼び出して問い合わせを自動分類する方法で詳しく解説しています。
記事シートとSNSごとの設定を用意する
まず、投稿文を作りたい記事をA列にタイトル、B列に要点(リード文や見出しをまとめたもの)、C列にURLで並べたシートを用意します。 D列は状態(未処理/完了)を記録する欄、E列以降がSNSごとの投稿文の出力欄です。 どのSNS向けに、何文字以内で、どんな口調で作るかはTARGETSにまとめて設定します。
// 記事を並べるシートと、SNSごとの設定
const SHEET_NAME = "記事";
// 生成したいSNSと、その文字数の目安・方針
const TARGETS = [
{ key: "x", label: "X", max: 140, note: "要点を短く。URLは末尾に置く前提で本文は簡潔に。" },
{ key: "instagram", label: "Instagram", max: 300, note: "共感を誘う語り口。改行を使い読みやすく。" },
{ key: "facebook", label: "Facebook", max: 250, note: "丁寧めの説明口調。読者に一歩踏み込んで伝える。" },
];
// シートを用意する(無ければ作り、見出し行を入れる)
// A列: タイトル / B列: 要点 / C列: URL / D列: 状態 / E列以降: SNSごとの投稿文
function getArticleSheet() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
let sheet = ss.getSheetByName(SHEET_NAME);
if (!sheet) {
sheet = ss.insertSheet(SHEET_NAME);
const header = ["タイトル", "要点", "URL", "状態"];
TARGETS.forEach(function (t) { header.push(t.label); });
sheet.appendRow(header);
}
return sheet;
}SNSを増やしたい・減らしたいときはTARGETSの中身を書き換えるだけで、プロンプトも出力欄も自動で追従します。 文字数の目安(max)はあくまで生成時の指示用なので、各SNSの実際の上限に合わせて調整してください。
1記事からSNSごとの投稿文をJSONで受け取る
ここが今回の中心です。記事のタイトル・要点・URLを渡し、SNSごとの投稿文を JSON(キーと値をまとめて扱う形式)で1回のAPI呼び出しでまとめて受け取ります。TARGETSの設定からプロンフトの条件(文字数・口調)を自動で組み立てるので、SNSを足しても書き換えは1か所で済みます。
// 1記事から、SNSごとの投稿文をまとめて受け取る
function generatePosts(title, summary, url) {
// SNSごとの条件を箇条書きにする
const rules = TARGETS.map(function (t) {
return "・" + t.key + "(" + t.label + "): 全角" + t.max +
"文字以内。" + t.note;
}).join("\n");
const keys = TARGETS.map(function (t) { return '"' + t.key + '"'; }).join(", ");
const instruction =
"あなたは企業のSNS運用に詳しい日本語の編集者です。\n" +
"次のブログ記事を紹介する投稿文を、SNSごとに1つずつ作ってください。\n" +
"記事タイトル: " + title + "\n" +
"記事の要点: " + summary + "\n" +
"記事URL: " + url + "\n" +
"条件:\n" + rules + "\n" +
"・各SNSに合う口調と長さにする。\n" +
"・記事内容に関連するハッシュタグを最大3個まで付ける。\n" +
"・事実と異なる断定や誇大表現は避ける。\n" +
"余計な説明は出力せず、JSONだけを返してください。\n" +
"形式: {" + keys + "} の各値が投稿文の文字列。";
const payload = {
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
messages: [{ role: "user", content: instruction }],
};
const res = UrlFetchApp.fetch("https://api.anthropic.com/v1/messages", {
method: "post",
contentType: "application/json",
headers: {
"x-api-key": getApiKey(),
"anthropic-version": "2023-06-01",
},
payload: JSON.stringify(payload),
muteHttpExceptions: true,
});
if (res.getResponseCode() !== 200) {
throw new Error("API error: " + res.getContentText());
}
const responseText = JSON.parse(res.getContentText()).content[0].text;
return JSON.parse(extractJson(responseText)); // { x, instagram, facebook }
}
// レスポンスから { ... } の部分だけを取り出す(前後の余計な文字対策)
function extractJson(text) {
const start = text.indexOf("{");
const end = text.lastIndexOf("}");
return text.slice(start, end + 1);
}AIの返答には、まれに前後の説明文が混ざります。そのためextractJson()で最初の{から最後の}までを切り出してから解析し、崩れにくくしています。 モデル名やパラメータの詳細は、利用中のプランやAPIの最新仕様に合わせて調整してください。
シートを回して処理済みをスキップする
シートを上から順に見て、タイトルが入っていて、かつ状態が「完了」ではない行だけを処理します。 受け取った投稿文はTARGETSの順にE列以降へ書き込み、書き終えたらD列に「完了」を記録します。 GASの実行時間制限に収まるよう、1回あたりの処理件数に上限を設けます。
// シートを回して、未処理の記事だけ投稿文を作る
function generateAllPosts() {
const sheet = getArticleSheet();
const values = sheet.getDataRange().getValues();
const statusCol = 4; // D列: 状態
const firstPostCol = 5; // E列以降: SNSごとの投稿文
let count = 0;
for (let row = 1; row < values.length && count < 10; row++) { // 1回最大10件
const title = String(values[row][0]).trim();
const summary = String(values[row][1]).trim();
const url = String(values[row][2]).trim();
const status = String(values[row][3]).trim();
if (!title) continue; // タイトルが無い行はスキップ
if (status === "完了") continue; // 生成済みはスキップ
const posts = generateWithRetry(title, summary, url);
// TARGETSの順にSNSごとの投稿文を書き込む(上限超えには印を付ける)
TARGETS.forEach(function (t, i) {
const text = posts && posts[t.key] ? String(posts[t.key]) : "";
const over = [...text].length > t.max ? " ⚠️長い" : "";
sheet.getRange(row + 1, firstPostCol + i).setValue(text + over);
});
sheet.getRange(row + 1, statusCol).setValue("完了"); // D列に状態を記録
count++;
Utilities.sleep(500); // 連続呼び出しの間隔を少し空ける
}
Logger.log(count + "件の記事でSNS投稿文を生成しました。");
}文字数は[...text].lengthで数えています。文字列をスプレッド構文で1文字ずつに分けると、絵文字などを含む場合でも見た目に近い文字数を数えられます。 目安を超えた投稿文には「⚠️長い」と印を付けるので、そのまま投稿できるかを一目で判断できます。
リトライで一時的なエラーに備える
APIは、混雑や通信の乱れで一時的に失敗することがあります。 1回の失敗で止めず、少し待ってから再試行するリトライを挟むと、まとめて処理するときに安定します。 何度も失敗する記事は空の結果を返して次へ進め、処理全体を止めないようにします。
// 一時的なAPIエラー時に最大3回まで再試行する
function generateWithRetry(title, summary, url, maxRetry) {
const limit = maxRetry || 3;
for (let attempt = 1; attempt <= limit; attempt++) {
try {
return generatePosts(title, summary, url);
} catch (e) {
Logger.log("試行" + attempt + "回目で失敗: " + e.message);
if (attempt === limit) {
return {}; // 空を返して次の記事へ進む
}
Utilities.sleep(1000 * attempt); // 待ち時間を伸ばして再試行
}
}
}カスタムメニューから一括実行する
投稿文づくりは、記事を書き終えたタイミングで動かしたいことが多いので、 スプレッドシートのメニューから実行できるようにしておくと便利です。onOpen()でカスタムメニューを追加すれば、シートを開くだけで「SNS投稿文生成」メニューが並びます。
// スプレッドシートを開いたときにカスタムメニューを追加する
function onOpen() {
SpreadsheetApp.getUi()
.createMenu("SNS投稿文生成")
.addItem("未処理の記事を一括生成", "generateAllPosts")
.addToUi();
}記事が大量にあり、放っておいて処理させたい場合は、時間主導トリガーで定期実行する形にもできます。1回の上限で少しずつ消化されるので、実行時間制限に引っかかりません。
実務での注意点
1. 投稿前に人が目を通す
SNSは自社の口調やブランドが伝わる場です。AIの下書きは便利ですが、そのまま自動投稿するより、選んで整えてから投稿する運用が安全です。 このコードは投稿文をシートに書き出すだけで投稿は行いません。事実の食い違いや過度な煽りがないかを確認してください。
2. 文字数は指示と後チェックの両方で守る
プロンプトで文字数を指示しても超えることがあるため、GAS側でも数えて印を付けています。 特にXはURLや絵文字の数え方に癖があるので、最終的な文字数は投稿画面でも確認するのが確実です。
3. ハッシュタグは実在するものに調整する
AIは実在しない流行タグを作ってしまうことがあります。自社でよく使うタグや、実際に検索されているタグと照らし合わせて調整してください。 タグの付けすぎは逆効果になりやすいので、媒体ごとに数を絞るのがおすすめです。
4. 実行時間とコストの上限に注意する
GASには1回あたり6分の実行時間制限があります。1記事ごとにAPIを呼ぶため、 件数が多いほど時間とトークン消費が増えます。1回の処理件数に上限を設け、残りは次回に回す形にすると安定します。
まとめ
SNS投稿文づくりは、記事のタイトルと要点をClaude APIに渡し、SNSごとの投稿文をJSONでまとめて受け取り、処理済みをスキップしながらシートに横並びで書き出せば、まとめて自動化できます。 文字数はプロンプトとGAS側の両方で見張り、最後は人が中身に合わせて選ぶ運用にすれば、記事を出すたびの告知を無理なく続けられます。 「書く」下ごしらえをAIに任せ、人は「選ぶ・磨く・投稿する」に集中してください。
よくある質問
下書きとしては十分使えますが、投稿する前に一度目を通すことをおすすめします。SNSは自社の口調やブランドの雰囲気が伝わる場なので、そのまま自動投稿するより「AIに下書きを作らせ、人が選んで整えてから投稿する」運用が現実的です。この記事のコードはSNSごとに投稿文をシートに書き出すだけで、投稿自体は行いません。誤字・事実の食い違い・過度な煽りがないかを確認してから使ってください。
SNSごとに最適な文体と長さが違うためです。X(旧Twitter)は短く要点を絞る方が読まれ、Instagramは共感を誘う長めの本文とハッシュタグが相性よく、Facebookはその中間で丁寧めの文章が好まれます。同じ記事でも1本の文章を使い回すより、媒体ごとに作り分けた方が反応が変わります。この記事ではプロンフトでSNSごとの文字数と方針を指定し、JSONで媒体別にまとめて受け取ります。
あります。プロンプトで「140文字以内」などと指示しても、AIは時々超えてくるため、この記事ではGAS側でも文字数を数えて、上限を超えた投稿文には「⚠️長い」と印を付けています。特にXは全角・半角やURL・絵文字の数え方に癖があるため、最終的な文字数は投稿画面でも確認するのが安全です。指示と後チェックの両方を入れておくと、そのまま使える割合が上がります。
はい。この記事のプロンプトでは、記事内容に関連するハッシュタグを数個まで付けるよう指示しています。ただしAIは実在しない流行タグを作ってしまうこともあるため、そのまま使う前に自社アカウントでよく使うタグや、実際に検索されているタグと照らし合わせて調整してください。タグの付けすぎは逆効果になりやすいので、媒体ごとに数を絞るのがおすすめです。
できます。この記事では、記事タイトルと要点(リード文や見出しをまとめたもの)をシートに入れておき、それをもとに投稿文を作ります。本文全体を送るとトークン消費が増え、GASの実行時間制限にも近づくため、要点だけを渡す方が速く安定します。UrlFetchAppで記事URLから本文を取得して要約してから渡す方法もありますが、まずは手元の要点で試すのが手軽です。
直接書くのは避けてください。スクリプトを共有した際に漏れる恐れがあります。Claude APIキーは PropertiesService(スクリプトごとの設定値を安全に保管する仕組み)のスクリプトプロパティに保存し、コードからは getProperty() で読み込む方法が安全です。
関連するサービス・記事
同じくコンテンツを量産する実装です。タイトル案づくりとSNS投稿文づくりを組み合わせると、記事の入口から拡散まで一気に下ごしらえできます。
GASでキーワードからAIでブログ記事タイトル案を量産する方法を見る →
記事URLから本文を取得して要点にまとめる実装です。要点づくりを自動化してから投稿文生成につなげられます。
GASでWebページのURLをAIで要約してスプレッドシートに保存する方法を見る →
Claude APIの基本的な呼び出し方・APIキーの保管・エラー処理を、分類を例に基礎から解説しています。
GASからClaude APIを呼び出して問い合わせを自動分類する方法を見る →
文章生成・要約・分類など、AIとGASを組み合わせた業務自動化の依頼内容と進め方を紹介します。
AI×GAS自動化の対応範囲を見る →
コンテンツ発信の
自動化を相談する。
SNS投稿文づくり以外にも、タイトル案・要約・分類など、AIとGASを組み合わせたコンテンツ・業務の自動化をご相談いただけます。