To read the article online, visit

Dynamic Content Tree Creation

When users browse your web site, there is the a tendency to get lost in all of the information present. This poses a larger problem when get past a few dozen pages. As pretty much all really good sites have lots of content, it's important to make navigation as easy as possible; lest the users get fed up with your site because they are constantly lost!

So, Microsoft, in their infinite wisdom, provided the Content Linking component. While this is a good tool for making web pages act like book pages, it really doesn't address following where the users are/have been. Also, it's not terribly dynamic. You, the web site developer, have to pre-define the order of the pages, how they should be listed, and fix their URLs... Not particularly nice if you move things around much, since you have to fix the linking file every time you do it.

Then Microsoft, in their FrontPage product, allowed you to create dynamic navigation bars. This was a lot better concept, but it has a few flaws. Unless you want to waste a bunch of space on your pages displaying the navigation text/icons/buttons there isn't much of a choice. Also, the editor for the relationships doesn't track with the links for the documents. So, once again, every time you move things around you also need to move them in the Navigation Bar view to match.

You will probably be more than slightly happy to know that there is a solution to this annoyance. Better yet, it's completely coded in VBScript running under ASP! Not only does this mean that it's a cinch to set up, but it's also completely customizable.

So, without further ado, let's dive in and have a look at what's involved.

Step 1: Install the GLOBAL.ASA file. If you don't know what the GLOBAL.ASA file is, then you're probably very new to writing applications using ASP. The GLOBAL.ASA file allows you to trigger four events. These are when the Application (your web site) starts/stops and when Sessions (a user login at run-time) start/stop. For the purposes of doing content tracking, we need to have each session's data separate. Therefore we will be installing a GLOBAL.ASA file with the Session_OnStart and Session_OnEnd routines defined. If you already have a GLOBAL.ASA file, then you will need to insert the few statements provided into it. Please look in the GLOBAL.ASA file provided. The purpose of the statements are to define the HistLog dictionary and HistCount session variable. "HistLog" will be used to hold the data representing where we have been and HistCount specified what is the last key added to HistLog.

Step 2: Install and customize the HISTMAINT.INC and HISTSHOW.INC files. These are the include files which make all of the magic happen. We'll discuss what's inside HISTMAINT.INC in a moment. For simple text linking, there is *no* customization that needs done in HISTMAINT.INC, unless you want to add additional items in the list. More on that later. Unfortunately, there is significant work do be done in HISTSHOW.INC; because it is responsible for formatting the content of HistLog into what you want to display to the user. Let's take a moment and look inside HISTSHOW.INC to see what needs done:

   ' - Show the entries in the History List
   'NOTE: This module should be modified to format the result
   '      data in the necessary fashion to be properly displayed on
   '      *your pages*!  Remember to handle any additional ThisXXX 
   '      entries here, or things will get really ugly!

   dim HistArray
   dim HistURL, HistText
   'Dim any additional data entries for ThisXXX as HistXXX here!
   HistArray = Session("HistLog").Items
   HistPtr = Session("HistCount")
   Response.Write("History Counter is " & HistPtr & "<br>")
     for i = 0 to HistPtr - 1 step ItemCount
       HistURL = HistArray(i)
       HistText = HistArray(i + 1)
       'Restore any additional ThisXXX entries as HistXXX here!
       'Example line below is for each ThisXXX entry
       '  note the index change!)
       'HistXXX = HistArray(i + 2)

       Response.Write(HistText & " at URL <a href=""" & _
            HistURL & """>" & HistURL & "</a><br>")

The first Response.Write that you see isn't necessary, and should be removed. It's sole purpose in life is to let you know that HistCount (locally referenced as HistPtr) is being properly maintained. When you are using this tool on your pages, it would look really ugly to show this value to the users! Our other Response.Write is what actually makes the list available to the users. How you choose to format the list is completely up to you! If you've seen Netscape's site with the neat dynamic navigation links at the top of their pages, you could do much the same thing with something like:

Response.Write(" > <a href=""" & HistURL & """>" & HistText & "</a>")

Think about what you want to make the Content List look like, try making a static version of it in your HTML editor, then substitute HistURL, HistText etc and slap it into Response.Write. With a little experimentation, you can achieve just about any look you desire. For those of you who want to do neat stuff this is the first place we would need to modify in order to add additional things, like an image URL for those of you who want to be able to display pretty buttons instead of just plain old text. You would, for instance, DIM a new variable as HistImageURL to hold the URL, then restore it's value using something like:

HistImageURL = HistArray(i + 2)

Remember that if you're adding more than one extra item, you'll need to increment the value added to i for each one. That's all there is to be done inside HISTSHOW.INC. I'm sure you've had worse tasks to do!

Step 3: Update your ASP pages to use HISTMAINT.INC and HISTSHOW.INC. This isn't anywhere near as bad as it sounds. For each page you wish to add a link on, there are two things which need to be added. And for each page that you wish to display the Content List on there is one thing to be added. You can look at the four ASP pages included for inspiration as to what needs done. Let's look at what is included in the START.ASP page provided. In the HTML <HEAD> section goes the code to set up where we are, and an include for HISTMAINT.INC:

      Dim ThisURL, ThisText
      'Dim any additional data entries for ThisXXX here!
      ThisURL = "http://" & Request.ServerVariables("SERVER_NAME") & _

      ThisText = "Start Page"
      'Set any additional data entries for ThisXXX here!

   <!-- #include virtual="/{your include path}/" -->

The DIM statement is used to define the variables that we will be providing to HISTMAINT.INC. ThisURL is the URL of the page we want to link to. Usually we would want to come right back to here, so the default code shown actually generates a valid URL from the Request.ServerVariables collection. ThisText is the displayed text you would show to the user. This is another place we would need to modify in order to add additional things, like an image URL. You would, for instance, DIM a new variable as ThisImageURL to hold the URL, then define it's value using something like:

ThisImageURL = "http://" & Request.ServerVariables("SERVER_NAME") & "/images/button1.gif"

After that, we need the include tag to make the magic happen. Obviously, the {your include path} should be replaced with wherever you place the include files on your server.

That covers maintenance of HistLog and HistCount. That wasn't too painful, was it? But, you know, that just maintaining the list isn't enough. We have to display what this list holds in store for us. That's even easier. All we need to do is include the reference to HISTSHOW.INC where we want the output to be placed. Once again, let's look inside START.ASP:

<!-- #include virtual="/{your include path}/" -->

Yes... you have to fix the {your include path} here aswell. If you are going to use plain text for your output, that's all the editing that each of your ASP pages requires. Simple? You bet!

Perhaps we should look into how HISTMAINT.INC works in a little more detail. We're going to look at the overall process that HISTMAINT.INC performs, not the specific code used. The HISTMAINT.INC, HISTMAINT.INC and START.ASP have been well documented to show you where specific things are happening, and also how to customize some of the aspects of it's operation.

We start by determining if the list is empty. Oh dear! When a user first accesses a page with this code, the list will be empty. It's a perfectly normal condition to have. In this case, we simply insert ourselves as the first entry in the list, and that's that. If there are already entries in the list, then we need to dig a little deeper.

Next, we check to see if we're already at the end of the list. If we are, we probably shouldn't add ourselves again. It would be bad for the same page to be listed more than once to the user!

Now that we've determined we're not the last entry in the list, we need to do something really tricky. We'll search the list to see if we're in there. Let's assume that we're already in the list at some point. If the user wants to go there, we shouldn't show them the entries that follow, so we'll need to flush the rest of the list. It's of no use to us, so wave it goodbye! Now that the list ends with us, we don't need to add ourselves again, so we're done.

If we've found that there was nothing to flush (we weren't in the list), then we need to add ourselves to the end of the list. In doing so, we've completed our task of maintenance, and should allow the page to be displayed.

Customization of HISTMAINT.INC, unless you want to radically change how the list operates, there is very little to do. The only thing that would be a common change is to include additional items for each entry. Why don't we use the example we discussed earlier; that of adding an image URL. We would need to change the number of items for each entry in the list. This is changed on the ItemCount constant line:

Private Const ItemCount = 2

The two here is indicative of HistURL and HistText. If we wanted to add HistImageURL, we would change this number to three. Also, we need to store this new item for the entry. You will find two places where this is done. These are when we are adding an entry to the end of the list, and when we are filling the first entry of an empty list. The code for doing that looks something like this:

HistPtr = HistPtr + 1
Session("HistLog").Add CStr(HistPtr), ThisImageURL

Both places use the same code, so there is no confusion as to which is which. As far as basic customization of HISTMAINT.INC, that's all there is to be done. Once again, with the exception of changing the basic operation of the list, there are no other changes to be done here.

Well, sadly that's all there is to be said and done. Now it's time for you to go off and implement this tool on your own web sites. Happy Programming!


  • This ZIP contains the 2 include files, the GLOBAL.ASA session setups, and 4 ASP pages that show how it's used. To run the example pages, you'll need to fix up the includes to point to the virtual path for the includes in each page, and place the GLOBAL.ASA in your application home path (usually the root of the web site.) If there is an existing GLOBAL.ASA, then it will need to be edited to add the constructors/destructors for the history dictionary and counter.

  • Article Information
    Article Title: - Dynamic Content Tree Creation
    Article Author: Bart Silverstein
    Published Date: Wednesday, November 04, 1998
    Article URL:

    Copyright 2017 QuinStreet Inc. All Rights Reserved.
    Legal Notices, Licensing, Permissions, Privacy Policy.
    Advertise | Newsletters | E-mail Offers