The idea of tracking 404 errors started from here (first posted by WP Mix). The problem is that the result of those tutorials is that you will receive an email for each 404 error, and that can be quite annoying.
So I created a plugin that saves the errors into a mySQL table and sends daily (hourly, twicedaily) email alerts using WordPress’ cron system. Save the code snippet below as nftracking.php
and place it in your plugins folder:
/* Plugin Name: 404 Not Found Tracking Plugin URI: https://wpcrumbs.com/404-not-found-tracking-plugin/ Description: Track every 404 not found page Version: 1.0 Author: George Jipa Author URI: https://wpcrumbs.com */ class NFTracking { public $notification = 'daily'; // you can change with hourly or twicedaily public $tracking_table; public $wpdb; public function __construct() { global $wpdb; $this->wpdb = $wpdb; $this->tracking_table = $wpdb->prefix . 'nftracking'; // activate / deactivate plugin register_activation_hook(__FILE__, array($this, 'activate_plugin')); register_deactivation_hook(__FILE__, array($this, 'deactivate_plugin')); // add tracking add_action('wp', array($this, 'tracking')); // add cron add_action('my_send_notifications', array($this, 'send_notifications')); } /** * Tracking */ public function tracking() { if (!is_404()) { return; } // insert 404 information $insert = array( 'data' => serialize(array( 'referer' => isset($_SERVER['HTTP_REFERER']) ? sanitize_text_field($_SERVER['HTTP_REFERER']) : 'undefined', 'request' => isset($_SERVER['REQUEST_URI']) && isset($_SERVER['HTTP_HOST']) ? sanitize_text_field('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']) : 'undefined', 'query_string' => isset($_SERVER['QUERY_STRING']) ? sanitize_text_field($_SERVER['QUERY_STRING']) : 'undefined', 'ip_address' => isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field($_SERVER['REMOTE_ADDR']) : 'undefined', 'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field($_SERVER['HTTP_USER_AGENT']) : 'undefined', 'remote' => isset($_SERVER['REMOTE_IDENT']) ? sanitize_text_field($_SERVER['REMOTE_IDENT']) : 'undefined' )), 'insert_date' => date('Y-m-d H:i:s') ); $this->wpdb->insert($this->tracking_table, $insert, array('%s', '%s')); } /** * Triggered when plugin is activated */ public function activate_plugin() { // create table $sql = "CREATE TABLE IF NOT EXISTS `{$this->tracking_table}` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `data` text NOT NULL, `insert_date` datetime NOT NULL, PRIMARY KEY (`id`), KEY `insert_date` (`insert_date`) );"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); // set cronjob event if (!wp_next_scheduled('my_send_notifications')) { wp_schedule_event(current_time('timestamp'), $this->notification, 'my_send_notifications'); } } /** * Triggered when plugin is deactivated */ public function deactivate_plugin() { // clear cronjob event wp_clear_scheduled_hook('my_send_notifications'); // delete plugin options delete_option('nftracking_last_notification'); } /** * Send email notifications */ public function send_notifications() { // get last check time $last_notification = get_option('nftracking_last_notification', 0); // check if there are any errors in the database $errors = $this->wpdb->get_results($this->wpdb->prepare("SELECT * FROM {$this->tracking_table} WHERE insert_date >= %s", $last_notification), ARRAY_A); if (!empty($errors)) { ob_start(); ?>
Time | 404 | Referrer | Query string | Remote address | Remote identity | User agent |
TO DO's:
1. Show the 404 errors in WordPress admin area too.
2. Clean the 404 errors table periodically.
2. Any ideas ?