開発

Blog

開発

【WordPress】Yoast SEO の設定を管理画面ではなくコードで固定する方法

Yoast SEO を使っていると、タイトルの形式や構造化データの設定を管理画面でひとつずつ決めていくことになります。ローカルと本番で設定がずれたり、いつの間にか誰かが変えていたり、という経験がある人もいると思います。この記事では、Yoast SEO の設定を、管理画面ではなくテーマのコードで固定する方法を紹介します。

この記事でわかること
  • Yoast SEO の設定をコードで固定するメリット
  • option_{設定名} フィルターで設定を上書きする仕組み
  • 投稿タイプ・タクソノミーの分の設定を、定義から自動で作る方法
  • Yoast の設定キャッシュと、一覧ページのタイトルが変わらない落とし穴

なぜコードで固定するのか

Yoast SEO の設定は、管理画面で決めると WordPress のデータベースに保存されます。便利な反面、こんなことが起きがちです。

  • ローカルで決めた設定を、本番でもう一度同じように設定し直す必要がある
  • カスタム投稿タイプを増やすたびに、タイトルや説明文の形式を設定し忘れる
  • いつ・なぜその設定にしたのかが残らない

コードで固定すると、これがまとめて解決します。

観点コードで固定するメリット
環境差ローカルと本番で、同じコードから同じ設定になる
抜け漏れ投稿タイプ・タクソノミーの定義から設定を作るので、増やしたときに設定し忘れない
履歴Git で管理できるので、いつ・なぜ変えたかが残る
誤操作管理画面で変えても反映されないので、うっかり崩れない

ただし、固定するのはコードに書いた項目だけです。書いていない項目は、今までどおり管理画面で設定できます。運用する人が画面で調整したい項目は、あえてコードに書かずに残しておけます。

仕組み:option_{設定名} フィルターで上書きする

Yoast SEO の設定は、wp_options テーブルに wpseo_titles(タイトル・説明文の形式など)や wpseo_social(OGP など)という名前で、配列として保存されています。

WordPress には、オプションを読むときに値を差し替えられる option_{オプション名} というフィルターがあります。これを使って、Yoast が設定を読むたびに、コードに書いた値で上書きします。

foreach ( ore2nari_wpseo_fixed_options() as $ore2nari_option_name => $ore2nari_option_values ) {
	// 優先度 20:Yoast が初期値を足す処理(優先度 10)の後に上書きする
	add_filter( "option_{$ore2nari_option_name}", function ( $value ) use ( $ore2nari_option_values ) {
		return is_array( $value ) ? array_merge( $value, $ore2nari_option_values ) : $value;
	}, 20 );
}
unset( $ore2nari_option_name, $ore2nari_option_values );

array_merge() で、データベースの値の上にコードの値を重ねています。コードに書いていない項目は、データベースの値(管理画面で設定した値)がそのまま使われます。

優先度を 20 にしている理由

Yoast は、同じフィルターの優先度 10 で、足りない項目に初期値を足す処理をしています。それより後に上書きしないと、初期値で上書きし返されてしまうので、優先度を 20 にしています。

固定する値をひとつの関数にまとめる

固定する値は、ore2nari_wpseo_fixed_options() という関数に、設定名ごとにまとめています。一部を抜き出すとこんな形です。

function ore2nari_wpseo_fixed_options(): array {
	$titles = array(
		// タイトルの区切り文字(|)
		'separator'          => 'sc-pipe',

		// サイトの運営者(構造化データ):個人
		'company_or_person'  => 'person',

		// 使わないページ:Yoast がトップページなどへ転送し、サイトマップからも外す
		'disable-author'     => true, // 投稿者アーカイブ
		'disable-date'       => true, // 日付アーカイブ
		'disable-attachment' => true, // 添付ファイルのページ

		// 検索結果・404
		'title-search-wpseo' => '「%%searchphrase%%」の検索結果 %%page%% %%sep%% %%sitename%%',
		'title-404-wpseo'    => 'ページが見つかりません %%sep%% %%sitename%%',

		// RSS の記事の末尾に「The post ○○ appeared first on ○○」を付けない
		'rssafter'           => '',
	);

	// …投稿タイプ・タクソノミーの分は下で足す

	return array(
		'wpseo_titles' => $titles,
		'wpseo_social' => $social,
	);
}

キーの名前は、Yoast がデータベースに保存しているものと同じです。どのキーが何の設定かは、管理画面で設定を変えて保存し、データベースの値を見比べるとわかります。

キーの調べ方

WP-CLI なら wp option get wpseo_titles --format=json で、今の設定を全部見られます。管理画面で1つ変えて保存し、もう一度見ると、どのキーが変わったかがわかります。

投稿タイプ・タクソノミーの分は、定義から自動で作る

カスタム投稿タイプごとに「詳細ページのタイトル」「一覧ページのタイトル」「説明文」などの設定があります。これを1つずつ書くと、投稿タイプを増やしたときに書き忘れます。

そこで、投稿タイプを登録している関数 ore2nari_post_types() から、設定を自動で作るようにしています。

	foreach ( ore2nari_post_types() as $post_type ) {
		$slug     = $post_type['slug'];
		$settings = ( $post_type_settings[ $slug ] ?? array() ) + array(
			'article_type' => 'None',
			'metadesc'     => '%%excerpt%%',
		);

		$titles += array(
			"title-{$slug}"               => '%%title%% %%page%% %%sep%% %%sitename%%',
			"metadesc-{$slug}"            => $settings['metadesc'],
			"schema-page-type-{$slug}"    => 'WebPage',
			"schema-article-type-{$slug}" => $settings['article_type'],
			"title-ptarchive-{$slug}"     => '%%pt_plural%% %%page%% %%sep%% %%sitename%%',
			"metadesc-ptarchive-{$slug}"  => '%%sitename%%の%%pt_plural%%の一覧です。',
		);
	}

投稿タイプごとに変えたいものだけ、別の配列に書いています。たとえばブログは、構造化データの記事の種類を BlogPosting にしています。タクソノミー(カテゴリーやタグの一覧ページ)も、同じようにタクソノミーの定義から作っています。

落とし穴1:Yoast は先に設定を読んで覚えている

フィルターを登録しただけでは、うまく効かないことがあります。Yoast は、プラグインを読み込んだ時点(テーマより先)で設定を読み、WPSEO_Options の中に覚えているからです。

テーマでフィルターを登録したあとに、覚えている値を捨てて読み直させます。

// Yoast はプラグインの読み込み時(テーマより先)に設定を読んで覚えているので、覚えた値を捨てて読み直させる
if ( class_exists( 'WPSEO_Options' ) ) {
	WPSEO_Options::clear_cache();
}

class_exists() で確かめているので、Yoast を止めていてもエラーにはなりません。

落とし穴2:一覧ページのタイトルが変わらない

もう1つ気をつけたいのがこれです。コードの設定を変えたのに、投稿タイプの一覧ページや検索結果、404 のタイトルだけが古いまま、ということが起きます。

原因は、Yoast の yoast_indexable というテーブルです。Yoast は、一覧ページなどのタイトルの形式を、最初に表示したときにこのテーブルへ保存し、以後はそれを使います。管理画面で設定を保存したときは作り直されますが、コードで変えたときは作り直されません。

そこで、コードの設定が変わったときだけ、該当する行を消して作り直させます。

add_action( 'init', function () {
	if ( ! class_exists( 'WPSEO_Options' ) ) {
		return;
	}

	$hash = md5( wp_json_encode( ore2nari_wpseo_fixed_options() ) );
	if ( get_option( 'ore2nari_wpseo_options_hash' ) === $hash ) {
		return;
	}

	global $wpdb;
	$wpdb->query( "DELETE FROM {$wpdb->prefix}yoast_indexable WHERE object_type IN ( 'post-type-archive', 'system-page', 'home-page', 'date-archive' )" );
	update_option( 'ore2nari_wpseo_options_hash', $hash, true );
}, 99 );
設定のハッシュを作る

固定する値をまとめて JSON にし、md5 でハッシュにします。

前回と同じなら何もしない

オプションに保存した前回のハッシュと同じなら、そこで終わります。毎回のページ表示で DB を消すことはありません。

変わっていたら行を消す

一覧ページ・検索結果や404・トップページ・日付アーカイブの行を消します。次に表示したときに、今の設定で自動で作り直されます。

「設定のハッシュを保存して、変わったときだけ処理する」形は、カスタムタクソノミーの初期タームの登録やパーマリンクの更新でも使っている書き方です。ひとつ覚えておくと、いろいろなところで使い回せます。

管理画面にも「固定している」と表示する

コードで固定した項目は、管理画面の Yoast の設定画面にも表示されますが、画面で変えても反映されません。知らない人が触ると混乱するので、admin_notices で設定画面に「テーマで固定しています」と表示するようにしています。

無料版では使えない項目もある

ソーシャル用のタイトル・説明文の形式(social-title など)は Yoast SEO Premium の機能なので、無料版ではコードに書いても使われません。

よくある疑問

管理画面で設定を変えるとどうなりますか?

コードに書いた項目は、画面上は変わったように見えても反映されません。コードに書いていない項目は、管理画面の設定がそのまま使われます。

Yoast SEO を止めたら、エラーになりませんか?

なりません。オプションのフィルターは、Yoast がなければ呼ばれないだけです。Yoast のクラスを使うところは class_exists() で確かめています。

Yoast SEO を更新したあとに気をつけることは?

キーの名前は Yoast の内部の値なので、大きな更新のあとは、設定画面と実際のページのタイトルや構造化データを一度確かめておくと安心です。

おわりに

Yoast SEO の設定は、一度決めたらあまり変えないわりに、項目が多くて抜け漏れが起きやすいところです。だからこそ、コードに書いて Git で管理しておくと安心だなと感じています。2つの落とし穴はなかなか気づきにくいところなので、同じところでハマっている人の参考になればうれしいです。

SEO プラグインの設定も、「コードで持てないかな?」と一度考えてみると、運用がぐっと楽になりますよ。

お仕事のご相談

WordPress の SEO まわりの設定や改修のような制作・改修のご相談も受け付けています。お気軽にどうぞ。

//サイト内を検索

制作実績・ブログ・お知らせから探します。キーワードはスペースで区切って複数入れられます。