81 views
【1】やりたいこと
各投稿、各固定ページについて、直近 n日間のアクセス数を表示したい。
【2】やってみた
1) 仕様
1) WORDPRESSの Pluginとして実装すること。
2) 同一IPからの重複アクセスは 1日 1カウントとすること。
3) データの格納先を WORDPRESSが使用している Databaseとすること。
SQLiteにしようか迷ったが、すでに WORDPRESS実行のために PostgreSQLと接続済みで負荷増の心配がなく、こちらを使うことにした。
4) shortcodeで投稿ページや固定ページに表示できること。
5) shortcodeのパラメータで過去 n日を指定できること。
6) BOTによるアクセスを除外すること。
(1) 重複カウント回避の方法
テーブルに対して UNIQUE制約を設定する。
UNIQUE KEY unique_view (post_id, ip_address, view_date)
これにより、post_id, ip_address, view_date の 3カラムの値が重複するレコードは存在できなくなる。
2) ソースコード
<?php /* Plugin Name: YTMR PV Counter Description: 各投稿・固定ページへのアクセス数を日別にカウントし、ショートコードで表示する。 Version: 1.0 Author: DOGROW.NET */ defined('ABSPATH') || exit; require_once plugin_dir_path(__FILE__) . 'includes/functions.php'; register_activation_hook(__FILE__, 'pvc_create_table'); add_action('wp', 'pvc_track_pageview'); add_shortcode('ytmr_pv_counter', 'pvc_show_last_n_days');
<?php defined('ABSPATH') || exit; //////////////////////////////////////////////////////////////////////////////// function pvc_create_table() { global $wpdb; $table_name = $wpdb->prefix . 'pageview_counter'; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE IF NOT EXISTS $table_name ( id BIGINT AUTO_INCREMENT PRIMARY KEY, post_id BIGINT NOT NULL, ip_address VARCHAR(45) NOT NULL, view_date DATE NOT NULL, UNIQUE KEY unique_view (post_id, ip_address, view_date) ) $charset_collate;"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta($sql); } //////////////////////////////////////////////////////////////////////////////// function pvc_track_pageview() { if(!is_singular('post') && !is_singular('page')) return; if(!isRealVisitor()) return; // BOTならばカウントしない。 global $wpdb; $post_id = get_the_ID(); if (!$post_id) return; $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; $today = date('Y-m-d'); $table = $wpdb->prefix . 'pageview_counter'; // 同一IP・日・投稿の組み合わせが存在しなければ追加 $exists = $wpdb->get_var($wpdb->prepare( "SELECT COUNT(*) FROM $table WHERE post_id = %d AND ip_address = %s AND view_date = %s", $post_id, $ip, $today )); if (!$exists) { $wpdb->insert($table, [ 'post_id' => $post_id, 'ip_address' => $ip, 'view_date' => $today ]); } } //////////////////////////////////////////////////////////////////////////////// function pvc_show_last_n_days($atts) { if (!is_singular('post') && !is_singular('page')) return ''; $atts = shortcode_atts(['n' => 5], $atts); $n = intval($atts['n']); if ($n < 1 || $n > 365) $n = 5; //$now = date('Y-m-d H:i:s'); global $wpdb; $post_id = get_the_ID(); if (!$post_id) return ''; $table = $wpdb->prefix . 'pageview_counter'; $output = "<div>アクセス数(直近{$n}日): "; for ($i = 0; $i < $n; $i++) { $date = date('Y-m-d', strtotime("-$i days")); $count = $wpdb->get_var($wpdb->prepare( "SELECT COUNT(*) FROM $table WHERE post_id = %d AND view_date = %s", $post_id, $date )); $output .= "<li>{$date}: {$count}回</li>"; } $output .= "</ul></div>"; return $output; } //////////////////////////////////////////////////////////////////////////////// // 投稿本文の後ろにカスタムHTMLを追加する function mcf_add_custom_footer_message($content) { // 投稿ページ(single)のみ対象にする if (is_single() && is_main_query()) { $add_content = pvc_show_last_n_days(null); return $content.$add_content; // 本文の後ろに追加 } return $content; } //////////////////////////////////////////////////////////////////////////////// // BOT判定 function isRealVisitor() { if (!isset($_SERVER['HTTP_USER_AGENT'])) { return false; // User-Agentがない=BOTの可能性大 } $ua = strtolower($_SERVER['HTTP_USER_AGENT']); // よく知られたBOTのキーワード(必要に応じて追加可) $bot_keywords = [ 'bot', // 一般的なbot(Googlebot, Bingbotなど) 'crawler', // クローラー 'spider', // スパイダー系 'slurp', // Yahoo 'baiduspider', // Baidu 'yandex', // Yandex 'ia_archiver', // Alexa 'python-requests', // Pythonによるアクセス 'wget', 'curl', 'httpclient', 'libwww-perl', ]; foreach ($bot_keywords as $bot) { if (strpos($ua, $bot) !== false) { return false; // BOTが含まれているので除外 } } return true; // BOTではないと判定 }
3) 動作確認
ここ(↓)に表示してみる。
アクセス数(直近7日): ※試験運用中、BOT除外簡易実装済2025-07-11: 0回 2025-07-10: 0回 2025-07-09: 4回 2025-07-08: 0回 2025-07-07: 0回 2025-07-06: 1回 2025-07-05: 0回
【3】残件
BOTによるアクセスを除外すること。
※ページ右上の総合カウンタは対応済み。このコードを移植する。
アクセス数(直近7日): ※試験運用中、BOT除外簡易実装済2025-07-11: 0回 2025-07-10: 0回 2025-07-09: 4回 2025-07-08: 0回 2025-07-07: 0回 2025-07-06: 1回 2025-07-05: 0回