Amazonで商品を見る セール会場へ

WordPress│WP REST APIとGASを使った投稿・更新方法

GASからWordPressのREST APIを呼び、下書きの作成、投稿の読み取りと更新、専用メタ項目の更新を行います。

旧記事の任意キーを書き込むpost_metaフィールドは使いません。

目次

著者

WEB制作をしているデジタルノマド
WordPressのカスタマイズが好きで、色々と自作しています。

WordPressのカスタマイズに困ったらご相談ください!

接続の準備

対象の投稿を編集できる専用ユーザーを用意し、そのユーザーのアプリケーションパスワードを発行します。

管理者権限を一律に要求するものではありません。

GASのプロジェクト設定→スクリプトプロパティへWP_SITE_URL、WP_USER、WP_APP_PASSWORDを登録します。

URLはhttps://example.comまたはhttps://example.com/wordpressのようにWordPressの設置先を指定します。

プロジェクトを編集できる人はスクリプトプロパティを取得できます。

共有範囲を限定し、通常のログインパスワードをコードやログへ書かないでください。

初回の認可画面は対象プロジェクトと要求権限を確認します。

警告を無条件で迂回する手順ではありません。

GASに追加する共通処理と操作関数

function wazaRequest(path, method, payload) {
  const p = PropertiesService.getScriptProperties();
  const base = (p.getProperty('WP_SITE_URL') || '').replace(/\/+$/, '');
  const user = p.getProperty('WP_USER');
  const pass = p.getProperty('WP_APP_PASSWORD');
  if (!/^https:\/\/[^\s/?#@:]+(?:\/[^\s?#]*)?$/.test(base) || !user || !pass) {
    throw new Error('HTTPSのサイトURLと認証用プロパティを確認してください');
  }
  if (!/^\/posts(?:\/[1-9]\d*)?(?:\?context=edit)?$/.test(path)) throw new Error('対象パスが不正です');
  const options = {
    method: method, contentType: 'application/json',
    headers: {Authorization: 'Basic ' + Utilities.base64Encode(user + ':' + pass)},
    muteHttpExceptions: true, followRedirects: false
  };
  if (payload !== undefined) options.payload = JSON.stringify(payload);
  const response = UrlFetchApp.fetch(base + '/wp-json/wp/v2' + path, options);
  const status = response.getResponseCode();
  if (status < 200 || status >= 300) throw new Error('WordPress HTTP ' + status);
  return JSON.parse(response.getContentText());
}
function wazaCreateDraft() {
  const post = wazaRequest('/posts', 'post', {
    title: '自動投稿テスト', content: '<p>下書きのテストです。</p>', status: 'draft'
  });
  return post.id; // IDを控える。再実行すると別の下書きが作られる。
}
function wazaReadPost(postId) {
  if (!Number.isSafeInteger(postId) || postId <= 0) throw new Error('投稿IDが不正です');
  return wazaRequest('/posts/' + postId + '?context=edit', 'get');
}
function wazaUpdatePost(postId, expectedModified, title, content) {
  const current = wazaReadPost(postId);
  if (!expectedModified || current.modified_gmt !== expectedModified) throw new Error('更新競合: 最新版を確認してください');
  return wazaRequest('/posts/' + postId, 'post', {title: title, content: content});
}
function wazaUpdateNote(postId, text) {
  if (!Number.isSafeInteger(postId) || postId <= 0 || typeof text !== 'string') throw new Error('入力が不正です');
  return wazaRequest('/posts/' + postId, 'post', {meta: {waza_note: text}});
}

下書きを作り、内容を確認する

最初はwazaCreateDraftを1回実行し、返された投稿IDを控えます。

再実行で別の下書きができるので、失敗表示の後も管理画面を確認してから再試行します。

成功後は編集画面で本文・公開状態を確認してください。

この例では自動公開しません。

既存記事の更新

wazaReadPost(対象ID)のtitle.raw、content.raw、modified_gmtと公開状態を更新前に保存します。

wazaUpdatePostにはそのID、保存したmodified_gmt、新タイトル、新本文を渡します。

statusを送らないため現在の公開状態を維持します。

公開済み記事では本文が即時反映されます。

直前にmodified_gmtを照合しますが、GETとPOSTの間を排他制御するものではありません。

同時編集を止めた複製環境で試し、更新後の値を再取得して確認します。

戻す場合も最新版を保存して競合を確認し、保存済みの本文とタイトルだけを戻します。

WordPress側:専用の文字列メタを登録

変更前のPHPを保存し、復旧できる状態にしてから追加します。

次をWordPress側の小さな専用プラグインまたは子テーマfunctions.phpへ追加します。

同じ関数とフックは1か所だけに登録します。

標準投稿のwaza_noteだけを登録し、既存の汎用post_meta追加コードは停止します。

SCFの繰り返しグループや任意の既存フィールドを更新する例ではありません。

function waza_register_note_meta() {
    register_post_meta('post', 'waza_note', array(
        'type' => 'string',
        'single' => true,
        'sanitize_callback' => 'sanitize_text_field',
        'auth_callback' => function ($allowed, $key, $post_id) {
            return current_user_can('edit_post', $post_id);
        },
        'show_in_rest' => array('schema' => array(
            'type' => 'string', 'context' => array('edit'),
        )),
    ));
}
add_action('init', 'waza_register_note_meta');

wazaUpdateNote(対象ID, “確認メモ”)で更新できます。

この関数にはwazaUpdatePostのmodified_gmtによる競合チェックがありません。

更新前にwazaReadPostで現在のmeta.waza_noteを保存し、同時編集を止めた検証用の下書きで試してください。

更新後は値を再取得して比較します。

保存済みの値へ戻す場合も、その間に別の変更がないか確認してから実行します。

RESTのeditコンテキストに限定し、対象投稿の編集権限を確認します。

他のプラグインやテンプレートまで含めて秘密を保証するものではないため、パスワードなどは保存しないでください。

文字列以外は送信しません。

下書きで確認する応答と保存結果

表の「更新競合」はwazaUpdatePostによるタイトル・本文更新の確認です。

スクロールできます
操作確認する結果
下書き作成HTTP 201と返された投稿ID。管理画面では下書きが1件だけ増える
読み取り・本文更新HTTP 200。本人のtitle.raw・content.rawが一致し、公開状態を維持
waza_note更新HTTP 200。登録済みの文字列だけを保存し、タグを除去
取得時刻から他の更新がある更新競合のエラーでPOSTを送らない
アプリケーションパスワードが不正HTTP 401。通常パスワードへの置き換えで済ませない
対象投稿を編集できないHTTP 403。ユーザーと投稿の編集権限を確認

WordPress 7.1.2の隔離環境で、掲載した共通処理を模擬GASサービス経由で実行し、実際のHTTPS通信と専用アプリケーションパスワードによる保存・拒否を確認しました。

Google側のUrlFetchApp、認可画面、トリガーの実動作まで確認した結果ではありません。

設置先でも下書き1件を使って、応答だけでなく保存内容を再取得して比較します。

エラーと撤去

HTTP 401/403は認証と投稿編集権限、404はサイトURLと投稿ID、400は値の形式を確認します。

3xxも失敗扱いで、認証ヘッダー付きの自動転送はしません。

接続先の正規URLを設定してください。

利用をやめる場合はGASのトリガーを停止し、不要になった専用アプリケーションパスワードを失効させます。

メタ登録を外しても保存済みの値は自動削除されません。

参照:WordPress REST APIのメタ項目登録。

隔離WordPressへのHTTPS通信で認証・投稿操作を確認しましたが、実際のGASプロジェクトからの実行と認可は別途確認が必要です。

旧外部コード集は未同期です。

  • URLをコピーしました!

実装を任せたい方へ

WordPressのカスタマイズ代行

ブロックの追加、テーマの改修、管理画面の調整など、記事で紹介している内容の実装を承ります。1時間 ¥8,000〜(税込)。

WAZAの有料記事のサブスクリプションも開始しました。

サービス

Service

WordPressサイトのカスタマイズのサービスに関心がありましたら、ぜひ詳細をご覧ください。

目次