...

View Full Version : Trying to Calculate the Read Time For A Page



DrDel
01-24-2006, 06:31 AM
I am trying to track the amount of time a user spends reading a specific webpage

I have decided on using an onClose call to the function called closeTime()

The code on the viewing page is:

<script type="text/javascript" language="javascript">
function closeTime() {

var closeTime = getTime();
var http;

if (window.XMLHttpRequest) { // Mozilla, Safari, ...
http = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
http = new ActiveXObject("Microsoft.XMLHTTP");
}

http.open('GET', 'inc/savetime.php?closeTime=' + getTime(), true);
http.send(null);

http.onreadystatechange = function() {
if (http.readyState == 4) {
document.getElementById('some_div_id').innerHTML = http.responseText;
}
}


}

</script>


</head>

<body onClose="closeTime();">


when I close this script NOTHING happens

I even put an alert box in there and no alert box pops up .. I am using Firefox

what am I doingwrong?

glenngv
01-24-2006, 06:55 AM
Use onunload. But the page may have finished unloading even before the script finishes executing. Try opening savetime.php in a small window onunload. Though popup blockers will block the popup.

DrDel
01-24-2006, 03:43 PM
so I did this:


<body onUnload="closeTime();">


and it still doesn't execute when I close the browser

I am using Firefox 1.5

Javascipt is enabled since JS works on other sites

can someone help me please?

felgall
01-24-2006, 09:40 PM
The browser is being closed too quickly to record any of the info you are after. There is no way to get around this.

They may have just left the page sitting there for half an hour during their tea break and remembered to close it when they came back so even if you did record a duration it will be meaningless.

DrDel
01-25-2006, 06:53 AM
browser closing too fast?

that is ridiculous!

what would be the purpose of onCLose or onUnload then?

it isnt executign for another reason

liorean
01-25-2006, 10:17 AM
The purpose of the unload even is to be able to clean up after you, and notifying other windows that you are being closed. The JavaScript environment will be intact, but there is no guarantee that the actual window object or any part of the DOM is still in place. Also, browsers may lock the environment so that you can't create new variables or change variables in that document since it's about to rip it apart.

DrDel
01-26-2006, 12:28 AM
there must be SOMEONE out there who can suggest a way to solve this problem.

How can one calculate the time it took a reader to read a webpage?

any answers?

glenngv
01-26-2006, 05:37 AM
Just have a button at the bottom of the page that says [Done] which when clicked calls your closeTime() function.

SpirtOfGrandeur
01-26-2006, 12:15 PM
The browser is being closed too quickly to record any of the info you are after. There is no way to get around this.
That is completely untrue. Sorry, it has to be said. An event should happen no matter what. I have tested what you have done (using my own ajax code) and I can get it to work in IE 5.5, IE 6.0 and FF 1.5, but Opera 8.51 is a bit more of a problem.

QuirksMode (http://www.quirksmode.org/js/events_compinfo.html)

In Opera load and unload do not fire when the user uses Back or Forward to enter or leave a page, or when the user closes the window.
This severely hampers the usefulness of the events. When I write a load or unload script to, for instance, adjust the navigation of this site, I want it to run whenever the user enters or leaves the page, and not just when a browser thinks it's appropriate.
Therefore I judge Opera's support Minimal and not Incomplete.

The actual problem you are running into is that you are trying to get the info back. If you put the code (or code like it, as I ran) you get a JS error because you set a function to the 'onreadystatechange' which is causing an error.

Error: [Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIXMLHttpRequest.status]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)" location: "JS frame :: http://xxx/javascript/AJAX.js :: CreateAJAX_Response :: line 118" data: no]
Source File: http://xxx/javascript/AJAX.js
Line: 118


Granted I have a core routine that is called every time, but it is trying to set the 'onreadystatechange' which is causing an error. Actually this question helped me fix my code. Now when I send my core function a null I make sure to set the 'onreadystatechange' to null.

I hope this helps. I would also like to make a suggestion of not sending a date and time string through the URL. Either post it, or just send the Milliseconds difference between the two times (onload and onunload). This way you make sure that you are getting an accurate reading each time. If you send a time to the server the servers clock might be different from the clients clock.



var startTime = null;
window.onload = function () {
startTime = new Date();
}

//window.onbeforeunload = function ( ) {
window.onunload = function ( ) {
var endTime = new Date();
var milDiff = Math.abs(startTime - endTime);
alert( milDiff );
//This is my function for my very core ajax control, donít mind it for it does a lot of work in the background
//CreateAJAX('./ajax.asp?fun=testTime&value=' + milDiff , null );

}

I noticed that my AJAX function was being called two times, I am sure this will be an easy fix and I do not have the time to do it. I hope this has answered your question correctly. I can be reached via PM if you have any more questions.

glenngv
01-27-2006, 04:04 AM
That is completely untrue. Sorry, it has to be said. An event should happen no matter what. I have tested what you have done (using my own ajax code) and I can get it to work in IE 5.5, IE 6.0 and FF 1.5, but Opera 8.51 is a bit more of a problem.
QuirksMode (http://www.quirksmode.org/js/events_compinfo.html)
Does it work consistently? It's all about timing. It may work sometimes or not. It depends on how long the processing in the server takes place. And if you have an alert in the onunload function, it may work more consistently as the script execution is delayed by the alert.

arnyinc
01-27-2006, 04:24 AM
How specific does the time have to be? You can have a timer that runs and reports every minute or so. You wouldn't have the exact time, but you could get within a minute.

SpirtOfGrandeur
01-27-2006, 04:42 AM
Does it work consistently? It's all about timing. It may work sometimes or not. It depends on how long the processing in the server takes place. And if you have an alert in the onunload function, it may work more consistently as the script execution is delayed by the alert.

glenngv, I just put the alert in there to show him the number I was sending. I never run an alert in an onunload event. And I always wrap my onunload's in try/catches to make sure the user never has to deal with the inconvenience of a popup that happens when you try to close the window.

Yes it works 100% of the time on FF and IE. The reason for this is that it can make the page call just before the browser unloads and does not care about the response. So in essence it makes a call to the web server then disconnects itself from it. I do not know why it is running 2 times though. It runs twice on both IE and FF. Then again it could be my code, but I have checked it toughly.

This same theory also works with IFRAMES. You can do the same thing if the user does not have an XMLHTTPREQUEST Object. You can create an IFRAME instead and call a url and a load. Have a pause of about 20 (a for loop with a counter of 20) to make sure the IFRAME has had time to load (It is a slower connection then the XMLHTTPREQUEST Object). And it will also work.

I have been using these objects for about 3 years now. I program full pages in AJAX (I love buzz words) all day long. I have so many widgets that use these objects. The one I have that is the closest related to this subject is a page load time (From the connection to the page ASP/PHP, until the page is done displaying on the clientís computer) to test my server on international connections. I have now made one that works to show how long some one has been viewing a page, thanks for the idea DrDel. I do use the onload, and onunload a lot (No I do not support Opera due to their limitations). I just thought of a hint I should share, to be safer you should use the onbeforeunload because there are some limitations to the onunload, but I highly doubt these limitations would be met by a timer script.

Hopefully this helps!

DrDel
01-27-2006, 07:15 AM
I appreciate your code SpiritofGrandeur

I tried it out using FF1.5 and MIE 6

nothing happens when I close the browser.. same problem as with my code -- no alert window, nothing

I don't know what the problem is... any other ideas?

thanks again for your assistance, it is much appreciated. I have searched high and low for an answer to this problem -- no one seems to have the solution save for yourself

so if this DOES work it would be a great success for a number of coders, not just me

DrDel
01-27-2006, 07:20 AM
are tabs an issue with FireFox?

If i have 6 tabs open an I close the one tab that is running the closeTime() script will it not work because I only closed the one tab ?

For what it's worth I closed all the tabs and it still doesn't popup the Alert window.. don't know why

DrDel
01-27-2006, 07:21 AM
block popups is also disabled in my browser, by the way...

arnyinc
01-27-2006, 07:27 AM
What kind of times are you expecting? Do you care what the timing is down to the second or are you just looking for a rough estimate (1, 5, 10 minutes, etc).

glenngv
01-27-2006, 09:30 AM
Aside from AJAX and Iframe techniques, there's also the image trick to send request to the server on the background and you don't care about the response.

var img = new Image();
img.src = "test.asp?fun=testTime";
Short, simple and really cross-browser.

glenngv
01-27-2006, 09:34 AM
are tabs an issue with FireFox?

If i have 6 tabs open an I close the one tab that is running the closeTime() script will it not work because I only closed the one tab ?

For what it's worth I closed all the tabs and it still doesn't popup the Alert window.. don't know why
Check the Javascript Console for any error.

SpirtOfGrandeur
01-27-2006, 02:16 PM
are tabs an issue with FireFox?

If i have 6 tabs open an I close the one tab that is running the closeTime() script will it not work because I only closed the one tab ?

For what it's worth I closed all the tabs and it still doesn't popup the Alert window.. don't know why

No, if a tab is closed the code will still run. You put my code exactly as it was and could not get an alert? That is really weird. I have about 5 differents set up's that I tested it on (all using VMWare) and it worked on all three of them.

You do not get any thing using this exact code?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test Page</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

<script type='text/javascript'>
var startTime = null;
window.onload = function () {
startTime = new Date();
}

window.onunload = function ( ) {
var endTime = new Date();
var milDiff = Math.abs(startTime - endTime);
alert( milDiff );
}
</script>
</head>
<body>
</body>
</html>

DrDel
01-28-2006, 12:00 AM
Spirit of Grandeur your code works perfectly

I think the 300 line script I was testing it in somehow conflicted with your code so I just started afresh and used your code as a test run. It works now. Thank you

I am trying to build on your code by running a PHP script that updates the mySQL database with the time difference (var milDiff ). Bascially I am trying to track what a reader reads on my site for stastical reasons.

The JS Console doesn't like my http.open('GET' command - keeps denying my persmisson to it I don't know why

Error: uncaught exception: Permission denied to call method XMLHttpRequest.open

any advice?

Here is my first attempt at anything remotely AJAX


<html>
<head>
<title>Test Page</title>
<script type='text/javascript'>
var startTime = null;
window.onload = function () {
startTime = new Date();
}

window.onunload = function ( ) {
var endTime = new Date();
var milDiff = Math.abs(startTime - endTime);
alert( milDiff );

if (window.XMLHttpRequest) { // Mozilla, Safari, ...
http = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
http = new ActiveXObject("Microsoft.XMLHTTP");
}

http.open('GET', 'http://www.foo.com/path/savetime.php?readTime=' +milDiff, true);

http.onreadystatechange = function() {
if (http.readyState == 4) {
document.getElementById('some_div_id').innerHTML = http.responseText;
}

}
}
</script>
</head>
<body >
</body>
</html>

SpirtOfGrandeur
01-28-2006, 12:52 AM
The problem is not with your 'http.get()' the problem is in your 'http.onreadystatechange' you cannot set a function to this in the onunload function. It must be null. You cannot get a responce from your 'http' object.

DrDel
01-28-2006, 01:13 AM
I am so close it's killing me.

here is my JS code which is working now:


<script type="text/javascript" language="javascript">
var startTime = null;
window.onload = function () {
startTime = new Date();
}

window.onunload = function ( ) {
var http;
var endTime = new Date();
var milDiff = Math.abs(startTime - endTime);

if (window.XMLHttpRequest) { // Mozilla, Safari, ...
http = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
http = new ActiveXObject("Microsoft.XMLHTTP");
}

http.open('GET', 'inc/savetime.php?readTime=' +milDiff, true);
http.send(null);

}
</script>

It runs without errors.

Here is my savetime.php script:


<?php

include("connect.php");

$sqlReadTime = "UPDATE auserfeeds SET readTime = $readTime WHERE rssfile = 'http://www.bluesnews.com/news/news_1_0.rdf' && userid = 1";

// $sqlReadTime = "UPDATE auserfeeds SET readTime = $readTime WHERE rssfile = '$feed' && userid = $_SESSION[userid]";

$resultReadTime = mysql_query($sqlReadTime) or die ($sqlReadTime);

echo $sqlReadTime;

?>

The mySQL readTime field gets updated with the milDiff value if I use the first SELECT statement (the one that isn't commented out)

But if I use the second SELECT statement (thereby commenting it out) it doesn't update. If I echo $sqlReadTime using the second SELECT statement in the body of the script it shows up blank; as if the UPDATE comand is NULL.

I am successfully logged in when I am doing this. Any ideas?

Even if I passed the $feed variable and the $_SESSION[userid] value the echo $sqlReadTime should give me a mySQL UPDATE error -- right now it isn't printing anything at all.


UPDATE: My answer to my own question would be(I think, correct me if I am wrong) the page is already rendered so the var value won't be printed. I would have to output it somehow using Javascript, is that correct?

SpirtOfGrandeur
01-28-2006, 01:42 AM
Can you use && as an and? I did not think you could.

DrDel
01-28-2006, 01:46 AM
yes you can use && as an AND in mySQL

the mySQL syntax works fine -- if I query mySQL via phpmyadmin it updates correctly, so the mySQL isnt the problem

the problem is with the second UPDATE statement

the minute I substitute an absolute feed with the var $feed the UPDATE statement no longer works

SOG can I talk to you via MSN? it would be a lot easier

SpirtOfGrandeur
01-28-2006, 01:55 AM
I am not a php guy. You might want to post over there. I havent used PHP in about a year and I am slowly losing my memories of it.

DrDel
01-28-2006, 11:58 PM
I got it working SOG

I used a combination of PHP, Javascript and cookies

it updates very nicely and I have a preset timeout function so that if the user goes idle for more than X minutes the read time stops

thanks for all your help SOG

SpirtOfGrandeur
01-29-2006, 07:33 AM
thanks for all your help SOG

Not a problem. I do enjoy helping people on things that most people say cannot be done ;)



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum