19.セレクトボックスのSEO化



当サイトでは、セレクトボックスを選択して、各都道府県の天気予報を表示しています。

以前の場合、セレクトボックスで都道府県を選択して表示しても、URLは https://rainboweather.info/ のままでした。

そこでSEO対策として、三重県を選択した場合、URLを https://rainboweather.info/mie/ とすることで、

Googleコンソールに三重県の天気予報のページとして、登録することが可能になり、

「三重県 天気」で検索すると、そのページがヒットするようになります。

19-1.全国都道府県のデータ

全国都道府県のデータを下記に示します。

<?php
    $json3 = '{
        "01": {
            "code": "011000",
            "name": "北海道宗谷地方",
            "roma": "hokkaidosoya"
        },
        "02": {
            "code": "012000",
            "name": "北海道上川・留萌地方",
            "roma": "hokkaidokamikawarumoi"
        },
        "03": {
            "code": "013000",
            "name": "北海道網走・北見・紋別地方",
            "roma": "hokkaidoabashirikitamimonbetu"
        },
        "04": {
            "code": "014100",
            "name": "北海道釧路・根室地方",
            "roma": "hokkaidokushironemuro"
        },
        "05": {
            "code": "015000",
            "name": "北海道胆振・日高地方",
            "roma": "hokkaidoiburihidaka"
        },
        "06": {
            "code": "016000",
            "name": "北海道石狩・空知・後志地方",
            "roma": "hokkaidoishikarisorachishiribeshi"
        },
        "07": {
            "code": "017000",
            "name": "北海道渡島・檜山地方",
            "roma": "hokkaidooshimahiyama"
        },
        "08": {
            "code": "020000",
            "name": "青森県",
            "roma": "aomori"
        },
        "09": {
            "code": "030000",
            "name": "岩手県",
            "roma": "iwate"
        },
        "10": {
            "code": "040000",
            "name": "宮城県",
            "roma": "miyagi"
        },
        "11": {
            "code": "050000",
            "name": "秋田県",
            "roma": "akita"
        },
        "12": {
            "code": "060000",
            "name": "山形県",
            "roma": "yamagata"
        },
        "13": {
            "code": "070000",
            "name": "福島県",
            "roma": "fukushima"
        },
        "14": {
            "code": "080000",
            "name": "茨城県",
            "roma": "ibaraki"
        },
        "15": {
            "code": "090000",
            "name": "栃木県",
            "roma": "tochigi"
        },
        "16": {
            "code": "100000",
            "name": "群馬県",
            "roma": "gunma"
        },
        "17": {
            "code": "110000",
            "name": "埼玉県",
            "roma": "saitama"
        },
        "18": {
            "code": "120000",
            "name": "千葉県",
            "roma": "chiba"
        },
        "19": {
            "code": "130000",
            "name": "東京都",
            "roma": "tokyo"
        },
        "20": {
            "code": "140000",
            "name": "神奈川県",
            "roma": "kanagawa"
        },
        "21": {
            "code": "150000",
            "name": "新潟県",
            "roma": "niigata"
        },
        "22": {
            "code": "160000",
            "name": "富山県",
            "roma": "toyama"
        },
        "23": {
            "code": "170000",
            "name": "石川県",
            "roma": "ishikawa"
        },
        "24": {
            "code": "180000",
            "name": "福井県",
            "roma": "fukui"
        },
        "25": {
            "code": "190000",
            "name": "山梨県",
            "roma": "yamanashi"
        },
        "26": {
            "code": "200000",
            "name": "長野県",
            "roma": "nagano"
        },
        "27": {
            "code": "210000",
            "name": "岐阜県",
            "roma": "gihu"
        },
        "28": {
            "code": "220000",
            "name": "静岡県",
            "roma": "shizuoka"
        },
        "29": {
            "code": "230000",
            "name": "愛知県",
            "roma": "aichi"
        },
        "30": {
            "code": "240000",
            "name": "三重県",
            "roma": "mie"
        },
        "31": {
            "code": "250000",
            "name": "滋賀県",
            "roma": "shiga"
        },
        "32": {
            "code": "260000",
            "name": "京都府",
            "roma": "kyoto"
        },
        "33": {
            "code": "270000",
            "name": "大阪府",
            "roma": "osaka"
        },
        "34": {
            "code": "280000",
            "name": "兵庫県",
            "roma": "hyogo"
        },
        "35": {
            "code": "290000",
            "name": "奈良県",
            "roma": "nara"
        },
        "36": {
            "code": "300000",
            "name": "和歌山県",
            "roma": "wakayama"
        },
        "37": {
            "code": "310000",
            "name": "鳥取県",
            "roma": "tottori"
        },
        "38": {
            "code": "320000",
            "name": "島根県",
            "roma": "shimane"
        },
        "39": {
            "code": "330000",
            "name": "岡山県",
            "roma": "okayama"
        },
        "40": {
            "code": "340000",
            "name": "広島県",
            "roma": "hiroshima"
        },
        "41": {
            "code": "350000",
            "name": "山口県",
            "roma": "yamaguchi"
        },
        "42": {
            "code": "360000",
            "name": "徳島県",
            "roma": "tokushima"
        },
        "43": {
            "code": "370000",
            "name": "香川県",
            "roma": "kagawa"
        },
        "44": {
            "code": "380000",
            "name": "愛媛県",
            "roma": "ehime"
        },
        "45": {
            "code": "390000",
            "name": "高知県",
            "roma": "kochi"
        },
        "46": {
            "code": "400000",
            "name": "福岡県",
            "roma": "fukuoka"
        },
        "47": {
            "code": "410000",
            "name": "佐賀県",
            "roma": "saga"
        },
        "48": {
            "code": "420000",
            "name": "長崎県",
            "roma": "nagasaki"
        },
        "49": {
            "code": "430000",
            "name": "熊本県",
            "roma": "kumamoto"
        },
        "50": {
            "code": "440000",
            "name": "大分県",
            "roma": "oita"
        },
        "51": {
            "code": "450000",
            "name": "宮崎県",
            "roma": "miyazaki"
        },
        "52": {
            "code": "460100",
            "name": "鹿児島県",
            "roma": "kagoshima"
        },
        "53": {
            "code": "471000",
            "name": "沖縄県本島地方",
            "roma": "okinawa"
        },
        "54": {
            "code": "472000",
            "name": "沖縄県大東島地方",
            "roma": "okinawadaito"
        },
        "55": {
            "code": "473000",
            "name": "沖縄県宮古島地方",
            "roma": "okinawamiyako"
        },
        "56": {
            "code": "474000",
            "name": "沖縄県石垣島地方",
            "roma": "okinawaishigaki"
        }
    }';
?>

このデータを、prefec.phpとして、セレクトボックスに利用します。



19-2.セレクトボックスの作成の仕方

都道府県のデータを読み込んで、セレクトボックスを作成するコードは下記になります。

<?php
	// 都道府県コードの読み込み
	require get_stylesheet_directory() . '/prefec.php';  
	$array = json_decode($json3, true);

	/* ==============================
   		URL /tokyo などをPOSTに変換
   	============================== */

	$roma = get_query_var('roma');

	$pref_name = '';
	if($roma){

    	foreach ($array as $value){

        	if(strtolower($value["roma"]) == strtolower($roma)){

            	$pref_name = $value["name"];

        	}
	    }
	}
	
	if($roma){

    	$roma = strtolower($roma);

    	foreach ($array as $key => $value){

        	if(strtolower($value["roma"]) == $roma){

            	$_POST["prefecture"] = $value["code"];

        	}

    	}

	}

	echo '<form id="myForm" action="'.home_url().'" method="POST">';

	// セレクトボックスの作成
	$prefecture = '';
	foreach ($array as $key => $value) {
  		if (isset($_POST["prefecture"]) && $_POST['prefecture'] == $value['code']) {
    		$prefecture .= '<option value="'.$value['code'].'" data-roma="'.$value['roma'].'" selected>'.$value['name'].'</option>';
  		} else {
    		$prefecture .= '<option value="'.$value['code'].'" data-roma="'.$value['roma'].'">'.$value['name'].'</option>';
  		}  
	}
	?>
	<select name='prefecture' onchange="changePref(this);">
  		<option value="" disabled style="display:none;" <?php if(empty($_POST['prefecture'])) echo 'selected'; ?>>都道府県を選択してください</option>
  		<?php echo $prefecture; ?>
	</select>
	<?php
	echo '</form>';
        echo "<p class='text-center'>※上のセレクトボックスで都道府県を選択すると、全国各地域の天気予報が表示されます。</p>";
?>

このPHPコードは、URLのローマ字都道府県(例 /tokyo)を読み取り、POSTデータに変換して、セレクトボックスと連動させる仕組みです。

WordPressでよくある 「SEO用URL + セレクトボックス連動」 の構造になっています。

私の天気サイトの構造から考えると、

  • /tokyo → 東京の天気
  • /osaka → 大阪の天気

のような SEO用URLから都道府県を自動選択する仕組みです。

順番にかなり詳しく解説します。


① 都道府県データを読み込む

require get_stylesheet_directory() . '/prefec.php';  
$array = json_decode($json3, true);

ここでやっていること

  1. prefec.php を読み込む
  2. JSONデータを配列に変換

prefec.phpのイメージ

$json3 = '[
{ "code":"130000", "name":"東京都", "roma":"tokyo" },
{ "code":"270000", "name":"大阪府", "roma":"osaka" }
]';

それを

$array = json_decode($json3, true);

PHP配列に変換

結果

$array = [
["code"=>"130000","name"=>"東京都","roma"=>"tokyo"],
["code"=>"270000","name"=>"大阪府","roma"=>"osaka"]
];

② URLの都道府県を取得

$roma = get_query_var('roma');

これは WordPressのカスタムURL取得です。

例えばURL

https://rainboweather.info/tokyo

Rewrite設定で

roma = tokyo

が取得されます。

結果

$roma = "tokyo"

③ URLから都道府県名を取得

$pref_name = '';if($roma){    foreach ($array as $value){        if(strtolower($value["roma"]) == strtolower($roma)){ 
$pref_name = $value["name"]; }
}
}

やっていること

URLの tokyo

配列の

roma

と比較して

一致する都道府県を探します。

tokyo = tokyo

一致すると

$pref_name = 東京都

になります。

strtolower()

小文字化

Tokyo
TOKYO
tokyo

全部同じ扱いにするため。


④ URL → POSTデータへ変換

ここがこのコードの核心部分です。

if($roma){
$roma = strtolower($roma);
foreach ($array as $key => $value){
if(strtolower($value["roma"]) == $roma){
$_POST["prefecture"] = $value["code"];
}
}}

何をしているのか

URL

/tokyo

POSTデータ

$_POST["prefecture"] = 130000

に変換しています。

つまり

URLPOST
tokyo130000
osaka270000

になります。


なぜこんなことをするのか

私の天気サイトの仕組みは

都道府県コードで天気を取得している

例えば

130000 → 東京
270000 → 大阪

だから

URL

/tokyo

130000

に変換する必要があります。



⑤ フォームを作成

echo '<form id="myForm" action="'.home_url().'" method="POST">';

フォーム作成

<form action="トップページ" method="POST">

⑥ セレクトボックスを作る

foreach ($array as $key => $value) {

都道府県を全部ループ。


選択済み判定

if (isset($_POST["prefecture"]) && $_POST['prefecture'] == $value['code'])

もし

$_POST["prefecture"] = 130000

なら

東京都

selected

にします。


生成されるHTML

<option value="130000" data-roma="tokyo" selected>東京都</option>
<option value="270000" data-roma="osaka">大阪府</option>

⑦ セレクトボックス表示

<select name='prefecture' onchange="changePref(this);">

ユーザーが選択すると

changePref()

というJavaScriptが動きます。

⑦-1 changePref()関数

<script>

	function changePref(obj){
	let roma = obj.options[obj.selectedIndex].getAttribute("data-roma");

	if(roma){
		location.href = "/" + roma;
	}
	}

</script>

このJavaScriptは、セレクトボックスで都道府県を選ぶと、その都道府県のURLへ移動する処理です。
あなたのPHPコードと完全に連動している部分です。

つまり

セレクトボックス

JavaScript

URL /tokyo に移動

PHPが解析

東京の天気表示

という流れです。

では1行ずつ詳しく説明します。


⑦-2 <script>

<script>

これは JavaScriptを書く場所です。

ブラウザに

「これからJavaScriptを実行します」

と伝えています。


⑦-3 関数の定義

function changePref(obj){

これは changePrefという関数を作っています

意味

changePref(何か)

この 何かobj です。

今回の obj

セレクトボックス自身です。

なぜかというと、PHP側で

<select name='prefecture' onchange="changePref(this);">

となっているからです。

this

このセレクトボックス

を意味します。

つまり

changePref(セレクトボックス)

になります。


⑦-4 選択されたoptionを取得

let roma = obj.options[obj.selectedIndex].getAttribute("data-roma");

ここが一番重要な部分です。

順番に分解します。


① obj.options

obj.options

これは

セレクトボックスの全option

<option value="130000" data-roma="tokyo">東京都</option>
<option value="270000" data-roma="osaka">大阪府</option>

② obj.selectedIndex

これは

選択されている番号

東京都 → 0
大阪府 → 1

③ obj.options[obj.selectedIndex]

つまり

現在選択されているoption

を取得しています。


④ getAttribute(“data-roma”)

optionには

data-roma="tokyo"

というカスタム属性があります。

<option value="130000" data-roma="tokyo">東京都</option>

ここから

tokyo

を取り出しています。


⑤ 最終結果

let roma = "tokyo"

になります。



④ romaが存在するか確認

if(roma){

これは

romaが空じゃなければ

という意味です。

つまり

tokyo
osaka

などが入っている場合。


⑤ URLへ移動

location.href = "/" + roma;

これは

ページを移動する命令です。

roma = tokyo

なら

/tokyo

へ移動。

実際には

https://rainboweather.info/tokyo

になります。


⑥ 関数終了

}

これで関数が終わります。


このコードの全体の流れ

ユーザー操作

セレクトボックス

大阪府選択

JavaScript

data-roma取得

osaka

URL変更

/osaka

WordPress

get_query_var('roma')

osaka

PHP

$_POST["prefecture"]=270000

天気表示

大阪の天気

大阪の天気が表示されます。


⑧ 最初の案内文

<p class='text-center'>
※上のセレクトボックスで都道府県を選択すると、全国各地域の天気予報が表示されます。
</p>

ユーザー説明。


このコードの全体構造

URL

/tokyoWordPress

get_query_var('roma')roma = tokyo↓
prefec.php照合tokyo → code 130000↓
POST変換$_POST["prefecture"]=130000↓
セレクトボックス東京都 selected↓
天気表示

このコードの凄いポイント

私のサイトは

SEOに強い構造になっています

普通の天気サイト

?pref=130000

あなた

/tokyo

Googleは

/tokyo

地域ページとして認識

SEO的にかなり良い設計です。


このコードには

  1. WordPress rewrite
  2. JSON処理
  3. POST変換
  4. SEO URL
  5. JS連携

5つの技術が混ざっています。



19-3.Apache(アパッチ)のWordPress のURL変換ルール

Apache(アパッチ)の .htaccess、下記コードを追加します。


# BEGIN WordPress
# "BEGIN WordPress" から "END WordPress" までのディレクティブ (行) は # 動的に生成され、WordPress フィルターによってのみ修正が可能です。
# これらのマーカー間にあるディレクティブへのいかなる変更も上書きされてしまいます。

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

これは Apache(アパッチ)の .htaccess に書かれている WordPress のURL変換ルールです。
簡単に言うと、

「WordPressのパーマリンク(きれいなURL)を動かすための仕組み」

です。

あなたのサイトの

/tokyo
/osaka
/hokkaido

のようなURLが動くのは、このコードのおかげです。

では1行ずつ詳しく説明します。


① BEGIN WordPress

# BEGIN WordPress

これは ただの目印コメントです。

意味

ここからWordPressの設定

WordPressは設定更新時に、この範囲を書き換えます。


② 注意コメント

# "BEGIN WordPress" から "END WordPress" までのディレクティブ (行) は
# 動的に生成され、WordPress フィルターによってのみ修正が可能です。
# これらのマーカー間にあるディレクティブへのいかなる変更も上書きされてしまいます。

意味

この部分はWordPressが自動生成するので
手で変更しても上書きされます

③ mod_rewriteがあるか確認

<IfModule mod_rewrite.c>

意味

ApacheにURL書き換え機能がある場合だけ実行

mod_rewrite は

URLを書き換える機能

です。


④ RewriteEngine ON

RewriteEngine On

意味

URL書き換え機能をONにする

⑤ Authorizationヘッダー保持

RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

これは少し高度です。

意味

AuthorizationヘッダーをWordPressに渡す

これは主に

  • REST API
  • JWT認証
  • プラグイン

で必要になります。

通常のサイトではあまり意識しなくてOKです。


⑥ RewriteBase

RewriteBase /

意味

URL書き換えの基準はルート

https://example.com/


⑦ index.phpは処理しない

RewriteRule ^index\.php$ - [L]

意味

index.phpはそのまま処理する

つまり

index.php

は書き換えない。


⑧ 実在ファイルは除外

RewriteCond %{REQUEST_FILENAME} !-f

意味

実際のファイルが存在するなら
書き換えしない

logo.png
style.css
script.js

など。


⑨ 実在ディレクトリも除外

RewriteCond %{REQUEST_FILENAME} !-d

意味

実際のフォルダなら書き換えない

/images
/wp-content

⑩ WordPressへ転送

RewriteRule . /index.php [L]

これが一番重要な部分です。

意味

すべてのURLを
index.phpへ送る

ユーザーが

/tokyo

にアクセス。

Apacheは

/tokyo

というファイルを探します。

しかし

存在しない

すると

index.php

に送られます。


WordPress内部の処理

/tokyo

.htaccess

index.php

WordPress

Rewriteルール解析

get_query_var("roma")

tokyo

私のPHPコードに届きます。


つまりこのコードは

私のサイトの

/tokyo
/osaka
/nagoya

というURLを

WordPressに渡す役割

です。


私のサイトの流れ

ユーザー

/tokyo

Apache

.htaccess

index.php

WordPress

あなたのPHP

get_query_var('roma')

tokyo

天気表示


重要なポイント

この設定があるから

普通なら

?pref=130000

になるところを

私のサイトでは

/tokyo

に出来ています。

これは

SEOにかなり有利です。



19-4.都道府県選択後のtitle変更

AIOSEOプラグインを利用して、セレクトボックス選択後の各都道府県に対応した、titleを表示します。

<?php

 // AIOSEOを停止するフィルターフック
 add_filter('aioseo_title', function($title){

    $slug = get_query_var('roma');

     if($slug){

         require(get_stylesheet_directory() . '/prefec.php');
         $prefs = json_decode($json3,true);

         foreach($prefs as $p){
            if($p['roma'] == $slug){
                return $p['name'].'の天気予報(今日・明日・週間) | レインボーウェザー';
            }
        }

     }

     return $title;
});

 add_filter('aioseo_description', function($desc){

     $slug = get_query_var('roma');

     if($slug){

        require(get_stylesheet_directory() . '/prefec.php');
        $prefs = json_decode($json3,true);

        foreach($prefs as $p){
            if($p['roma'] == $slug){
                return $p['name'].'の最新天気予報。気象庁データを元にした天気図、天気概況、今日・明日・週間天気、雨雲レーダー、台風進路情報、アメダス気温を掲載しています。';
            }
        }

    }

    return $desc;
});

?>

このコードは、
AIOSEO(All in One SEO)のタイトルとディスクリプションを、URLごとに動的に書き換える処理です。

私のサイトでいうと

/tokyo → 東京都のタイトル
/osaka → 大阪府のタイトル

のように、地域ごとにSEOタグを自動生成しています。
これはかなり実用的で、SEO的にも良い実装です。


全体の役割

このコードは大きく2つあります。

  1. タイトルを書き換える
  2. 説明文(description)を書き換える

① タイトルの書き換え

add_filter('aioseo_title', function($title){

何をしているか

WordPressの「フィルターフック」を使っています。

👉 意味

AIOSEOがタイトルを出す直前に、
この関数で内容を変更する

slug(URLの値)を取得

$slug = get_query_var('roma');

/tokyo → slug = tokyo
/osaka → slug = osaka

slugがあるかチェック

if($slug){

👉 /tokyo のようなページだけ処理する

トップページなどは無視


都道府県データを読み込む

require(get_stylesheet_directory() . '/prefec.php');
$prefs = json_decode($json3,true);

ここはあなたが作ったJSON

tokyo → 東京都
osaka → 大阪府

に変換


一致する都道府県を探す

foreach($prefs as $p){
if($p['roma'] == $slug){

tokyo == tokyo → 一致

タイトルを上書き

return $p['name'].'の天気予報(今日・明日・週間) | レインボーウェザー';

結果

東京都の天気予報(今日・明日・週間) | レインボーウェザー

見つからなければ元に戻す

return $title;

👉 何もしない



② ディスクリプションの書き換え

add_filter('aioseo_description', function($desc){

基本構造はタイトルと同じです。


書き換え部分

return $p['name'].'の最新天気予報。気象庁データを元にした天気図、天気概況、今日・明日・週間天気、雨雲レーダー、台風進路情報、アメダス気温を掲載しています。';

東京都の最新天気予報。〜

このコードの動き(流れ)

ユーザー

/tokyo にアクセスWordPress

get_query_var('roma')

tokyoJSON照合

東京都AIOSEOフック

タイトル変更HTML出力

<title>東京都の天気予報...</title>
<meta name="description" ...>

このコードのすごいところ

私のサイトは

👉 全地域ページに個別SEOタグがある

状態です。

普通の初心者サイト

全ページ同じタイトル

あなたのサイト

/tokyo → 東京都の天気
/osaka → 大阪府の天気

👉 完全に地域特化ページになっている


SEO的な評価

かなり良いです。

特に

「東京都 天気」
「大阪府 天気」

などで検索されやすくなります。



19-5.パーマリンクの変更

パーマリンク設定が「基本」になっていると、https://rainboweather.info/tokyo/ が表示されません。

現在の設定

https://rainboweather.info/?p=123

これは WordPressがRewriteを使わないモードです。
そのため

/tokyo
/fukushima

のようなURLは すべて404になります。


解決方法

WordPress管理画面で変更します。

設定

パーマリンク

投稿名

これに変更してください。

設定はこうなります。

https://rainboweather.info/%postname%/

保存します。


変更するとどうなるか

今まで

?p=123

だったURLが

/sample-post/

のようになります。

そして同時に

/tokyo
/fukushima

のRewriteも 動くようになります。



今までは、セレクトボックスで都道府県を選択しても、https://rainboweather.info/ と認識され、天気予報のページとは認識されませんでした。

しかし、セレクトボックスのSEO化を行うことで、各都道府県の天気予報として、Google検索が認識されるようになりました。

これによって、47都道府県の天気予報のページとして認識されることで、「三重県 天気予報」等の検索語句でヒットするようになり、

アクセスログの増加が期待できますね‼️


以上で、セレクトボックスのSEO化の解説は、終了です。

お疲れ様でした😊♨️☕