意外と多いWordPress Popular Postsの落とし穴
今までページビューの多い人気の投稿を表示するのに、Post-Plugin Libraryと組みあせて使うPopular Postsというプラグインを利用していました。
動作的には問題ありませんでしたが、「最終更新日2012-1-28、最新の対応バージョン: 3.3.2」というのが気になっていました。
今回、自作プラグイン「Step by Step Social Count Cache」を利用してSNSで人気の記事Top10を表示するのに合わせて最新のWordPressにも対応しているWordPress Popular Postsに乗り換えました。
他のサイトで導入済みだったこともあり、さくっと設置できたのですが、なぜかカウントが増えません。正確には自分のカウントだけ計測されて、他の利用者のカウントだけ計測されていないようでした。以前コメントで「カウントが表示されません」と質問をもらったこともあったので、対策をまとめました。
原因1:設定が間違っている
単純にプラグインの設定が間違っている場合があります。
対策
「設定 > WordPress Popular Posts」の「Tools」タブを開き「Log views from:」の項目を見ます。
Visitors onlyは訪問者のみをカウントします。(ログインユーザーはカウントしない)
Logged-in users onlyはWordPressのログイン・ユーザーのみカウントします。クローズドのサイトの場合はこちらで良いかもしれません。
Everyoneこれは全てのユーザーでカウントという意味です。少しわかりにくいですが、ログインユーザーもそうでない一般の訪問者もカウントするという設定です。
ログインユーザーでアクセスしてカウントを確かめる場合はVisitors onlyではカウントされません。ログインユーザーもカウントするEveryoneにする必要があります。
今回の「ログインユーザーしかカウントされていない」と思ったら、まずはこの設定を見てみるのが良いと思います。
原因2:ページキャッシュを利用している
WordPress Popular Postsを導入すると、ヘッダーにカウント用のJavaScriptを書き出します。
そこに「params = ‘action=update_views_ajax&token=650d941ba9&wpp_id=9278’;(例)」という記述があります。どうやらここで発行されるTokenでbot対策をしているようです。wp_verify_nonce()でnonceを生成して有効期限が過ぎた場合にエラーを返す仕組みになっています。(ソースを見ると24時間経過するとエラーになるようです)
エラーになるとコンソールログに「WPP: Oops, invalid request!」と表示されるので失敗している場合は簡単に判断できます。
対策
「設定 > WordPress Popular Posts」の「Tools」タブを開き、「Ajaxify widget:」を「Enabled」にします。
こうすることでキャッシュしたページでもカウントするようになります。
しかし、疑問なのはこの機能はページキャッシュ有効時にWidgetに表示している人気の記事一覧が更新されない問題を解決するために、Ajaxで人気記事を表示するためのオプションです。
推測ですが、この対策でカウントされた場合は「Widget機能を使って人気記事を表示していて、キャッシュ系プラグインでカウントする前のページキャッシュを見ていた場合」だと思います。
そのため、1度ページキャッシュを削除してみるというのも対策として良いかもしれません。
問題はページキャッシュの保存期間を1日以上にしている場合です。
「Ajaxify widget:」を「Enabled」にしても動作しない場合は、キャッシュ期間を1日未満にするか、wp_verify_nonce()で生成するキャッシュの有効期限を伸ばす必要があります。
nonceの有効期限を変更するにはnonce_lifeフィルターを使います。デフォルトはDAY_IN_SECONDSというWordPressの定数がセットされています。これは60*60*24つまり86,400秒のことです。
例えば有効期限を1週間にするにはfunctions.phpに以下のように記述します。
function change_nonce_life( $nonce_life ) { $nonce_life = 60 * 60 * 24 * 7; return $nonce_life; } add_filter( 'nonce_life', 'change_nonce_life' );
これで生成されたnonceは1週間有効になっているので、ページキャッシュが1週間以内に
更新されれば問題なくカウントされます。
原因3:wp-adminをアクセス規制している
ログイン画面へのブルートフォース攻撃にwp-login.phpやxmlrpc.phpへアクセス規制をする方も多いと思います。合わせてwp-adminディレクトリへのアクセス規制をしている場合は、このプラグインで利用している「wp-admin/admin-ajax.php」というファイルへアクセスできず正しくカウントされません。
このファイルはTokenと組み合わせれば、パラメータを組み立てるだけで簡単に実装できることから、利用しているプラグインは多いようです。
当サイトの場合、これが原因でカウントされませんでした。
対策
当サイトではnginxでホワイトリスト形式でIPアドレスを許可していました。
wp-admin以下のファイルは拒否しつつ、admin-ajax.phpだけは例外的に許可するには以下のように設定します。リバースプロキシ側のserverディレクティブに記述してください。
location ~ wp-login\.php$|xmlrpc\.php$|wp-admin/((?!admin-ajax\.php).)*$ { allow 0.0.0.0; // ここに自分(ASP)のIP allow 127.0.0.1; deny all; proxy_pass http://backend; }
もしくはもろもろを拒否した後にadmin-ajax.php限定で許可しても見通しが良くていいと思います。
location ~ /wp-admin/admin-ajax\.php.*$ { allow all; }
原因4:オレオレ証明書を使ったSSLを使っている
これは以下のサイトで詳しく解説されています。
WP Super CacheとWordPress Popular Postsプラグイン | メモ置場のブログ
簡単にいえばブラウザの警告機能が動作するためカウントされないということですね。ということは普通にページを閲覧している人々にも警告画面が出ているということです。
対策
対策はオレオレ証明書を使ったSSLの利用を中止することです。最近では無料のLet’s Encryptなども出てきているので利用するのも手です。(2015年夏にリリースと言われていましたが、まだ正式にはリリースされていません)
プラグイン内部ではis_ssl()で判定しているので、この記述を削除してhttpに固定したり、wp-config.phpに$_SERVER[‘HTTPS’] = NULL;なんて書いても動作するかもしれませんが、どちらも筋は良くないですね。
ちなみに共用SSLを利用時にWordPressが正しくSSLを認識しないことがあります。ものによっては、SSLに必要なヘッダーを返さない場合や、ポートが443でなく80のままだったりと原因は様々ありますが、以下の対策が有効なようです。
wp-config.phpに以下の記述をします。
$_SERVER['HTTPS'] = 'on';
またロードバランサを噛ませていてhttpsが正常に判定できない場合は以下のようにすると良いようです。
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') $_SERVER['HTTPS'] = 'on';
番外編
他にもこのプラグインは全てのアクセスをデータベースにカウントするため、高負荷のサイトの場合はサンプリング機能を使うことをお勧めします。
これは100人にアクセスされた時に全員のアクセスをカウントするのではなく、1人分だけ抽出してカウントするという方法です。この1人のアクセスは100人分の重みがあり、カウントも100追加されます。
デフォルトのサンプルレートは100になっています。1日に数10万アクセスある場合はこのままでも良いですが、一般のサイトでは流石に精度が荒い気がします。
レートを2にすれば単純に書き込みの負荷は半分になります。少ない数字でも効果があるのでレンタルサーバなど、負荷の気になる場合は設定しておきましょう。
一旦Data Samplingを有効にするとサンプルレートを入力するフィールドが表示されるので、5や10程度にしておきましょう。
こうしてまとめると人気のプラグインですが、意外に落とし穴が多く、扱いには注意が必要なようです。
ピンバック: Ayumi folio | 日々の出来事