WordPress REST APIで画像をアップロードしてアイキャッチに設定する手順|投稿は成功しているのに記事が完成しない理由
WordPress REST APIで画像をアップロードしてアイキャッチに設定する手順|投稿は成功しているのに記事が完成しない理由
WordPressのREST APIで自動投稿を組むと、最初に動くのは本文のPOSTです。タイトルと本文を送れば記事は作られ、200も返る。ところが管理画面を開くと、アイキャッチ画像だけが空のままという状態になります。
結論から書きます。アイキャッチの設定は本文投稿とは別工程で、画像アップロード → 代替テキスト設定 → 記事への紐付け、の3リクエストで完結します。そして自動化で本当に詰まるのはこの3リクエストではなく、その画像がどのドメインから配信されるかという設計のほうです。ここを決めずに公開すると、記事は正常に見えているのに検索結果やSNSでサムネイルだけが出ない状態が、記事数の分だけ積み上がります。
この記事では、graciautoが自社ブログの自動投稿基盤(100本以上を自動公開)で使っている実装と判断基準をそのまま公開します。
—
1. 結論:アイキャッチ設定は3リクエストで完結する
WordPressのREST APIでアイキャッチを設定するとき、叩くエンドポイントは次の3つだけです。
| 順番 | エンドポイント | メソッド | 目的 |
|---|---|---|---|
| ① | /wp-json/wp/v2/media |
POST | 画像ファイル本体をアップロードし、メディアIDを受け取る |
| ② | /wp-json/wp/v2/media/{id} |
POST | 代替テキスト(alt)とタイトルを設定する |
| ③ | /wp-json/wp/v2/posts |
POST | 記事を作成し、featured_media にメディアIDを渡す |
ポイントは3つです。
- 画像は記事とは別のリソースとして先に登録する。記事のPOSTに画像は同梱できません
featured_mediaに渡すのは画像のURLではなく、①で返る整数のIDです- ①だけでは代替テキストは入りません。②を省くとalt属性が空の画像が溜まり続けます
認証は本文投稿と同じアプリケーションパスワードで通ります。ユーザー名とパスワードをコロンでつないでBase64化し、Authorization: Basic ...ヘッダーに載せる方式です。アップロードにはupload_files権限が要るので、管理者ユーザーで1つ発行しておくと投稿・カテゴリ・メディアを1つの認証情報でまかなえます。
—
2. 画像アップロードはヘッダー2つで決まる(multipartは不要)
/wp/v2/mediaへのアップロードは、Webフォームの画像送信とは形が違います。multipart/form-dataを組み立てる必要はありません。画像のバイナリをそのままリクエストボディに入れ、ヘッダーで素性を伝えます。必須は次の2つです。
Content-Disposition: attachment; filename="eyecatch-20260811.jpg"
ここで指定した文字列がメディアライブラリ上のファイル名になります。このヘッダーが無いと、正しい画像を送っても登録は通りません
Content-Type: image/jpeg
ファイルの実体と一致させます。PNGならimage/png、WebPならimage/webp
MIMEタイプは拡張子から判定させ、判定できないときだけ既定値に落とします。固定値でベタ書きすると、あとからPNGをJPEGに切り替えた瞬間にアップロードだけが静かに失敗します。
成功するとレスポンスにid(メディアID)とsource_url(配信URL)が返ります。以降で使うのはこの2つです。なお実装に入る前に/wp/v2/users/me?context=editで認証だけが通ることを確認しておくと、以降のエラーを実装側の問題だと確定できます。
—
3. 代替テキスト(alt)は別リクエストで入れる
アップロードの成功で止まりがちですが、代替テキストはアップロード時のヘッダーでは設定できません。①で受け取ったIDに対し、あらためて/wp/v2/media/{id}へJSONをPOSTします。
alt_text:画像の内容を説明する文(検索エンジンと読み上げソフトが読む)title:メディアライブラリ上での管理名
自動投稿なら、記事タイトルを流用して「〈記事タイトル〉 – 〈サイト名〉ブログのアイキャッチ画像」のような文面を機械的に組み立てれば十分です。後回しにすると、数百枚たまってから一括で埋める作業が発生します。1枚につき1リクエスト増えるだけなので、最初から生成と同じ工程に入れます。
差し替える運用なら、古いメディアの削除まで手順にします。削除はDELETE /wp/v2/media/{id}?force=true。メディアはゴミ箱を経由しない仕様のためforce=trueの明示が要ります。忘れると使われない画像が積み上がり続けます。
—
4. 実例:自社ブログのアイキャッチをどう作っているか
graciautoの自動投稿基盤では、アイキャッチを写真素材にテンプレートを合成して作っています。ストックした写真を背景に、半透明の白帯・記事タイトル(明朝体)・英字カテゴリラベル・ロゴを重ねる方式です。生成した画像をそのまま/wp/v2/mediaへ送り、featured_mediaに紐付けます。
画像生成AIに「文字入りの完成画像」を作らせない判断
画像生成AIに丸ごと作らせる方式も試せますが、自動投稿に載せるなら写真素材+テンプレート合成のほうが安定します。理由は3つです。
- 日本語の文字が崩れない。生成AIに日本語タイトルを描かせると字形がぶれますが、合成側で描画すれば正確です
- ブランドのトーンが揃う。背景・帯・ロゴの位置が固定され、一覧に並べたときの見た目が統一されます
- 生成コストと待ち時間がかからない。1本あたり数秒で終わり、APIの障害にも左右されません
生成AIは背景写真を増やす用途では使えますが、タイトル文字を含む最終成果物を任せる場所ではないというのが実運用での判断です。
アイキャッチ生成は1本の関数に集約する
自動投稿の入口は時間とともに増えます(記事を書いて投稿する経路、既存の下書きにまとめて付ける経路、別スクリプトから呼ぶ経路)。このとき画像を作る処理は1つの関数に集約し、すべての経路がそこだけを呼ぶ形にします。経路ごとに生成コードを持たせると、片方だけを新方式に更新したときに経路によってデザインの違う画像が混ざります。エラーにならないため、公開後に一覧ページを見るまで気づけません。
また、素材やロゴの置き場所を特定ユーザー名を含む絶対パスで書くと、別の端末では素材が見つからず画像だけが生成されません。ホームディレクトリは実行時に取得します。
—
5. 投稿が成功しても記事が完成しない理由=画像の配信ドメイン
ここが本題です。①〜③が全部成功し、管理画面でもアイキャッチが表示されている。それでも記事が完成していないケースがあります。ヘッドレス構成(WordPressをCMS専用に置き、表示は別ドメインで行う構成)の場合です。
この構成では、WordPressをcms.〈ドメイン〉のようなサブドメインに置き、本番サイトはビルド時にREST APIから記事を取得して静的HTMLを吐きます。このときfeatured_mediaから解決される画像URLは、CMS側のサブドメインを指したままになります。
そしてヘッドレス構成では、CMS側をrobots.txtで全面クロール拒否するのが定石です。同じ本文が2箇所で読める状態は重複コンテンツになるため、遮断の判断自体は正しい。問題は、その遮断がアイキャッチにも効いてしまうことです。
記事ページのog:imageも構造化データ(Article)のimageもCMS側のURLを指しており、そのCMSはクロール拒否——検索エンジンはその画像を取得できません。
結果、記事本文は正常にインデックスされているのに、検索結果のサムネイル・Discover・SNSシェア時のカードだけが空になります。画像自体はブラウザで開けば表示されるので、目視では気づけません。
この状態は記事数の分だけ一斉に発生します。1本ずつ壊れるのではなく、構成を切り替えた瞬間に全記事が同時にこうなるためです。記事168本規模のブログでヘッドレス化後の点検を行うと、全記事のog:imageがCMS側を指したままという状態は珍しくありません。
正しい設計:画像は本番ドメインから配信する
対処は「CMS側のrobots.txtを緩める」ではなく、画像を本番ドメイン配下に書き出して配信する(自己ホスト化)方向で組みます。ビルドの前処理でアイキャッチをCMSから取得し、本番側の公開ディレクトリ(例:/og/{記事ID}.jpg)へ書き出して、og:imageと構造化データのimageをそのURLに差し替えます。
この方式を選ぶ理由は3つです。
- CMSは将来の置き換え候補である。画像URLをCMSに依存させると、乗り換えた瞬間に全記事のOGPが壊れます
- 本番ドメインからの配信のほうが自然で、ドメイン評価の面でも整合します
- CMS側の遮断を維持したまま、画像だけを見えるようにできます
あわせて、アイキャッチが無い記事の退避先も決めます。サイト共通の既定OGP画像を指すようにしておけば、メタ情報が空欄になることはありません。
—
6. 画像サイズは用途ごとに分ける(OGP用を本文に流用しない)
自己ホスト化するとき、「1種類作って使い回す」は失敗しやすい設計です。用途ごとに必要な形が違います。
| 用途 | サイズ | 形式・品質 | 理由 |
|---|---|---|---|
OGP(og:image・構造化データ) |
1200×630にクロップ | JPEG 品質82 | SNSと検索結果のカードは横長比率が決まっている |
| 記事本文・一覧のサムネイル | 原寸比を保ったまま幅1600px | JPEG 品質90 | クロップすると構図が変わる |
OGP用の1200×630を本文画像に流用してはいけません。これは元画像を横長に切り抜いた結果なので、本文に置くと構図が変わり見た目が別物になります。同じ元画像から用途ごとに別サイズで生成し直すのが正しい手順です。
サイズは表示枠の実寸から逆算する
「とりあえず大きめに」で決めると、無駄に重い画像を配信することになります。決め方は逆算です。
- 表示枠をブラウザの検証ツールで測る(例:一覧のサムネイル枠が横712px)
- 高解像度ディスプレイ用に2倍する(1424px)→ 切りのいい上限に丸める(1600px)
- 枠と元画像のアスペクト比を確認する(16:9の枠に対し元画像も約1.777ならクロップは発生しない)
この手順で幅1600px・品質90に揃えたところ、画像1枚あたりの平均が931KB→231KB(-75.1%)になりました。保存容量は増えますが、アイキャッチはファーストビューに入るためLCP(表示速度の評価指標)の対象になりやすい。読み込む画像が4分の1になる効果を優先しました。
—
7. 自動処理に入れておく安全弁
画像の変換とアップロードを自動化するときは、「失敗したときに何が起きるか」を先に決めておきます。無人で回すなら次の4つは入れておきます。
① アスペクト比が変わったら書き込まない
変換後の縦横比が元と0.01以上ずれたら例外を投げて止める。設定ミスで全画像が潰れる事故を公開前に止められます。
② 差分方式にする
取得元URLが同じで変換済みファイルがあるならスキップする。毎回全件を作り直すと、記事が増えるほどビルド時間が伸びます。
③ 画像処理の失敗でビルド全体を止めない
書き出しが失敗してもビルドは最後まで通します。画像マップが空なら既定のOGP画像へ退避する逃げ道があれば、全滅してもサイトは正常に公開されます。
④ 公開後に実データで検証する
これが最も重要です。投稿APIが200を返したことと、記事が完成したことは別です。公開直後にREST APIで記事をGETし直し、次を実測します。
statusがpublishになっているかfeatured_mediaが0以外の値になっているか- 記事ページの
og:imageのURLに実際にアクセスして、HTTP 200とimage/jpegが返るか
自動処理は中身が空振りしていても、ログ上は成功に見えます。終了コードではなく、出来上がったデータ側で健全性を見る——画像に限らず、自動化全般に共通する原則です。
—
8. 実装前チェックリスト
| 確認項目 | 判断基準 |
|---|---|
| 認証の疎通 | /wp/v2/users/me?context=editが200を返し、権限にupload_filesが含まれる |
| アップロードのヘッダー | Content-DispositionとContent-Typeの2つを送っている(multipartは不要) |
| MIMEタイプ | 拡張子から判定している(固定値でベタ書きしていない) |
| alt設定 | アップロード直後に/wp/v2/media/{id}へalt_textを送っている |
| 記事との紐付け | featured_mediaにIDの整数を渡している(URLではない) |
| 画像生成の入口 | 生成処理が1つの関数に集約され、全経路がそこを呼んでいる |
| 配信ドメイン | og:imageがクロール可能なドメインを指している |
| サイズ設計 | OGP用と本文用を別サイズで生成している |
| 公開後の検証 | REST GETでfeatured_mediaと画像URLの200を実測している |
—
まとめ
WordPress REST APIでのアイキャッチ設定は、/wp/v2/mediaへのバイナリPOST → alt_textの設定 → featured_mediaへの紐付けという3リクエストで完結します。実装の要点は、multipartではなくContent-DispositionとContent-Typeの2ヘッダーで送ること、代替テキストは別リクエストで入れることの2つだけです。
本番運用で効いてくるのは、実装の細部よりも設計の判断です。画像をどのドメインから配信するかを決めずにヘッドレス構成へ切り替えると、記事は正常に公開されているのに検索結果のサムネイルだけが記事数の分だけ一斉に空になります。目視では発見できず、実際にURLへアクセスして初めて分かります。
投稿を自動化するなら、公開して終わりにせず、公開後にREST APIで実データを取り直して検証する工程まで含めて1セットにしてください。「200が返った」は、記事が完成したことの証明にはなりません。
自社サイトの自動投稿やヘッドレス構成の設計でお困りの場合は、graciautoまでご相談ください。実際に運用している基盤をもとに、規模に合った構成をご提案します。