お宿にもSSL化の波が押し寄せてキター

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
∀ガンダムはスパロボでしか知らないっす

この記事を三行にまとめると

アドレスバーを見るとhttpsになってるっしょ?
グレートタイムドクターに任せましょう
できるわきゃねーだろおおおお!!!(CV:ギム・ギンガナム)
つい先日、サイトをSSL化してみようと思ったけどうんぬんかんぬん的なことを言いましたが、改めてちゃんと対応してみました。アドレスバーを見るとhttpsになってるっしょ?

たぶん問題なくSSL化できてると思うのですが、とりあえず、サイトを常時SSLにした時に確認しておいた方が良いんじゃないかな〜と思ったポイントが個人的にいくつかあったので、今日はそれを一つずつ見ていきたいと思います。

まあ「常時SSL化」とかでググると気をつけるべきポイントが書かれた記事がたくさん見つかるので、ある程度はそれらをさら〜っと流していく感じになると思います。

個人的に確認しておいた方良いと思ったポイントは以下の通りです。

httpからhttpsのリダイレクト設定
Googleアナリティクスのプロパティ
Google Search Consoleのプロパティ
画像のパス
広告を埋め込んでいる場合
SNSのシェア数の引き継ぎ

ほんじゃあ順番に見ていきましょー。



httpからhttpsのリダイレクト設定

もしサイトをhttpsのみのアクセスにするのなら、httpにアクセスされた時にhttpsの同じページにリダイレクトされるように設定する必要があります。

と言ってもやり方は簡単。.htaccessにちょこちょこっと設定を書き込むだけで実現できます。

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTPS} off
  RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
</IfModule>

これでオーケー。特にSSL化した直後はhttpsのページがGoogleなどにインデックスされてないので、検索で表示されるページはhttpのままですから、この設定は大事でしょう。

さくらインターネットなどはこの設定では上手く動かないんですが……まあ、その辺については前にも語ったので今回は省略しましょう。

さくらインターネットのレンタルサーバー(スタンダードプラン)でSSLを使ってみたけど……



Googleアナリティクスのプロパティ

Googleアナリティクスのアカウント管理のところでプロパティやビューの設定ができますが、ここで「デフォルトのURL」や「ウェブサイトのURL」をhttpからhttpsに切り替えます。

httpのままでも動くっちゃ動く

これはたぶん対応し忘れててもあまり支障がないような気もするんですが、やらないよりはやっといた方が良いでしょう。



Google Search Consoleのプロパティ

Googleアナリティクスは切り替えが簡単なのですが、Search Consoleの方はちょい手間がかかります。ドメインが一緒でもhttpとhttpsを一つのプロパティで扱えないようなので、httpsの方を新たに登録し直さないといけません。

wwwありなしも両方別々に登録する必要があるらしい

「プロパティの追加」でhttpsの方のドメインを新たに登録してください。

httpを登録した時と手順は一緒ですが、プロパティを追加すると所有権の確認をしろと言われるので、指示に従って確認作業を行います。

確認方法はいくつかあります

ちなみに、指示通りにやったのに確認ボタンを押すと「確認できませんでした」というエラーが出ることがあるかもしれません。

何が原因でそうなるのかは分からないのですが、手順を間違えていないなら、ひとまず放っておけばそのうち確認できるようになります。僕も次の日になったら無事に確認できた。時は偉大な医者とはよく言ったものですね。ネットのエラーですら直してくれるとは。

無事に確認できるようになったら、サイトマップを追加し直しておきましょう。もちろんサイトマップの中身はhttpをhttpsに変えたものね。

あとはGoogleがクロールしてくれるのを気長に待てば、検索アナリティクスなどにも徐々に結果が出るようになると思います。僕はまだ切り替えてそんなに日が経ってないのでまだぼちぼちと言ったところですが、まあそれもグレートタイムドクターに任せましょう。



画像のパス

ページ内に埋め込まれた画像が絶対パスで書かれていると、SSL化した時に「このサイトへの接続は完全には保護されていません」みたいな警告が出ることがあります。これはhttpsのページの中にhttpで参照した画像が入っていたりすると出ます。画像だけじゃなく、cssやjsファイルもhttpsで読み込まないと同様のエラーが出る。

外部のサイトから直接参照している場合はそっちがhttpsに対応してないとどうしようもないですが、自分とこのファイルを埋め込んでいる場合は、httpをhttpsに修正しないといけません。

Wordpressで動いているサイトなら「Search Regex」というプラグインがあるので、それを使って本文中の画像のパスを書き換えるというやり方がありますが、僕的には直接DBからwp_postsテーブルのSQLをエクスポートして、テキストエディタで一括置換しちゃっても良いと思います。僕はそうしました。そっちのやり方ならWordpressとかじゃなくても対応できるしね。まあ記事の数が多いとSQLのファイルサイズが大きくなるから、テキストエディタで開きにくいかもしれませんが……。

というか、個人的にはもう、画像は相対パスにしちゃえば良いんじゃないかと思うんだけど、どうですかね? 今回の置換で僕は本文中の画像を全部相対パスにしました。



画像の挿入を相対パスにしてみる

これもWordpressの話ですが、新しく記事本文にメディアを挿入する場合、挿入した後に手動で相対パスに書き換えても良いですが、それが面倒って場合には、挿入時に自動的に相対パスになるようにしてしまうという手もあります。

functions.phpに以下の関数を作ることで、相対パスで画像を挿入することができます。

function delete_host_from_attachment_url($url) {
  $regex = '/^http(s)?:\/\/[^\/\s]+(.*)$/';
  if (preg_match($regex, $url, $m)) {
    $url = $m[2];
  }		
  return $url;
}
add_filter('wp_get_attachment_url', 'delete_host_from_attachment_url');

じっさいやってみるとこんな感じ。

相対パスで特に問題はないはず

URLが相対パスになってますね。

こちらの記事を参考にさせていただきました。ありがらす!!(←ありがとうございますと言っている)
WordPressで挿入する画像のsrcを相対リンクにする



ただし一つだけ注意しなきゃいけないのは、このやり方だと、アイキャッチ画像の取得なども相対パスになってしまうということです。

$thumbnail_id = get_post_thumbnail_id();
$image = wp_get_attachment_image_src($thumbnail_id, 'full');

$image = get_the_post_thumbnail($post_id, 'full');

これらの関数を使って画像を取得すると、URLが相対パスになります。

サイト内に表示するだけなら問題ないですが、SNSのシェアボタンを設置する場合やmetaタグの「og:image」に記述する時は、絶対パスじゃないといざシェアしようって時などにエラーになります。

$thumbnail_id = get_post_thumbnail_id();
$image = wp_get_attachment_image_src($thumbnail_id, 'full');
<meta property="og:image" content="<?php echo $image[0] ?>" />

↑みたいなことをやると相対パスになってしまうので、必要な箇所を絶対パスに書き換えるか、ここまで書いといてなんですが、この方法はひとまず使わずに、本文に挿入したメディアを手作業で相対パスに書き換えるなどしてください。



お宿でもいくつか広告を埋め込んでいますが、SSLのサイトでは表示できない広告がいくつかあります。

うちの場合だと、Amazonの通常の広告(バナーリンクとかウィジェットとか)はSSLでも表示できますが、Publisher StudioはSSLだと表示できないみたいです。現時点ではという話なので、そのうち使えるようになるかもしれません。

Google AdSenseや忍者Admaxは問題ないようですね。まあSSL化を推奨してるGoogleさんが広告をSSLに対応しないはずはないよね。

対応している広告のはずなのに表示できないって場合は、広告を表示するjavascriptなどの埋め込みコードがhttpになっているか確認してみましょう。そこをhttpsに書き換えれば表示されるはずです。



SNSのシェア数の引き継ぎ

やっぱりWordpressの話になりますが、Wordpressには「SNS Count Cache」という、シェア数を取得してくれるプラグインがあります。このプラグインの設定項目の中に「HTTPからHTTPSへのスキーム移行モード」というのがあるのですが、これを有効にするとプラグインがhttpとhttpsの両方のシェア数を取ってきて合算してくれます。これを使えば今まで通りのシェア数を表示できます。Wordpressでサイトを作っているのなら、この辺に頼るのが一番簡単かなと思います。

ただしWordpressであっても、自分でカスタマイズしたものではなく公式のボタンを表示させる場合は、当然ながらこのプラグインが取得したシェア数は使えません。

公式ボタンが表示するシェア数は、引き継がれる場合と引き継がれない場合があります。お宿では現在、以下の5つのボタンを表示しています。

・Facebook
・Hatebu
・Pocket
・Google+
・Twitter

このうち、PocketとTwitterはhttpsに変えてもシェア数が引き継がれてるっぽいです。まあ、Twitterは公式のAPIがカウントを取得できなくしてしまったので、どのサービスを使って取得するかで違いがあるかもしれません。

僕はwidgetoon.js & count.jsoonというサービスを利用しています。ここはhttpsに引き継いでくれている。

Google+はちょっと微妙な感じです。たぶん引き継いでくれていると思うのですが……取れる時と取れない時がある気がして、ちょい様子見って感じですね。

Hatebuは引き継いでくれません。引き継ぐ方法があるかどうか運営さんに問い合わせてもみたのですが「できるわきゃねーだろおおおお!!!(CV:ギム・ギンガナム)」と言われてしまいました。そのうち引き継げるようになるかもしれませんが、とりあえず今は無理のようです。残念。

Facebookは引き継げるのですが、ちょいとした一手間が必要になります。



引き継げないものを引き継ぐ

上記の5つの場合だとHatebuとFacebookが公式ボタンでは引き継げません(Google+は様子見)。じゃあどうれうば良いかって話なのですが……Hatebuに関しては次善の策として、ボタンに設定するURLをhttpの方にするという方法があります。

<a href="https://b.hatena.ne.jp/entry/http://norm-nois.com/blog/***" class="hatena-bookmark-button" data-hatena-bookmark-title="タイトル" data-hatena-bookmark-layout="vertical-large" data-hatena-bookmark-lang="ja" title="このエントリーをはてなブックマークに追加"><img src="https://b.st-hatena.com/images/entry-button/button-only@2x.png" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;" /></a>

「href=”https://b.hatena.ne.jp/entry/」の後ろを「https://norm-nois.com/blog/***」ではなく「http://norm-nois.com/blog/***」とすれば、以前のシェア数が表示されます。ただしこれだと、今後もhttpの方のシェアとして扱われてしまいます。

んー、まあ……httpでシェアされてもアクセスされたらhttpsにリダイレクトするわけだし、別に良いっちゃ良いのかもしれないですが……どうなんだろ。

僕はとりあえず、Hatebuの公式ボタンに関してはほったらかすことにしました。だから公式ボタンでは0なのにSNS Count Cacheで取得した数字は0じゃないというページがいくつもあります。でも決してDBを書き換えて数字を盛ってるわけじゃないのよ?



Facebookは公式のFAQに引き継ぐための手順が載っています。

ページを別のURLに移動させるには

簡単に言うと、metaタグの「og:url」にhttpのURLを記述して、Facebookのクローラーからのアクセスをリダイレクトさせないようにしてくださいってことのようです。

ちょっとやってみましょう。

//metaタグの設定(URLをhttpsにしない)
<meta property="og:url" content="http://norm-nois.com/blog/***" />

//.htaccessの設定(Fbクローラーはリダイレクトしないように)
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_USER_AGENT} !(^facebookexternalhit)
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

httpsのみのアクセスにしている場合は、httpでアクセスすると自動的にhttpsにリダイレクトされてしまいますが、それだとFbクローラーがhttpのサイトの情報を取得できなくなってしまうので、.htaccessのhttpsリダイレクト設定のところに、Fbクローラーかどうかをユーザーエージェントで判定する一文を足しています。

きちんと動作確認したわけではないけど、シェア数が正しく表示されるようになったから、たぶん書き方は合っていると思う。

クローラーのユーザーエージェントはドキュメントに載っています。

Facebookクローラー



それでもFacebookのシェア数が取れない場合

「上記の設定をしたのに公式ボタンのシェア数が0のままなんだけど?」という場合があると思います。

これはFacebookクローラーがまだスクレイピングしてくれていないか、前にスクレイピングした時のキャッシュが残っている可能性が高いです。

Facebookのシェアデバッガーを使えば、いつスクレイピングされたかなどの情報を確認することができます。

昔アダルトサイトのスクレイピングを……いや何でもない

httpsのURLを入力してこんな画面が出たらまだスクレイピングされてないので、「新しい情報を取得」ボタンを押すことでその場でスクレイピングが完了します。その後自分のサイトでシェアボタンを見れば数字が正常に表示されていると思います。

とはいえ、数が少ないならこのシェアデバッガーに一つずつURLを入力してスクレイピングすれば良いのですが、何百とある過去記事を全部やるとなると大変ですね。そういう場合はcurlを使ってスクレイピングする方法があります。

curl -d scrape=true -d id=https://norm-nois.com/blog/*** https://graph.facebook.com/

これを全ページに対して行えば新規のスクレイピングやキャッシュのクリアができます。

PHPでループ処理するならこんな感じですかね。

foreach($urls as $url) {
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_URL, 'https://graph.facebook.com/');
  curl_setopt($ch, CURLOPT_POSTFIELDS, array('scrape' => 'true', 'id' => $url));
  $result = curl_exec($ch);
  $result = json_decode($result);
  print_r($result);
  curl_close($ch);
}

「$urls」には公開記事のURLの一覧(httpsの方)が入っていると思ってください。念のため「$result」に結果を入れて正常に行えているか確認しています。

僕がやってみた限り、たまにエラーが出てスクレイピングできない場合がありますが、その場合は先ほどのシェアデバッガーで直接エラーになったURLを入力してスクレイピングすれば問題なさそうです。



おまけ

SNS Count Cacheでスキーム移行モードを有効にしているのに、なぜかシェア数が取得されないって場合。

sns-count-cache.phpの1150行目あたりを見ると、こんなコードがあります。

$this->scheme_migration_exclude_keys = array(
  self::REF_SHARE_POCKET,
  self::REF_SHARE_GPLUS,
  self::REF_SHARE_LINKEDIN,
  self::REF_FOLLOW_TWITTER,
  self::REF_FOLLOW_FACEBOOK,
  self::REF_FOLLOW_PUSH7,
  self::REF_FOLLOW_INSTAGRAM
);

これは「公式の方がhttpからhttpsにシェア数を引き継いでくれるサービスに関しては、こっちではhttpとhttpsの両方からは取得しないよ」的な設定です。先述の通り、PocketやTwitterはプラグインに頼らなくてもシェア数を引き継いでくれるので、プラグインがhttpとhttpsの両方から取得しちゃうとシェア数が重複して二倍になってしまいます。意図せず水増しできちゃうわけですね。

このうち取得できないサービスをコメントアウトすれば、プラグインがhttpとhttpsの両方から取ってきてくれます。公式のボタンは使わずにプラグインで取得した数字だけで自作のボタンを表示する場合は、例えばFacebookだったら先ほどのクローラーがどうのこうのという設定はやらずに、こっちをコメントアウトするだけでもシェア数は復活します。でもさっきの設定もきちんとやった上でこっちもコメントアウトしてしまうと、やはりシェア数が二倍になるので注意です。

これはプラグインのバージョンが0.11.1の場合の話です。もう少しバージョンが上がったり公式の方がシェア数の引き継ぎに対応すれば、この辺の設定も変わってくると思いますし、コメントアウトしなくても無事にシェア数が取れるようになるでしょう。

書いといてなんですが、このやり方はあまり推奨できないですかね……特にFacebookは、ちょっとめんどいかもだけどちゃんと公式の方のやり方でシェア数を引き継ぐ設定をした方が良いと思います。






ふう……こんなとこですかねー。

あとは、うーん、何かあるかなぁ……細かいことを言い出せばまだまだあるのかもしれませんが(Cookieをsecure属性にするとか)、ひとまずここまでできれば表示に関しては問題ないんじゃないでしょうか。

これ以外に「これはやっとかねーとやべーぞ。オラぁ恐怖でドキドキすっぞ」ってのがあれば、ご一報いただけるとありがたいです。僕自身も対応漏れしてるわけですから、やっとかないとね。
 もしかしたら何か関連しているかも? 
 質問や感想などお気軽にコメントしてください