We then open a new transaction because we are going to update two tables. Next, we update the the SD_Tut_Tracker table and increment the TrackerPageViews column. If the user that requested this page was new i.e, the last argument to this stored procedure was 1 (true), we also increment the TrackerUniqueUsers column. If for instance this UPDATE operation was the first operation to be carried on the SD_Tut_Tracker table, it is possible that this table may not be holding any record for the given date and time. Thus, we check the @@ROWCOUNT variable to see if any rows were affected by the UPDATE operation. If we get zero rows affected, we run an INSERT statement to insert a new record for the current date and time.
If referring domain and URL arguments are not NULL (i.e., we have a referrer website/page), we increment the referral count of that domain and URL in their corresponding tables (i.e., SD_Tut_ReferringDomains and SD_Tut_ReferringURLs).
Finally, we commit the transaction if there were no errors during the INSERT and UPDATE operations, but if there were, we rollback the transaction. That is all SD_Tut_Track stored procedure was all about. Simple stuff, eh?
Note: I assume here that you have executed each one of the stored procedures above to create them in your database. If you have executed them correctly, you should be seeing 14 stored procedures listed when you click the 'Stored Procedures' option after you've expanded the node of your database in the SQL Server Enterprise Manager as shown below.
If this is NOT the case, go back to the source code of stored procedure #1, copy it's code in the SQL Server Query Analyzer, connect to your database and hit the 'F5' key to create the stored procedure. Then delete the code from Query Analyzer field, and move to the source code of stored procedure #2. Copy it's code and then paste it in the Query Analyzer Window, and then hit the 'F5' key to create it in the database as well. Repeat the same procedure for all 14 stored procedures.

We are now finished creating the database back-end (tables and stored procedures). Our focus will now shift to the ASP.NET (C#) code that executes these stored procedures and generates reports.
Creating the ASP.NET Front-end
The ASP.NET front-end is comprised of 4 ASP.NET pages and accompanying Web.config and Global.asax files. We'll go through all of them one-by-one.
Transparent 1x1 GIF file
To log each request made by the client browser, we make use of HTML <img> tag. This tag when parsed by the client browser makes the browser request that image separately from the server. The server then sends the image file back to the browser. We'll make our ASP.NET page instead serve this request and send a tiny image back to the browser. During this process, the ASP.NET page will log the request to the database using one of the stored procedures we have already discussed.
This is a tiny 1x1 pixel image of only 43 bytes in size. It doesn't put much burden on the server bandwidth. Since this image is very small, will not be updated/written to, yet will be read/requested a lot by the client browsers, we cache this image in the memory the moment our ASP.NET Application is started. To do this we make use of Global.asax file, which we'll visit a bit later in this tutorial.
Create a new folder with the name of "images" in your ASP.NET application folder where you are/will be placing files for our Tracker application. Now, save this image in that folder as "trans.gif". To do that, first move the mouse over this link, then right-click and from the options, choose 'Save Target As' and then save the image to the "images" folder (as explained above).
Web.config
Web.config file contains configuration data/constants for an ASP.NET application. Create a new text file in Notepad and save it as Web.config file in the root folder of your ASP.NET application where you want to place all the files of the web component of our Tracker application. Now copy/paste the following code it in, then click the 'Save' button:
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings>
<add key="SD_Tut_ImageFileKeyName"
value="SD_Tut_TrackerImageFile"/>
<add key="SD_Tut_ImageFileLocation"
value="~/images/trans.gif"/>
<add key="SD_Tut_TrackerLastUpdatedCookieName"
value="SD_Tut_LastUpdated"/>
<add key="SD_Tut_TimeOffset" value="+0"/>
<add key="SD_Tut_WebSiteName"
value="ASP.NET Development Server"/>
</appSettings>
<connectionStrings>
<add name="SD_Tut_TrackerDB"
connectionString="server=;database=;user id=;password="
providerName="System.Data.SqlClient"/>
</connectionStrings>
<system.web>
<authentication mode="Windows"/>
<sessionState mode="Off"/>
<trace enabled="false"/>
</system.web>
</configuration>
Explanation
This Web.config file is a simple XML file which contains few ASP.NET application wide constants. All of it's items are kept between <configuration></configuration> tags.
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
...
</configuration>
Next comes the appSettings key which should contain ASP.NET application wide user-defined constants in the form of HashMap (key/value pairs). In our case, we define 5 constants/variables.
<appSettings>
<add key="SD_Tut_ImageFileKeyName"
value="SD_Tut_TrackerImageFile"/>
<add key="SD_Tut_ImageFileLocation"
value="~/images/trans.gif"/>
<add key="SD_Tut_TrackerLastUpdatedCookieName"
value="SD_Tut_LastUpdated"/>
<add key="SD_Tut_TimeOffset" value="+0"/>
<add key="SD_Tut_WebSiteName"
value="ASP.NET Development Server"/>
</appSettings>
The first variable 'SD_Tut_ImageFileKeyName' contains the name of the key we use to cache 1x1 pixel image in the ASP.NET's Application object. The value of this variable is trivial and for clarity's sake, we give it the value of "SD_Tut_TrackerImageFile".
Second variable is 'SD_Tut_ImageFileLocation'. It's value is the relative path to the 1x1 pixel GIF image. The tilde (~) at the beginning of the path to trans.gif (transparrent 1x1 pixel GIF file) file means the root of the current ASP.NET application.
Third variable is 'SD_Tut_TrackerLastUpdatedCookieName'. It's value is the name of the cookie we set in the client browser to determine if the user is visiting our website the first time this day, or he has already viewed page or pages of our website. Again, the value of this variable is trivial and for clarity's sake, we give the it the name of "SD_Tut_LastUpdated".