Howto Create a Hit Counter Using a Text File

If you have a live Web site on the World Wide Web, you may be interested in how many people are visiting your site. You can of course analyze the log files of your Web server but that information is usually difficult to read. The log files contain information for each and every request a visitor has made to your site, including resources like images, Flash movies and so on. This makes it near impossible to extract information about individual users. It would be a lot easier if you could count the number of individual users that have visited you since you started your site. It would also be useful if you could see the number of users that are currently browsing your site.

This article will show you how to accomplish these two tasks by storing the hit counters in Application variables and in a text file using code in the global.asa file. This article extends the ideas from a previous article where the values of the counters were just stored in Application variables. By writing the counters to a file you can maintain their values, even when you restart the Web server.

There is also an ASP.NET version of this article available.

Prerequisites

The code in this article uses Sessions in ASP, so you'll need to have them enabled on your server. See the References section at the end of this article for more information. You'll also need to have access to a file called global.asa in the root of your site. If you run your own Web server, this is not a problem; you can simply create the file yourself. If you are using an ISP, you'll need to check with them if they support the use of the global.asa file as, unfortunately, not all ISPs allow this. You'll also need to be able to write to a text file from within the global.asa file. This means that the account your Web site is running under (usually, IUSR_MachineName where MachineName is the name of your computer) needs sufficient permissions to write to the file. Finally, most Anti-virus software come with a "Script blocking" feature, that disables writing to text files from within ASP pages. If you find that your files are not written at all, you may need to disable this feature. Alternatively, read this article that explains how to store your counters in a database.

Counting Users

Just as in the article where the counters were stored in just the Application object, you can make use of the Session_OnStart event, defined in the global.asa file to keep track of your users. This event is fired whenever a user requests the first page in your Web site. This way, you have the ability to count each unique visitor only once during their visit. As long as the Session remains active on the server, the user won't be counted again. After the Session has timed out (it will automatically time out after a certain interval when no new pages have been requested) or has been explicitly ended, a request to a page will create a new Session, Session_OnStart will fire and the user will be counted again.

To keep track of the total number of users that have visited your site since you started the Web server, you can increase a counter for each request a user makes. Let's call this counter TotalNumberOfUsers. You can store that counter in a variable in Application state, so you can retrieve and display it on other pages in your site. You can also create a second counter, called CurrentNumberOfUsers for example, that counts the number of active Sessions on your server. Just as with TotalNumberOfUsers, you increase the value of this counter whenever a new Session is started. However, you should decrease its value again when the Session ends. so you can keep track of the number of users that are currently visiting your site.

Besides storing these values in the Application object, you can also write them to a text file. When your server is restarted, code in the global.asa file will read in the old values from the text file, so your counters will continue with the values they had before the restart.

Let's take a look at how you can accomplish all this:

Start by creating a file called global.asa (note that the extension is different from ordinary ASP pages) and save it in the root of your Web site. Open the file in Notepad or in your favorite editor, and make sure it's completely empty (it shouldn't contain any ASP or HTML tags). Add the following ASP code to the file:

<script language="vbscript" runat="server">
Sub Session_OnStart

End Sub

Sub Session_OnEnd

End Sub
</script>
This code defines the skeleton for the two methods that fire when a new Session is started and when a Session ends. You can add the code for the counters to these two Subs. To keep track of the total number of users and the current number of users, you'll need to add the following shaded lines of code that create two Application variables. Once the variables have been increased and stored in the Application object, the value for the total number of users is saved to a text file called Counter.txt in the root of your site:

<script language="vbscript" runat="server">
Sub Session_OnStart
  Application.Lock
  Application("TotalNumberOfUsers") = _
      Application("TotalNumberOfUsers") + 1
  Application("CurrentNumberOfUsers") = _
      Application("CurrentNumberOfUsers") + 1
  Application.Unlock

  ' Values have been increased. Now write them to a text file as well
  Dim aFSO ' As FileSystemObject
  Dim aFile ' As Scripting.TextStream
  Set aFSO = Server.CreateObject("Scripting.FileSystemObject")
  Set aFile = aFSO.CreateTextFile(Server.MapPath("/") & _
       "\Counter.txt", True)
  aFile.Write ("TOTAL" & vbTab & Application("TotalNumberOfUsers"))
  aFile.Close
  Set aFile = Nothing
  Set aFSO = Nothing
End Sub
When a user starts a new Session by requesting a page in your site, the code in the Session_OnStart event will fire. This code will lock the Application object temporarily, to prevent two users from writing to it at the same time. Then the Application variables TotalNumberOfUsers and CurrentNumberOfUsers are increased by one. Once they are increased, the Application is unlocked again, so it's available to other users.

The second block of code in the Session_OnStart event writes this value to a text file. The FileSystemObject is used to create the file, using its CreateTextFile method. This method expects two parameters: the name of the text file (created by using Server.MapPath and appending Counter.txt to it) and a boolean indicating whether the file can be overwritten if it already exists. In this example True is passed, so you'll end up with a new file each time the Session_OnStart event fires. This way, you can be sure you always have just a single line of text in this file, because the old one is overwriiten.
Once the file is created and opened, the Write method of the TextStream object is used to write the value of the counter to the text file. When that is done, the file is closed and all objects are set to Nothing to clean up resources.

Notice that just the value of the TotalNumberOfUsers counter is written to the text fiile. There is no need to store the current number of users; after all, when the Web server is restarted, there are no current users yet.

To decrease the counter for the CurrentNumberOfUsers, you'll need to add some code to the Session_OnEnd event, that will fire when a Session times out, or when it is explicitly ended. You should just decrease the value for CurrentNumberOfUsers, and leave TotalNumberOfUsers untouched. Add the following shaded lines of code to the Session_OnEnd event in your global.asa file:

    Application.Unlock
End Sub

Sub Session_OnEnd
    Application.Lock
    Application("CurrentNumberOfUsers") = _
         Application("CurrentNumberOfUsers") - 1
    Application.Unlock
End Sub
</script>
Whenever a Session is ended, the value of CurrentNumberOfUsers is decreased by one. This way, its value will always reflect the number of users that are browsing your site right now.

Reading the Counter When the Web Server Starts

As long as the Web server keeps running, this code will run fine. For each new Session that is created, the counters are increased by one and the value of TotalNumberOfUsers is written to the file. If, however, the Web server stops unexpectedly, or your restart or reboot the Web server yourself, the values for TotalNumberOfUsers and CurrentNumberOfUsers are lost. But because the value for TotalNumberOfUsers has also been stored in a text file, it's easy to retrieve the counter again from that file when the Web server starts. To read in the value from the Counter.txt file, you'll need to add some code to the Application_OnStart event that is also defined in the global.asa. Add the following code to the end of the global.asa file, right before the closing </script> tag:

End Sub

Sub Application_OnStart
  ' Web server is started. See if counter file exists,
  ' and if it does, read in its value:
  Dim aFSO ' As FileSystemObject
  Dim aFile ' As Scripting.TextStream
  Dim Result
  Dim ArrResults
  Set aFSO = Server.CreateObject("Scripting.FileSystemObject")
  If (aFSO.FileExists(Server.MapPath("/") & "\Counter.txt")) Then
    ' File exists, grab its contents.
    Set aFile = aFSO.OpenTextFile(Server.MapPath("/") & "\Counter.txt")
    Result = aFile.ReadLine()
    If Len(Result) > 0 Then
      ArrResults = Split(Result, vbTab)
      If IsArray(ArrResults) Then
        If UBound(ArrResults) = 1 Then
          Application("TotalNumberOfUsers") = ArrResults(1)
        End If
      End If
    End if
    aFile.Close
    Set aFile = Nothing
  End If
  Set aFSO = Nothing
End Sub
</script>
The code looks a bit complicated, but it's actually rather simple. The FileSystemObject is used again to see if the counter file exists. If it doesn't, the code simply does nothing. If it does exist, a TextStream object reads the first line from the file into a string called Result. If the line contained some text (the Len of the string Result is greater than zero) this line of text is split into two elements. If you look at the code that writes to the file in the beginning of this article, you can see that the word TOTAL, then a Tab and then the value are written to the file. Since all you're interested in is the value for the counter, you'll need to split the line in two elements; both sides of the Tab character. If the UBound (or Upper Bound, the index of the greatest element in the array) of ArrResults equals 1 (this means two elements, item 0 and item 1) you can be sure you read in a valid line. The second element, ArrResults(1), is then used as the new value for the Application variable TotalNumberOfUsers.

It would have been easier to leave out the TOTAL in the text file, so there is no need to split the line of text you retrieved from the file. I did include it in this example though, because it can be useful if you want to store multiple counters in the same text file. This way, you can save individual counters as TOTALUSERS, TOTALDOWNLOADS and so on all in the same file, while you can still see which value means what.

At the end, the file is closed and the objects are cleaned up again, just as in the code for the Session_OnStart event.

Testing it Out

To test out your hit counter, create a new ASP file and call it Counter.asp. You can save it anywhere in your site. Add the following ASP code to that page:

Total number of visitors: <%=Application("CurrentNumberOfUsers")%><br>
Current visitors: <%=Application("TotalNumberOfUsers")%>
These two lines of code write out the total number of visitors and the current number of visitors. Open the page in your browser and you'll see there is one current user. Also, the total number of users is 1. Open another browser (don't use Ctrl+N, but start a fresh instance or use an entirely different brand of browser) and open the counter page. You'll see there are two current users, and two users in total.
Next, restart your Web server. If you are using IIS, you can choose Restart IIS... from the All Tasks context menu for your Web server in the IIS Management Console.
Open Counter.asp again. You'll see that currently you're the only user browsing the site, but the total number of users has maintained its value.

Summary

This article demonstrated how to create a hit counter that keeps track of the current and total number of users to your site. It stores these variables in Application state so they are available in each page in your Web site. It also stores the value for the total number of users in a text file so its value won't be lost when the Web server restarts.

A disadvantage of using text files is that it's difficult to scale out your Web site to lots of users. Only one user has access to the file at any given moment, so if you have a real busy site, you'll soon run into problems.
Check out the following article to see how you can improve the counter page even further by using a database instead of a text file.

Related Articles

References

Download Files


Where to Next?

Wonder where to go next? You can read existing comments below or you can post a comment yourself on this article .


Consider making a donation
Please consider making a donation using PayPal. Your donation helps me to pay the bills so I can keep running Imar.Spaanjaars.Com, providing fresh content as often as possible.



Feedback by Other Visitors of Imar.Spaanjaars.Com

On Thursday, February 22, 2007 8:48:29 AM atul chauhan said:
effective
On Monday, January 14, 2008 5:39:22 PM kidist said:
it is an axcellent article,
but i was trying to modify the code for specific logIn page only. such as to keep track of only the number of people who are loged on. Could you give me some sujestion on that please?
thank you
kidist
On Monday, January 14, 2008 5:50:48 PM Imar Spaanjaars said:
Hi there,

You can use the exact same principle. However, instead of doing this in Session_OnStart, you do it in the Login page.

Cheers,

Imar
On Friday, April 04, 2008 12:05:19 AM Andrew said:
Is there an easy way to track visits for a specific month? I'm using the text file as you have in your code but instead of TOTAL, I'm saving the month to the text file using Month(Now) and when comparing I do:

If ArrResults(0) = Month(Now) Then 'and so on

but I'm not quite getting the results I want. When I intentionally change the month so that it's 3 (March) instead of 4 (April), I want it to start counting from 1 and change the month to the current month - this works fine but I still get whatever the current total visitors are (like 7) instead of a fresh count from 1.

I believe my problem lies is in the program flow or logic. How would you go about this?
On Saturday, April 05, 2008 10:17:02 AM Imar Spaanjaars said:
Hi Andrew,

You could use a dictionary object:

http://www.4guysfromrolla.com/webtech/102898-1.shtml

and then use Year + Month as the key.

Hope this helps,

Imar

Talk Back! Comment on Imar.Spaanjaars.Com

I am interested in what you have to say about this article. Feel free to post any comments, remarks or questions you may have about this article. The Talk Back feature is not meant for technical questions that are not directly related to this article. So, a post like "Hey, can you tell me how I can upload files to a MySQL database in PHP?" is likely to be removed. Also spam and unrealistic job offers will be deleted immediately.

When you post a comment, you have to provide your name and the comment. Your e-mail address is optional and you only need to provide it if you want me to contact you. It will not be displayed along with your comment. I got sick and tired of the comment spam I was receiving, so I have protected this page with a simple calculation exercise. This means that if you want to leave a comment, you'll need to complete the calculation before you hit the Post Comment button.

If you want to object to a comment made by another visitor, be sure to contact me and I'll look into it ASAP. Don't forget to mention the page link, or the QuickDocId of the document.

For more information about the Talk Back feature, check out this news item.