AJAX Logging if JavaScript is Enabled
January 12th, 2006
This tutorial describes a method of tracking JavaScript usage using AJAX on an established PHP/MySQL web site.
[Note:] Please send questions, error corrections, or bugs in this article to Steve Stringer.
Until recently, it has been nearly impossible to log if a site user has JavaScript disabled. Sure, you can use clever combinations of
AJAX changes that. By using a simple JavaScript technique that calls a PHP script, you are able to trigger the log. This tutorial will walk you through the steps necessary to implement this script.
Overview
Our goal is to determine the percentage of site visitors who have JavaScript enabled in their browser.
The basic structure of this technique is as follows:
- Determine if the visitor has been here before. If so, clean out any previous entries.
- Log the page visit via normal PHP
- Trigger a nearly identical log entry via a JavaScript function
- Compare the two after the fact; matched record pairs indicate that JavaScript was active, singleton entries indicate that it was disabled.
To increase the accuracy of the script, we want to track JavaScript usage on a per-user basis, not a per hit basis. Why is this necessary?
Let’s say visitor A has JavaScript disabled but hits the site 10 times. Now let’s say visitor B has JavaScript enabled but hits the site only once. If we logged every hit, our results would say that 90% of the site’s visitors have JavaScript disabled when in actuality the number should be 50%. This is a simplified example, but it shows the importance of logging only the most recent visit from any given user.
In order to accomplish this, we’ll tap into the existing user log in system of the site. This technique is dependent upon such a system, the implementation of which is well outside the scope of this tutorial.
Code Walk-through
MySQL Setup and Support Functions
Before we get started, we need to set up the table in your database. Assuming you are using MySQL, the following SQL code will create the table used to log the records.
1 2 3 4 5 6 |
CREATE TABLE `log_js` ( `log_jsId` int(11) NOT NULL auto_increment, `log_jsKey` varchar(14) default NULL, `userId` int(11) default NULL, PRIMARY KEY (`log_jsId`) ) TYPE=MyISAM AUTO_INCREMENT=1 ; |
Establish a Connection to Your Database
We assume you have made a secure connection to your elsewhere. For this tutorial, our variables are:
1 2 3 4 5 6 |
$hostname = "localhost"; $database = "[your database]"; $username = "[your username]"; $password = "[your password]"; |
You would connect to your database with the mysql_pcconnect function, and you’d select your database with the mysql_select_db function:
1 2 3 4 5 |
$my_db = mysql_pconnect($hostname, $username, $password) or trigger_error(mysql_error(),E_USER_ERROR); mysql_select_db($database, $my_db); |
If you use Dreamweaver, these values will be set in the Connections/[yoursite].php file.
Support Functions
Next, we need a function that will let us create a unique key for each record pair. Anything will do, but I use a timestamp with the epochStamp function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
function epochStamp() { // epochStamp() returns a unix timestamp in the yyyymmddhhmmss format. $today = getdate(); $y = $today['year']; $m = $today['mon']; if(strlen($m)==1) { $m = "0".$m; }; $d = $today['mday']; if(strlen($d)==1) { $d = "0".$d; }; $h = $today['hours']; if(strlen($h)==1) { $h = '0'.$h; } $min = $today['minutes']; if(strlen($min)==1) { $min = '0'.$min; } $s = $today['seconds']; if(strlen($s)==1) { $s = '0'.$s; } return ($y.$m.$d.$h.$min.$s); } |
The AJAX JavaScript
This code is adapted from the “30 Second AJAX Tutorial” originally posted on rajshekhar.net.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
// This script is adapted from the "30 Second AJAX Tutorial" // originally posted on rajshekhar.net. // This function establishes how the XMLHTTP request will be handled // depending on whether the client is using IE or not. function createRequestObject() { var req; var browser = navigator.appName; if(browser == "Microsoft Internet Explorer"){ req = new ActiveXObject("Microsoft.XMLHTTP"); }else{ req = new XMLHttpRequest(); } return req; } var http = createRequestObject(); // Next, we handle the triggered event. In this case, if JavaScript // is enabled, we will send the request and wait for a response. function sndReq(procpage) { http.open('get', procpage); http.onreadystatechange = handleResponse; http.send(null); } // Normally, you would do something to handle the response from the // PHP request. In this case, we need to track only debugging // information should something go wrong. function handleResponse() { if(http.readyState == 4 && http.responseText!=''){ //alert(http.responseText); // uncomment to help debug your script } } |
User Log In
As mentioned before, we assume you use at least a rudimentary user login method. The user’s login id will be stored in the $userid variable used below.
Log the visit (Part 1)
Now that the housekeeping is out of the way, we’re ready to log the visit. This bit of code can be stuck in the header below the user login code or just above the AJAX part of this script.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// $jslogkey is a unique key that will be used to identify both entries // in the record pair $jslogkey = epochstamp(); // We look to see if the user is logged in. If he is, $userid will be // specified by your code elsewhere (not included here) if($userid!='') { $deleteSQL = sprintf("DELETE FROM log_js WHERE userId=%s", $userid); $Result1 = mysql_query($deleteSQL, $my_db) or die(mysql_error()); // now we log the visit using the unique key and the user id $insertSQL = sprintf("INSERT INTO log_js (log_jsKey, userId) VALUES ('%s', %s)", $jslogkey, $userid); $Result1 = mysql_query($insertSQL, $my_db) or die(mysql_error()); } |
Log the Visit (Part 2)
Determining if a visitor is using JavaScript or not after the fact is a bit tricky. We do this by logging the visit in pairs; the first log is by standard PHP (above). The second part is triggered by a JavaScript AJAX technique (below). We know when querying the log table at some future point that if we get a pair of entries, JavaScript was enabled, but if we get only one entry, we can deduce it wasn’t.
The AJAX technique triggers a remote page call via an XMLHTTPRequest. Don’t worry. We aren’t actually using or parsing any XML, but the function does allow us to call a PHP page that runs in its own scope via JavaScript.
First, create a page called “log_js.php.” I’ve placed this file in the ‘include’ directory, but it can go anywhere–just be sure to update the link in the JavaScript below. The “log_js.php” file contains the following code:
1 2 3 4 5 6 7 8 9 10 11 |
include('./config.inc.php'); // log javascript usage, pt 1 $jslogkey = $_GET['key']; $id = $_GET['id']; $agent = urldecode($_GET['agent']); $insertSQL = sprintf("INSERT INTO log_js (log_jsKey, userId, log_jsAgent) VALUES ('%s', '%s', '%s')", $jslogkey, $id, $agent); $Result1 = mysql_query($insertSQL, $my_db) or die(mysql_error()); |
This code does exactly the same thing as Part 1. Note that this script runs in its own scope, so you need to call any database or configuration settings again (done in this example in my “config.inc.php” file).
Now, back on our main page, we call the “log_js.php” file with the following JavaScript:
1 2 3 4 5 6 7 |
$queryStr = 'key='.$jslogkey.'&id='.$userid; |
This second trigger will use the same unique key ($jslogkey) and the $userid from your login system.
Looking at the Results
After your script has run for a period of time, you should amass enough entries to create a statistically signficant percentage of users who do and do not have JavaScript activated.
Note that because we expect and require a $userid to be set, this technique will necessarily exclude bots, crawlers, and other non-human visitors to your site.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// get JavaScript Log $query_js = "SELECT Count(log_jsKey) AS keyCount FROM log_js "; $query_js .= "WHERE userId Is Not Null GROUP BY userId;"; $all_js = mysql_query($js, $my_db) or die(mysql_error()); $row_all_js = mysql_fetch_assoc($all_js); $js_on = 0; $js_off = 0; do { switch($row_all_js['keyCount']) { case(1): $js_off++; break; case(2): $js_on++; break; } } while ($row_all_js = mysql_fetch_assoc($all_js)); $js_total = number_format($js_off + $js_on, 0, '.', ','); $js_on_percent = round(($js_on / $js_total * 100),0).'%'; $js_off_percent = round(($js_off / $js_total * 100),0).'%'; |
The query groups key pairs, and the value ‘keyCount’ will produce either a value of 1 (no JavaScript) or 2 (match pairs indicating JavaScript was enabled). The switch function loops through the results and sums the results. The final tallies can be displayed in a table using the various $js variables:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
||
| JS On: | echo $js_on.‘ (‘.$js_on_percent .‘)‘ | ||
|---|---|---|---|
| JS Off: | echo $js_off.‘ (‘.$js_off_percent .‘)‘ |
Findings and Conclusion
In my own research, I have found the JavaScript usage rate to be between 95% and 98%.
Note that various factors can be at play here such as incomplete page loads or other factors that make the final results less an exact science and more of an inference. With the help of this AJAX technique, it is now possible to get a much more precise number than ever before.
Sphere: Related Content


