WP-Mix

A fresh mix of code snippets and tutorials

WordPress 404 email alerts

Here is a customized plug-n-play PHP script for reporting 404 errors via email. No editing required, just clean email alerts for each 404 error.

Part of working online is cleaning up 404 errors for good SEO. Instead of taking the time to hunt them down manually or installing and maintaining another plugin, I add a small script to my theme’s 404.php file, so that I’m notified whenever 404 errors occur. This enables me to react swiftly to dead links, errors, and threats. Super-useful when working with many sites.

To implement this technique, simply include this script at the top of your theme’s 404.php file:

<?php // WP 404 ALERTS @ https://wp-mix.com/wordpress-404-email-alerts/

// set status
header("HTTP/1.1 404 Not Found");
header("Status: 404 Not Found");

// site info
$blog  = get_bloginfo('name');
$site  = get_bloginfo('url') . '/';
$email = get_bloginfo('admin_email');

// theme info
if (!empty($_COOKIE["nkthemeswitch" . COOKIEHASH])) {
	$theme = clean($_COOKIE["nkthemeswitch" . COOKIEHASH]);
} else {
	$theme_data = wp_get_theme();
	$theme = clean($theme_data->Name);
}

// referrer
if (isset($_SERVER['HTTP_REFERER'])) {
	$referer = clean($_SERVER['HTTP_REFERER']);
} else {
	$referer = "undefined";
}
// request URI
if (isset($_SERVER['REQUEST_URI']) && isset($_SERVER["HTTP_HOST"])) {
	$request = clean('http://' . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
} else {
	$request = "undefined";
}
// query string
if (isset($_SERVER['QUERY_STRING'])) {
	$string = clean($_SERVER['QUERY_STRING']);
} else {
	$string = "undefined";
}
// IP address
if (isset($_SERVER['REMOTE_ADDR'])) {
	$address = clean($_SERVER['REMOTE_ADDR']);
} else {
	$address = "undefined";
}
// user agent
if (isset($_SERVER['HTTP_USER_AGENT'])) {
	$agent = clean($_SERVER['HTTP_USER_AGENT']);
} else {
	$agent = "undefined";
}
// identity
if (isset($_SERVER['REMOTE_IDENT'])) {
	$remote = clean($_SERVER['REMOTE_IDENT']);
} else {
	$remote = "undefined";
}
// log time
$time = clean(date("F jS Y, h:ia", time()));

// sanitize
function clean($string) {
	$string = rtrim($string); 
	$string = ltrim($string); 
	$string = htmlentities($string, ENT_QUOTES); 
	$string = str_replace("\n", "<br>", $string);

	if (get_magic_quotes_gpc()) {
		$string = stripslashes($string);
	} 
	return $string;
}

$message = 
	"TIME: "            . $time    . "\n" . 
	"*404: "            . $request . "\n" . 
	"SITE: "            . $site    . "\n" . 
	"THEME: "           . $theme   . "\n" . 
	"REFERRER: "        . $referer . "\n" . 
	"QUERY STRING: "    . $string  . "\n" . 
	"REMOTE ADDRESS: "  . $address . "\n" . 
	"REMOTE IDENTITY: " . $remote  . "\n" . 
	"USER AGENT: "      . $agent   . "\n\n\n";

mail($email, "404 Alert: " . $blog . " [" . $theme . "]", $message, "From: $email"); 

?>

No editing required, just include and done. To disable the email reporting, either remove the script or comment-out the mail() function, like so:

// mail($email, "404 Alert: " . $blog . " [" . $theme . "]", $message, "From: $email");

Note that any of the variables (e.g., $time, $request, et al) are available for use elsewhere on the page. For example, you could display the information to the visitor to help deliver a useful 404 page.

Here is a screenshot showing how the email alerts will look in your inbox.

Update (2013/03/03): Thanks to Drew Jaynes for sharing his OOP-enhanced version of the 404-email script. Muy bueno!!

Update (2015/09/13): Here is a more robust IP-detection script, which could be used to beef up the 404-alert functionality.

Learn more

Digging Into WordPressWordPress Themes In DepthWizard’s SQL Recipes for WordPress