
「表示は多いのにクリックされない記事のタイトルを、10本まとめて直したい」「フォームの完了ページを、全部 noindex にしたい」。WordPressの管理画面でやると、1ページずつ編集画面を開いて、SEOの設定欄を探して、保存して……のくり返しになります。
WordPressには、外からプログラムで記事や設定を読み書きできる REST API という仕組みがあります。アプリケーションパスワードでログインし、REST APIでSEOプラグインの設定を書き換える と、何十ページ分の変更でも、内容を1つのファイルにまとめて、一度に反映できます。
この記事では、Cruwが自社サイトで実際に、記事・固定ページのSEOタイトルと説明文の見直しや、サンクスページの noindex 化に使った方法を、Pythonのコードとあわせて紹介します。SEOプラグインは All in One SEO(AIOSEO) の例です。
- アプリケーションパスワードの発行と、REST APIへの接続のしかた
- SEOタイトル・説明文を、ファイルに書いた内容でまとめて変更するコード
- noindex を変えるときに、ほかの設定を消してしまわない ための注意点と、元に戻す仕組み
結論:アプリケーションパスワードで接続し、「取得 → 書き換え → 確認」の順で更新する
全体の流れは、次のとおりです。
- WordPressのユーザー画面で、アプリケーションパスワード を発行する
- 接続情報を
.envファイルに書き、REST APIにつながるか確かめる - 変更したい内容(スラッグ・タイトル・説明文)を、1つのJSONファイルにまとめる
- スクリプトで、スラッグから投稿IDを探し、SEOプラグインのAPIに送って更新する
- 変更前の値を保存しておき、おかしければすぐに元に戻す
大事なのは5番目です。プログラムでの一括変更は、うまくいけば一瞬ですが、間違えたときも一瞬で全ページに広がります。Cruwでは、変更前の設定を必ずファイルに残し、1つのコマンドで元に戻せるようにしてから本番に反映しています。
管理画面で1ページずつ直す方法との違い
| 管理画面で1ページずつ | REST APIでまとめて | |
|---|---|---|
| 10ページ以上の変更 | 時間がかかり、直し忘れが出やすい | 1つのファイルにまとめて一度に反映 |
| 変更内容の確認 | ページごとに開いて確かめる | ファイルを見れば全体がわかる。事前にほかの人に見てもらえる |
| 元に戻す | 前の文章を覚えていないと戻せない | 変更前の値を保存しておけば、コマンド1つで戻せる |
| 準備 | 不要 | アプリケーションパスワードの発行と、少しのプログラム |
数ページだけなら、管理画面で直すほうが早くて安全です。直したいページが多いとき、サーチコンソールの数字を見ながら、タイトルを何度も見直したいとき に、この方法が役に立ちます。
Cruwでは2026年9月に、サーチコンソールで「表示回数は多いのに、クリック率が低い」記事7本と、会社概要・ホームページ制作・トップページのタイトルと説明文を見直しました。あわせて、お問い合わせ・お見積もりなどのフォームのサンクスページ(送信完了のページ)を noindex にしています。
手順1:アプリケーションパスワードを発行する
アプリケーションパスワード は、プログラムや外部のツールからWordPressにログインするための、専用のパスワードです。WordPress 5.6 から標準で使えます。ふだんのログインパスワードとは別のもので、用途ごとに発行し、いらなくなったら、そのパスワードだけを取り消せます。
- WordPressの管理画面で「ユーザー」→「プロフィール」を開く
- 下のほうにある「アプリケーションパスワード」に、わかりやすい名前(例:
seo-script)を入れて「新しいアプリケーションパスワードを追加」を押す - 表示された24文字のパスワードを控える(この画面を閉じると二度と表示されません)
発行するときは、次の点に気をつけましょう。
- サイトがHTTPS(https://)であること:アプリケーションパスワードは、通信が暗号化されたサイトでないと使えません
- 権限に合ったユーザーで発行する:パスワードには、そのユーザーと同じ権限が付きます。SEOプラグインの設定を変えるなら、管理者か、SEOの設定を任されたユーザーで発行します
- パスワードをGitやチャットに貼らない:Cruwでは、接続情報をテーマ直下の
.envファイルに書き、.gitignoreで Git の管理から外しています
# .env(Gitには入れない)
WP_BASE_URL=https://example.com
WP_USERNAME=your-user
WP_APP_PASSWORD="abcd efgh ijkl mnop qrst uvwx"手順2:REST APIにつながるか確かめる
まず、ログインできているかを確かめます。ターミナルで、次のコマンドを実行してみましょう。
curl -s -u 'your-user' \
'https://example.com/wp-json/wp/v2/users/me?context=edit' | head -c 300-u にユーザー名だけを書くと、実行したときにパスワードを聞かれるので、アプリケーションパスワードを入力します。-u 'ユーザー名:パスワード' のようにコマンドへ直接書くと、ターミナルの履歴にパスワードが残ってしまうので避けましょう。
自分のユーザー名やIDが返ってくれば、接続できています。401 や rest_not_logged_in が返るときは、後半の「うまくいかないときに確認したいこと」を見てください。
続けて、Pythonから呼び出すための小さな関数を用意します。Cruwで使っているものを、短くした形です(標準ライブラリだけで動きます)。このあとのコードは、すべてこの wp_api.py と同じフォルダに置き、.env もこのフォルダに置く前提です。
# wp_api.py
import base64
import json
import os
import urllib.request
HERE = os.path.dirname(os.path.abspath(__file__))
BACKUP_DIR = os.path.join(HERE, 'backup')
def load_env():
""".env の「キー=値」を読み込む"""
env = {}
with open(os.path.join(HERE, '.env'), encoding='utf-8') as f:
for line in f:
line = line.strip()
if line and not line.startswith('#') and '=' in line:
k, v = line.split('=', 1)
env[k.strip()] = v.strip().strip('"').strip("'")
return env
ENV = load_env()
TOKEN = base64.b64encode(
f"{ENV['WP_USERNAME']}:{ENV['WP_APP_PASSWORD']}".encode()).decode()
def request(method, path, data=None):
req = urllib.request.Request(
ENV['WP_BASE_URL'].rstrip('/') + path,
data=json.dumps(data).encode() if data is not None else None,
method=method,
headers={
'Authorization': 'Basic ' + TOKEN, # アプリケーションパスワードで認証
'Content-Type': 'application/json',
})
with urllib.request.urlopen(req, timeout=60) as res:
return json.loads(res.read() or 'null')
def get(path):
return request('GET', path)
def post(path, data):
return request('POST', path, data)
def save_backup(name, data):
"""変更前の値を backup/ に保存する。すでにあれば上書きしない(最初の状態を残す)"""
os.makedirs(BACKUP_DIR, exist_ok=True)
path = os.path.join(BACKUP_DIR, name)
if not os.path.exists(path):
with open(path, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)アプリケーションパスワードは、「ユーザー名:パスワード」をBase64という形式に変えて、Authorization ヘッダーに付けて送るだけで使えます。
手順3:SEOタイトルと説明文をまとめて変更する
変更したい内容を1つのファイルにまとめる
変更したい記事のスラッグ(URLの末尾の部分)と、新しいタイトル・説明文を、JSONファイルに書きます。Cruwが実際に使ったファイルから、一部を抜き出したものです。
{
"posts": {
"css-counter": {
"title": "CSS counterで連番・ナンバリングを自動出力する方法|Cruw",
"description": "CSSの counter(カウンター)を使えば、見出しやリストに連番を自動で付けられます。数字だけでなくアルファベット・ひらがな・漢数字、「第1位」のような文字との組み合わせ方も紹介します。"
},
"font-awesome": {
"title": "Font Awesomeが表示されない・四角くなる原因と対処法4選|Cruw",
"description": "Font Awesomeのアイコンが表示されない、四角(□)に文字化けする主な4つの原因と対処法を紹介。CDNの読み込み方やPro版との違いなど、よくあるつまずきをまとめて確認できます。"
}
},
"pages": {
"company": {
"title": "会社概要|株式会社Cruw(クルー)長野県上田市のWeb制作会社",
"description": "株式会社Cruw(クルー/Cruw Inc.)の会社概要。長野県上田市を拠点に、ホームページ制作・Webマーケティング・AI/システム開発で地域企業の成長を支援しています。"
}
}
}ファイルにまとめておくと、反映する前に、変更内容の全体を見直せます。文字数のチェックや、ほかの人への確認もしやすくなります。
スラッグから投稿IDを探して、AIOSEOに送る
WordPress標準のREST APIで、スラッグから投稿IDを探します。記事は /wp/v2/posts、固定ページは /wp/v2/pages です。そのIDを、All in One SEO のAPIに送って、タイトルと説明文を変更します。
# apply.py
import json
from wp_api import get, post
changes = json.load(open('changes.json', encoding='utf-8'))
for kind in ('posts', 'pages'):
for slug, c in changes[kind].items():
# スラッグから投稿IDを探す
pid = get(f'/wp-json/wp/v2/{kind}?slug={slug}&_fields=id')[0]['id']
# AIOSEO のSEOタイトル・説明文を変更する
r = post('/wp-json/aioseo/v1/posts-list/update-details-column', {
'postId': pid,
'title': c['title'],
'description': c['description'],
})
print(f'[{slug}] success={r.get("success")}')/aioseo/v1/posts-list/update-details-column は、AIOSEOの管理画面の「投稿一覧」で、タイトルと説明文をその場で編集するときに使われている仕組みです。送るのはタイトルと説明文だけで、Cruwで使ったときも、ほかの設定(noindex など)は変わりませんでした。念のため、実行の前後で、1ページ分の設定を取得して見比べておくと安心です。
トップページを固定ページにしている場合は、/wp-json/wp/v2/settings の page_on_front で、そのページのIDがわかります。Cruwでは、トップページもこの方法で変更しました。
なお、AIOSEOのAPIは、プラグインが管理画面のために用意しているもので、WordPress本体のように仕様が公開・保証されているものではありません。プラグインの更新で変わることもあるので、使う前に、1ページだけで試してから まとめて実行しましょう。
手順4:noindex は「ほかの設定を消さない」ように変更する
タイトル・説明文と違い、noindex(検索結果に出さない設定)などのページごとの設定は、AIOSEOの別のAPI(/aioseo/v1/post)で保存します。ここに、気をつけたい点があります。
このAPIは、送った内容で、そのページのSEO設定をまるごと保存します。 noindex だけを送ると、送らなかったタイトルや説明文などの項目まで、空や初期値で上書きされるおそれがあります。
そこでCruwでは、次の順で更新するようにしています。
- 今の設定を すべて 取得する
- 変更前の設定を、ファイルに保存する(元に戻すため)
- 変えたい項目だけを書き換えて、全部を送り返す
- もう一度取得して、変更前と比べる
- 変えた項目 以外 が変わっていたら、変更前の設定に自動で戻して止める
# aioseo_post.py
from wp_api import get, post, save_backup
# 取得結果にだけある表示用の項目(比べるときに外す)
IGNORE = {'loading', 'modalOpen', 'redirects', 'linkAssistant', 'metaDefaults',
'options', 'editlink', 'permalink', 'seo_score', 'page_analysis'}
def current(post_id):
return get(f'/wp-json/aioseo/v1/post?postId={post_id}')['data']['currentPost']
def update(post_id, changes, label):
before = current(post_id) # 1. 今の設定をすべて取得
save_backup(f'aioseo_{post_id}_before.json', before) # 2. 変更前を保存(最初の1回だけ)
payload = dict(before, **changes) # 3. 変えたい項目だけ書き換え
payload['id'] = int(post_id)
res = post('/wp-json/aioseo/v1/post', payload) # 全部を送り返す
if not res.get('success'):
raise RuntimeError(f'{label}: 更新に失敗しました {res}')
after = current(post_id) # 4. もう一度取得して比べる
unexpected = {k for k in set(before) | set(after)
if k not in IGNORE and k not in changes
and before.get(k) != after.get(k)}
if unexpected: # 5. 想定外の変化 → 元に戻す
post('/wp-json/aioseo/v1/post', dict(before, id=int(post_id)))
raise RuntimeError(f'{label}: 想定外の項目が変わったため元に戻しました {sorted(unexpected)}')noindex にするときは、次のように呼び出します。AIOSEOでは、ページごとの設定を使うために default(初期設定を使う)を False にしたうえで、noindex を True にします。
update(page_id, {'default': False, 'noindex': True}, '/contact/thanks/')Cruwのサイトでは、/contact/thanks/ /estimate/thanks/ などのサンクスページを、この方法で noindex にしました。スクリプトは、何も指定しないと「どのページを変えるか」を表示するだけで、--apply を付けたときだけ実際に変更するようにしています。サンクスページを noindex にする理由は、サンクスページはnoindexにすべき?で紹介しています。
変更前の値を残して、すぐに元に戻せるようにする
一括変更で一番こわいのは、「前のタイトルが何だったか、わからなくなる」ことです。Cruwでは、どのスクリプトも、次のルールで作っています。
- 変更前の値を、最初の1回だけ保存する:同じスクリプトを2回実行しても、最初の状態が上書きされないようにする
--revertで元に戻せる:保存した変更前の値を、そのまま送り返すだけで戻せるようにする- 保存したファイルもGitに入れない:変更前の設定には、公開前の情報が含まれることもあるため、
.gitignoreで外しておく
save_backup は、手順2の wp_api.py のとおり、ファイルがすでにあれば上書きしません。元に戻すときは、保存しておいた変更前の設定を、そのまま送り返します。
# aioseo_post.py に追加
import json
import os
from wp_api import BACKUP_DIR
def revert(post_id, label):
path = os.path.join(BACKUP_DIR, f'aioseo_{post_id}_before.json')
before = json.load(open(path, encoding='utf-8'))
post('/wp-json/aioseo/v1/post', dict(before, id=int(post_id)))
print(f'[{label}] 元に戻しました')タイトルを変えたあとは、サーチコンソールで、数週間ほどクリック率や順位の変化を見ます。思ったような結果が出なかったときも、変更前に戻したり、別の案を試したりしやすくなります。
うまくいかないときに確認したいこと
| 症状 | 確認したいこと |
|---|---|
401 や rest_not_logged_in が返る | ユーザー名とアプリケーションパスワードが正しいか。セキュリティ系のプラグインで、アプリケーションパスワードやREST APIが止められていないか。サーバーの設定で Authorization ヘッダーが届いていないこともある |
403 や rest_forbidden が返る | 発行したユーザーに、その操作をする権限があるか(SEOの設定は、管理者などの権限が必要なことが多い) |
404 や rest_no_route が返る | URLのつづり、プラグインが有効になっているか。AIOSEOのバージョンによって、APIの場所が違うこともある |
| 実行は成功したのに、表示が変わらない | キャッシュ系のプラグインやサーバーのキャッシュが残っていないか。ページのソースで <title> を確認する |
| 下書きの記事が見つからない | /wp/v2/posts?slug=... は、何も指定しないと公開済みの記事だけを返す。下書きも探すときは status=draft と context=edit を付ける |
よくある質問
Yoast SEO など、ほかのSEOプラグインでもできますか?
考え方は同じです。WordPressのREST APIで投稿IDを探し、そのプラグインがSEOの設定を保存している場所を更新します。ただ、保存のしかたはプラグインごとに違うため、まず1ページの設定を取得して中身を確かめ、1ページだけで試してから進めましょう。
プログラムが書けなくても使えますか?
アプリケーションパスワードの発行は管理画面でできますが、まとめて変更する部分は、プログラムを動かす必要があります。変更するページが数ページなら、管理画面で1ページずつ直すほうが安心です。ページ数が多いときや、定期的に見直したいときは、Cruwにご相談ください。
アプリケーションパスワードが漏れたら、どうすればいいですか?
「ユーザー」→「プロフィール」のアプリケーションパスワードの一覧から、そのパスワードだけを「取り消し」ます。ふだんのログインパスワードや、ほかのアプリケーションパスワードには影響しません。作業が終わって使わなくなったパスワードも、取り消しておくと安心です。
まとめ
- アプリケーションパスワードを使うと、WordPressのREST APIに安全にログインして、SEOタイトル・説明文・noindex をまとめて変更できます
- タイトルと説明文は、変えたい内容を1つのファイルにまとめ、スラッグから投稿IDを探してAIOSEOのAPIに送ります
- noindex などの設定は、保存のときにほかの項目まで上書きされることがあるため、「すべて取得 → 変えたい項目だけ書き換え → 全部送り返す → 確認」の順で更新し、変更前の値を残して元に戻せるようにしておきましょう
タイトルや説明文の見直しは、ホームページを「作ったら終わり」にせず、育てていくための地道な作業のひとつです。サーチコンソールを見ながらの改善を続けたい方には、月額定額のサイト改善おまかせパックもご用意しています。「どのページから直せばいいかわからない」「SEOの設定をまとめて見直してほしい」といったご相談は、集客サポート・SEOをご覧のうえ、お問い合わせからお気軽にご相談ください。







