はじめに
WordPressで記事を公開したタイミングで、X(旧Twitter)にも自動投稿したい、という要望はかなり多いです。プラグインでも実現できますが、API制限や将来的な仕様変更を考えると、外部連携を自前で持っておく価値は高いです。
この記事では、WordPress → Google Apps Script(GAS)Web App → X API v2 という構成で、投稿内容をXに自動投稿する仕組みを実装し、そのコードを一つずつ解説します。実運用を想定し、エラーハンドリングやログ保存まで含めた構成です。
ただ動かしたい人は次の記事に行ってください。こっちはコードの解説バージョンで難しいです。
→WordPressからXへ自動投稿する最強構成を自作した話 ― プラグインを捨てて、GAS+X APIで“壊れない配信基盤”を作る
全体構成の概要
流れは非常にシンプルです。
- WordPress側からHTTP POSTでJSONを送信
- GASの
doPost(e)が受信 - X API v2(OAuth 1.0a)を使ってポスト
- 結果をスプレッドシートにログ保存
- JSONでレスポンスを返却
WordPress側は「投稿ID」と「本文テキスト」を送るだけで済むため、REST APIやフックとの相性も良い構成です。
エントリーポイント:doPost(e)
function doPost(e) {
try {
if (!e || !e.postData || !e.postData.contents) {
throw new Error('No postData');
}
const data = JSON.parse(e.postData.contents);
if (!data.text) {
throw new Error('No text');
}
const tweetId = postToX(data.text);
logPost({
post_id: data.post_id || '',
text: data.text,
tweet_id: tweetId,
status: 'success',
error: ''
});
return json({ ok: true, tweet_id: tweetId });
} catch (err) {
logPost({
post_id: '',
text: '',
tweet_id: '',
status: 'error',
error: err.toString()
});
return json({ ok: false, error: err.toString() });
}
}
役割
- GAS Web AppのHTTP POST受付口
- WordPressから送られたJSONを検証
- 投稿処理・ログ処理・レスポンス生成を統括
ポイント
e.postData.contentsが空の場合は即エラー- JSON.parse失敗もcatchでまとめて処理
- 成功・失敗いずれもログを残す
- WordPress側が扱いやすいJSONレスポンスを返却
Web Appを「APIサーバ」として扱う前提の、堅実な構造です。
X(旧Twitter)への投稿処理
function postToX(text) {
const props = PropertiesService.getScriptProperties();
const url = 'https://api.twitter.com/2/tweets';
const method = 'POST';
const oauth = {
oauth_consumer_key: props.getProperty('X_API_KEY'),
oauth_token: props.getProperty('X_ACCESS_TOKEN'),
oauth_nonce: Utilities.getUuid(),
oauth_timestamp: Math.floor(Date.now() / 1000),
oauth_signature_method: 'HMAC-SHA1',
oauth_version: '1.0'
};
認証方式について
X API v2でも「ツイート投稿」は OAuth 1.0a が必要です。Bearer Tokenでは投稿できません。この点で詰まる人が非常に多いです。
ここでは以下をScriptPropertiesに保存して使用しています。
- X_API_KEY
- X_API_SECRET
- X_ACCESS_TOKEN
- X_ACCESS_SECRET
署名ベース文字列の生成
const baseString =
method + '&' +
encodeURIComponent(url) + '&' +
encodeURIComponent(
Object.keys(oauth)
.sort()
.map(k => `${encodeURIComponent(k)}=${encodeURIComponent(oauth[k])}`)
.join('&')
);
OAuth 1.0aでは、
- HTTPメソッド
- URL
- 全OAuthパラメータ(アルファベット順)
を結合した「署名ベース文字列」を作成します。この順序が一つでも違うと認証エラーになります。
署名生成とAuthorizationヘッダ
const signingKey =
encodeURIComponent(props.getProperty('X_API_SECRET')) + '&' +
encodeURIComponent(props.getProperty('X_ACCESS_SECRET'));
const signatureBytes = Utilities.computeHmacSignature(
Utilities.MacAlgorithm.HMAC_SHA_1,
baseString,
signingKey
);
oauth.oauth_signature = Utilities.base64Encode(signatureBytes);
GAS標準のcomputeHmacSignatureを使えば、外部ライブラリ不要で署名を生成できます。
const authHeader = 'OAuth ' + Object.keys(oauth)
.sort()
.map(k => `${encodeURIComponent(k)}="${encodeURIComponent(oauth[k])}"`)
.join(', ');
最終的にこのAuthorizationヘッダをUrlFetchApp.fetchで送信します。
投稿リクエストとレスポンス検証
const res = UrlFetchApp.fetch(url, {
method: 'post',
headers: {
Authorization: authHeader,
'Content-Type': 'application/json'
},
payload: JSON.stringify({ text }),
muteHttpExceptions: true
});
const body = JSON.parse(res.getContentText());
if (!body.data || !body.data.id) {
throw new Error(res.getContentText());
}
return body.data.id;
muteHttpExceptions: trueでエラー本文を取得- 投稿成功時は
data.idが必ず返る - 失敗時はレスポンス全文をそのままエラーにする
デバッグ時に非常に有効です。
投稿ログをスプレッドシートに保存
function logPost(row) {
const sheetId = PropertiesService
.getScriptProperties()
.getProperty('LOG_SHEET_ID');
if (!sheetId) return;
const sheet = SpreadsheetApp
.openById(sheetId)
.getSheets()[0];
sheet.appendRow([
new Date(),
row.post_id,
row.text,
row.tweet_id,
row.status,
row.error
]);
}
なぜログを残すのか
- WordPress側の再送防止
- 投稿失敗の原因追跡
- API制限・凍結時の証跡
自動化するほど「失敗したときの可視性」が重要になります。
JSONレスポンスの共通化
function json(obj) {
return ContentService
.createTextOutput(JSON.stringify(obj))
.setMimeType(ContentService.MimeType.JSON);
}
WordPress側で fetch や wp_remote_post を使う場合、JSONで返すのが最も扱いやすいです。
単体テスト用関数
function testPost() {
postToX('GASからのテスト投稿です');
}
Web Appを叩かなくても、
- 認証
- 署名
- 投稿
が正しく動くかを即座に確認できます。
まとめ
この構成の強みは以下です。
- WordPressとXを疎結合にできる
- プラグイン依存がない
- 投稿ログを確実に残せる
- 将来BlueskyやThreadsへも横展開しやすい
「自動投稿」は小さな仕組みに見えて、運用フェーズで差が出ます。GASを中継点にする構成は、個人運用から業務利用まで十分に耐える選択肢です。
Zidooka!では、X(旧Twitter)への自動投稿を含む業務自動化の開発も承っております。
本記事で紹介している構成をそのままお渡しし、セットアップまで含める場合は目安として1万円前後です。
運用状況に応じた例外処理やログ設計、WordPress側との連携調整など、細かなチューニングをご希望の場合は内容に応じてお見積りいたします。
ご興味がありましたら、
main@zidooka.com(山口)
まで、お気軽にご連絡ください。