Celebrating 20 years online :)
Web Dev + WordPress + Security

Ajax-Powered Error Logs for WordPress

[ WordPress ] In my previous post, I share my technique for Ajax-Powered Error Logs. That tutorial shows you how to set up dynamic error monitoring on any typical website, but the script requires some tweaking to get it working with WordPress. In this quick post, I explain how to set up Ajax Error Logs specifically for WordPress sites.

Update: Check out the new and improved Ajax Error Logs for WordPress v2.0!

About the different methods

[ Ajax Error Log WP - Project Files ] By default, WordPress handles 404 errors for anything under its control. For example, if WordPress is installed in the root directory of your site, it pretty much handles all 404 (Not Found) errors for the entire site. In this scenario, implementing an Ajax Error Log as directed in the original tutorial is going to be difficult because WordPress will be intercepting the 404 errors and making them unavailable to the Ajax Error script. Of course, the easiest way around this is to replace your theme’s 404.php file with a customized version of the Ajax Error script that is designed to work with WordPress. This is more or less what we’re doing in this tutorial.

The other scenario is that WordPress is installed in a SUBdirectory, in which case you have two options: either implement the Ajax Error Log as directed in the original tutorial (placed outside of the WordPress installation directory), or follow along with this tutorial and integrate the Ajax functionality into your existing subdirectory WP installation.

Ajax Error Logs for WordPress

Most of the information and tips in the original tutorial also applies to this WordPress-specific implementation, so I’ll be focusing only on the key steps required to make it happen with WordPress. That said..

Step 1: Prepare the Database

This step is the same as before, only this time we’re creating the error_log table within our existing WordPress database. This is key for the technique to work with WordPress. Here again is the SQL query to set it up:

CREATE TABLE `error_log` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `logtime` varchar(200) NOT NULL default '',
  `request` varchar(200) NOT NULL default '',
  `referer` varchar(200) NOT NULL default '',
  `qstring` varchar(200) NOT NULL default '',
  `address` varchar(200) NOT NULL default '',
  `agent` varchar(200) NOT NULL default '',
  `error` varchar(200) NOT NULL default '',
  PRIMARY KEY  (`id`),
  cur_timestamp TIMESTAMP(8)

That should create a table named “error_log” in your database. This is where we will be storing the data collected from our 404.php file, which we set up next.

Step 2: Create the custom error page

Create a blank file named 404.php, and fill it with the following PHP code:

Template Name: Ajax Error Log - 404 Page
Dynamic Error Logging by Jeff Starr @ Perishable Press
Project URL: https://perishablepress.com/ajax-error-log/
License: GNU General Public License
Version: 1.0

// site URL (no trailing slash!)
$website = "http://example.com";

// set headers for error page
header("HTTP/1.1 404 Not Found");
header("Status: 404 Not Found");

// WordPress

// set some server variables
$logtime = date("F jS Y, h:ia", time() - 10800);
$request = $site . $_SERVER['REQUEST_URI'];
$referer = $_SERVER['HTTP_REFERER'];
$qstring = $_SERVER['QUERY_STRING'];
$address = $_SERVER['REMOTE_ADDR'];
$agent   = $_SERVER['HTTP_USER_AGENT'];
$error   = "404"; // for other errors

// sanitize server variables
$logtime_esc = mysql_real_escape_string($logtime);
$request_esc = mysql_real_escape_string($request);
$referer_esc = mysql_real_escape_string($referer);
$qstring_esc = mysql_real_escape_string($qstring);
$address_esc = mysql_real_escape_string($address);
$agent_esc   = mysql_real_escape_string($agent);

// insert record and close database
$query  = "INSERT INTO `error_log` (logtime,request,referer,qstring,address,agent,error) ";
$query .= "VALUES ('$logtime_esc','$request_esc','$referer_esc','$qstring_esc','$address_esc','$agent_esc','$error')";
$result = @mysql_query($query);

// and finally output the html

		<div class="left">
			<div class="post">
				<h1>Error 404 — Not Found</h1>
				<p>The requested resource was not found on this server.</p>
				<div class="content">
					<p><?php echo "Requested URL: " . $website . $request_esc; ?></p>

<?php get_sidebar(); ?>

<?php get_footer(); ?>

The required edit is for the first variable, $website – just change that to match your site’s URL. Once you’ve got the code in place, just add the 404.php file to your active WordPress theme directory. If your theme already contains a 404.php file, rename it to something like “404_ORIGINAL.php” and then add the custom 404.php file.

Step 3: Create the WordPress Pages

At this point, 404 errors should be getting recorded in the database, and your custom 404 page should be displayed whenever there’s an error. This is pretty useful as-is, but we also want to display the errors on a page somewhere so we can keep an eye on things.

To display the results from our error_log database table, we need to create two pages in WordPress:

  • Display Page – a private page used to display the Ajax Error Log
  • Processing Page – a hidden page used to generate data for the Display Page

So create these two pages in the WordPress Admin and name them something like “Display Page” and “Process Page” (or whatever). Note the URL for each of these pages for later use.

Step 4: Create the Page Templates

The next step is to add the two page templates to your WordPress theme files. First, create a theme template file named something like “page-ajax-process.php” and add the following code:

Template Name: Ajax Error Log - Processing Script
Dynamic Error Logging by Jeff Starr @ Perishable Press
Project URL: https://perishablepress.com/ajax-error-log/
License: GNU General Public License
Version: 1.0

// site URL (no trailing slash!)
$website = "http://example.com";

// create the sql query
$query = 'SELECT id,logtime,request,referer,qstring,address,agent,error
 FROM error_log ORDER BY id DESC LIMIT 50'; // defaults to 50 entries

// execute query and return records
$result = @mysql_query($query);
$number = @mysql_num_rows($result);

// display the results
while($row = mysql_fetch_array($result)) {
	echo '<div class="log-entry"><pre>';
	echo 'Error: '.htmlspecialchars($row['error']);
	echo ' - '.htmlspecialchars($row['logtime'])."\n";
	echo 'Request: '.$website.htmlspecialchars($row['request'])."\n";
	echo 'User Agent: '.htmlspecialchars($row['agent'])."\n";
	echo 'IP Address: '.htmlspecialchars($row['address']);
	echo '</pre></div>';

Only one edit to make: the $website variable needs set to your site’s URL. Once you’ve done that, save the file and upload it to the server. Then visit your newly created “Processing Page” in the WordPress Admin and set the page template to “Ajax Error Log - Processing Script”.

Next, create a second page template in your theme files and name it something like “page-ajax-display.php”. Inside that file, place the following code:

Template Name: Ajax Error Log - Display Results
Dynamic Error Logging by Jeff Starr @ Perishable Press
Project URL: https://perishablepress.com/ajax-error-log/
License: GNU General Public License
Version: 1.0

<?php get_header(); ?>

	<div id="ajax-error-display">
			#ajax-error-display { width: 735px; margin: 0 auto; }
			pre {
				font: 10px/1.5 Courier, "Courier New", mono;
				background-color: #efefef; border: 1px solid #ccc;
				width: 700px; margin: 7px; padding: 10px;
				white-space: pre-wrap;
		<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js"></script>
			$(document).ready(function() {
				var refreshId = setInterval(function() {
				}, 2000); // refresh time (default = 2000 ms = 2 seconds)
		<noscript><div id="response"><h1>JavaScript is required for this demo.</h1></div></noscript>
		<div id="results"></div>

<?php get_footer(); ?>

Only one edit is required for this code to work – change the /wordpress/ajax-error-log-process/ path in the jQuery snippet to match the permalink of your own processing page. Once you’ve got that, just save the file and upload to your server. Then visit your newly created “Display Page” in the WordPress Admin and set the page template to “Ajax Error Log - Display Results”.

Note that jQuery is included from Google’s API server. If you’re sure that jQuery is already included elsewhere on the page, then you should delete (or comment out) the following line in the code:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js"></script>

Viewing your site’s errors

That’s pretty much it. At this point everything should be up and running. You can view the 404 errors for your site by visiting your new Display Page. To trigger some test errors, visit a URL on your site that doesn’t exist, like http://your-site.com/thereisnowaythispageexistsonyourserver or whatever. Once you’re sure it’s all working properly, open the Display page in a new window to keep an eye on your site’s 404 errors, which are also stored in your database for extended use.

As discussed in the original tutorial, there are ton of possibilities for this technique, which by default is very basic. Once you get everything up and running, I encourage you to experiment, modify, and customize the technique to suit your needs.

Live Demo

To the Ajax Error Log working on a live WordPress site, do the following:

  1. Open the Demo Page in a new window (not tab)
  2. With both the current browser window and the Demo Page window in view, click this link to trigger a 404 error (please click only once or twice :)
  3. Watch the 404 error magically appear in the Ajax Error Log


As with the non-WordPress tutorial, please only click the error link a few times to get the idea and see it working. Then if you like the effect, grab the files and roll one up for yourself. It’s really pretty basic stuff, but you don’t want to make the log display file public like I’m doing with the Demo. Keeping the Display Page private helps minimize potential server load.

Note that as of 2015/04/26, this demo actually is the demo used for the regular Ajax Error Log (i.e., non-WordPress version). The underlying logic is the the same, but the steps to get there are a bit different. In either case, the end result basically is the same.

Download the files

Here you may download the source files for Ajax Error Log for WordPress.

Electric eye on you..

In this Perishable Press tutorial, we’ve seen how to implement my dynamic error logging technique in an existing WordPress site. Much more information is available in the original article, so check there for all the gory details. If you have questions, concerns, or improvements, please explain in the comments or send via email. Muchas gracias, señors and señoritas! ;)

About the Author
Jeff Starr = Web Developer. Book Author. Secretly Important.
WP Themes In Depth: Build and sell awesome WordPress themes.

10 responses to “Ajax-Powered Error Logs for WordPress”

  1. Just installed it and already discovered a missing file in Yoast’s Google Analytics for WordPress plugin. Already contacted him about it :)

  2. I’m not lucky this time with the script. I get this error for line 30 till 35

    Warning: mysql_real_escape_string() [function.mysql-real-escape-string]: Access denied for user 'apache'@'localhost' (using password: NO) in /home/deb42336n2/domains/xxxxx.com/public_html/blog/wp-content/themes/xxxxx/404.php on line 30

    Did I miss something?

  3. Jeff Starr 2011/07/12 9:53 am

    Not sure.. it looks like it has something to do with that function requiring a database connection to filter the data.

    To workaround (until I have time to look closer), try replacing each instance of mysql_real_escape_string with mysql_escape_string, which is deprecated but should work for now.

    Note to others who may be reading: the script works fine, it just throws a “warning” error because of the way WP is connected to the database.

    • The good thing is that the error messages are gone.
      The bad thing is that nothing is written in the database.

      I followed the steps (twice) exactly. I really want this to work, but I am stuck now. What else could it be?

      There are no 404 re-directions in my htaccess, the url is right in 404.php, table is created in the database by executing the query, 404.php is in the theme folder.

      • Jeff Starr 2011/07/12 3:30 pm

        Hmmm.. not sure. When I setup the Demo for the tutorial, it was done using a default/vanilla install of WordPress.

        Let me ask you this, when you trigger the 404 errors when testing, do you see the custom 404 error page from the tutorial, or something else?

  4. Yeah, it’s the default WP 3.2.1 right now.

    Besides the result of this echo “Requested URL: ” . $website . $request_esc
    I also get a list with all my pages and a search field. Where does that come from? Could be it…

    • Jeff Starr 2011/07/12 3:58 pm

      Yeah I really don’t know what the issue could be.. I would look into it, but time is scarce these days. Maybe look at the custom 404.php file and see if that’s producing the error page you’re seeing. If not, you may find some clues to go on..

  5. The extra content was from the sidebar. I don’t use one on my website.
    So, content is gone. Guess I have to study on why the errors don’t end up in the database…

    Thanks anyway for your time, Jeff.

  6. why not just do some nasty bootstraping using wp-config.php instead? instant DB connection, instant $wpdb! ;)

    cu, w0lf.

  7. Drew Clardy 2011/07/19 11:44 am


    I have implemented all of this, but I am unable to get the display page to load the information from the processing page. Do you have any ideas as to what it could be? In the demo files and code snippets, the script is slightly different, but I can’t get either one to work for me. I have the processing page at /processing/. I put that in the script, but it will not load the data from the processing sheet.

Comments are closed for this post. Something to add? Let me know.
Perishable Press is operated by Jeff Starr, a professional web developer and book author with two decades of experience. Here you will find posts about web development, WordPress, security, and more »
The Tao of WordPress: Master the art of WordPress.
Crazy that we’re almost halfway thru 2024.
I live right next door to the absolute loudest car in town. And the owner loves to drive it.
8G Firewall now out of beta testing, ready for use on production sites.
It's all about that ad revenue baby.
Note to self: encrypting 500 GB of data on my iMac takes around 8 hours.
Getting back into things after a bit of a break. Currently 7° F outside. Chillz.
Get news, updates, deals & tips via email.
Email kept private. Easy unsubscribe anytime.