« Making the Most of SpamLookup | Main | Entry Titles Linked to Permalinks »

Understanding the Category Listing Code

mtbadge-small.gif This tutorial is co-authored by LMT contributor Chad Everett of Everitz Consulting and Elise Bauer of elise.com.

Movable Type allows you to create categories and sub-categories for organizing your entries. The default MT3.2 Main Index template includes code to list these categories in the sidebar section. This tutorial will attempt to explain the tags used in this code and how they work together.

Categories, Sub-categories, Parent, Child, and Levels

The only difference between a category and a sub-category is that the latter will always have a "parent" category. The sub-category is still a category, and everything else remains the same as any other category. But by having sub-categories, you can provide better organization for your site. One example might be to put sub-categories of "Movable Type" and "Typepad" under a parent category of "Tips", to better classify the information you are creating.

Any category with such a "parent" will be considered a "child". Additionally, any category (even a sub-category!) can have its own children as well. Because of this, within this tutorial, you will see the term "level" used frequently. A parent category (Tips) is on one level. The child category (Movable Type, Typepad) is another. In turn, the child category may have children itself (Plugins, Styles, Templates), creating still another level.

The Default Category Listing Code

Here is the code from the Main Index template:

<MTIfNonZero tag="MTCategoryCount">
<li><a href="<$MTCategoryArchiveLink$>"

<MTTopLevelCategories> <MTTopLevelCategories> is a container that processes the code within, starting with the current highest level category. When it gets to the <MTSubCatRecurse> tag, it then repeats the process with the next highest level of category, and so on, through all levels of sub-categories.

<MTSubCatIsFirst> <MTSubCatIsLast> These tags simply indicate if a particular category is the first in the list or the last in the list, respectively. As you can see these tags open the <ul> and then close the <ul> at the end of this section of code. So, the first category in the list of categories opens the unordered list tag - <ul> - which pulls from your stylesheet the direction of how to display an unordered list. (Unordered lists are usually displayed with bullet points. Ordered lists - <ol> - are usually displayed numbered 1, 2, 3, etc.) Likewise, the last category in the list of categories closes the unordered list tag.

<MTIfNonZero>, MTCategoryCount and <MTElse> The <MTIfNonZero> tag compares the value of the tag (in this case, MTCategoryCount) to zero. If there are entries within a category, the MTCategoryCount will be greater than zero and a link will be provided to the category page. If the there are no entries in the category, the MTCategoryCount will equal zero and <MTElse> will come into play and only the category label will be shown, without a link.

In either case, an <li> tag is opened which instructs the browser that what comes next is a list item. The <li> tag is closed after the processing of the <MTSubCatsRecurse> is complete.

<MTSubCatsRecurse> This tag says to process this hunk of code for each level of sub-categories under this one (and so on).

"Recurse", by the way, is a programming term, indicating to "use recursion". In other words, it is the ability of the routine - in this case the <MTTopLevelCategories> container - to call itself over and over again.

In this example it means that the container will continue to loop through each "level" of categories, until it reaches the end of that level. At this point, if on a "lower" level (that is, a sub-category), processing will return to the next higher level (the "parent"), where the loop will complete. If the loop is still on a lower level, it will end that loop, and return up to the next level. And so on.

If you remove this tag, the code will produce the same structure - but it will only be for the top-level categories (no sub-categories). If you include this tag, each time through the loop (that is, for each current category), it will redo the structure for the categories below that one. You can perhaps see this best by looking at the HTML.

For top-level categories only (no recurse tag, meaning no sub-categories at all), you might see something like:


But with the recurse tag, you will be able to produce something like this:


To explain how this works...

First, the opening <ul>, then the first category (the only one in this sample). Prior to that tag being closed, the recurse tag runs - and realizes there are some sub-categories for the current category.

So it opens a new <ul> for this level of sub-categories, which in turn has its own items in the list. When that category is at the end, it closes that list with </ul>, then closes that item (News) with </li>. Finally, we're at the end of the entire category list, so the top-level list is closed with </ul>.

This illustrates a more likely example, with multiple categories at each level:

    <li>Movable Type

You'll notice that under "Tips", the recurse tag pulls up "Movable Type", similar to how "News" worked earlier. But when this category is the "current" category, it will again pull up the recurse tag, now at the next "level" down in the category listing. This next level down generates the list for those sub-categories: "Plugins", "Styles" and "Templates". The structure is all the same - pulled from the top-level. It just runs it over and over again as needed for all of the sub-categories.

Customizing the Category Listing

Not Showing Categories without Entries The default code will display the name of all of your categories, whether or not you have entries in them. If you want to display only those categories which currently have entries, you need to remove the <MTElse> condition from the equation. Your resulting code would be something like this:

<MTSubCatIsFirst>    <ul>    </MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<li><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><MTCategoryLabel></a>
<MTSubCatIsLast>    </ul>    </MTSubCatIsLast>

Note that if you have a top level category that is empty, but contains sub-categories that have items, removing this piece of code will create an unusual display as those sub-categories will be placed in the same list as the prior category. This is because the <MTCategoryCount> tag doesn't include the count of sub-category items beneath the current category.

If you use sub-categories and you do not want to show sub-categories or top level categories unless they contain items, one method you can use is to install the SubCatCount plugin. With this plugin installed, your code would look like this:

<MTSubCatIsFirst>    <ul>    </MTSubCatIsFirst>
<MTIfNonZero tag="MTSubCatCount">
<li>    <a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"> <MTCategoryLabel> </a>
<li>    <MTCategoryLabel>
<MTSubCatIsLast>    </ul>    </MTSubCatIsLast>

Limiting the levels of sub-categories displayed

If you have several levels of sub-categories, you may want to limit the display of them in your Category List to only a few levels. To do this add a max_depth attribute to the recurse tag like so:

<MTSubCatsRecurse max_depth="3">

Not Showing sub-categories

To show only primary categories, and not sub-categories in your listing, remove the <MTSubCatsRecurse> tag from the code entirely. This is not the same as max_depth="1". That will include the top-level categories and the first level of sub-categories.

Adding an Entry Count

To add the the number of entries in parentheses after each category or sub-category label, you would use the <MTCategoryCount> template tag. Something like this displays the added code at the end of the link to the category archive page:

<li><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><MTCategoryLabel></a> (<MTCategoryCount>)

If you wanted to instead display the sub-category count at that point, you should use <MTSubCatCount> instead of <MTCategoryCount>, as mentioned previously, by installing the SubCatCount plugin.

Displaying Categories in a Custom Order

This tip comes in from an LMT reader. To come up with your own custom order of categories or subcategories, without the use of a plugin, do the following:

a. Name the categories 1, 2, 3 ... in the order you want them to appear. b. Use the description field for the name of the category. c. Replace MTCategoryLabel with MTCategoryDescription in your category display code.

Many thanks to Hugo Paulissen for this last tip.

Comments (50)

Great explanations! I still have trouble wrapping my head around how all the category tags work, and this goes a long way towards a clear understanding!

I'm looking for code to put the category keywords into a pull-down menu list and as soon as you select an item, you're taken to that page. I remember seeing an how-to somewhere, but I can't remember the URL and I think I threw out the printout.

Lola, you can use this as a base to create your drop-down list. Instead of list items (<li>), you would use options (contained within a select statement).

You would then populate the value of each with the path to the archive, and then you'd want a Javascript routine to take that value and redirect the user once an option has been selected.

It's a bit beyond the scope of this tutorial, but if you can handle the Javascript and form-building, this should get you there.

Thanks! By the way, I did find a tutorial in this site for the pull-down menu that I'd been asking for. The article is from November 2004, I believe.


In MT3.2, how do I control the order of top level categories displayed on the main blog page sidebar?
Alphbetical only is such a drag. There must be a plugin.


Actually, that is the only option. There has been talk of such a plugin, but I don't believe that there has been any development of such a beast.

One option would be to put a number in front of the category - for instance:

1. Zebra
2. Apple
3. Bubba

So that the alpha sort would do what you want. Of course, you may not want the number there, which would make it tougher - you could use PHP to chop off the leading number perhaps.


Actually, you can use the Regex plugin to remove the numbers - works like a charm:



Thanks Chad,
You do great work man.

Just to confirm, the "table of contents" on this page is hand-coded Elise? Or is there some neat category PHP trick we can steal from you?


elise [TypeKey Profile Page]:

Hi Don,
All hand-coded. I rarely change the categories so this is the best way I've found to get the flexibility I want for the listing.

Elise & Chad, GREAT article, it has really helped me to understand how everything (category-wise) is supposed to flow.

Elise, you hard code your categories correct? Do you put them into a module or php and do an include?

I am thinking of hard coding my categories as well because I want each parent to be a link which then drops opens the sub categories. (taken from one of your previous tutorials).

Thanks so much!

Thanks Chad,
You have done an amazing job =)

jyoseph, I can't speak for Elise, but I would use an index template and include via PHP before I used a module. This is for two reasons.

The first is that if you want to update the menu, and you are using a module, you will then have to rebuild all the templates using an MTInclude to pull in the contents of the module. Not impossible, but a bit of a pain. If you use PHP, as soon as the change is saved, it's live on your site.

The second is that the MTInclude process takes a lot of resources. If you're building a single page, it's not (generally) an issue. If you use dynamic publishing, you won't really see a problem for this reason - the page is rendered one-at-a-time (basically). But if you rebuild a few hundred individual archives, and each of those has a couple of MTIncludes on it, you'll see a noticeable lag.

Chad, many thanks. Not only did that help (in this situation) but it helped me to curb using the MTInclude so much. I swear I overuse that feature big time.

Thanks again!

Question, if someone can answer: would there be a way to, say, have a thumbnail image and title as the "title" for a post/article, so that I could have images of products reviewed alongwith the titles of the reviews display when you click the "reviews" category link? If so then this is what I'm looking for. Preferably I'd have an option of having, say, normal text display for blog entries, pictures of products in the case of reviews, and so on. Is there a plugin for this?

Hi Peter -

You don't really need a plugin for this. You can just use the power of MT to make it happen. All you need is a handful of images (however many you would like to display).

Simply use <MTCategoryLabel dirify="1"> within the declaration of your image. That way each page gets its picture named dynamically (not truly dynamic, but you get the idea).

For instance, you might see something like this:

<img src="/images/<MTCategoryLabel dirify="1">.jpg" />

If your category is "Reviews", your image name would become "/images/reviews.jpg". You could use other tags (perhaps the entry title?) to create other names. Then all you need is to have images that correspond to the name.



I'm using MT in a corporate setting to post documents and instructions for clients--so I'd like to protect these from being viewed by general public.

My hosting service has a feature to password protect a given category, but the problem is I don't know how to post to a category without the posting being displayed on the main/index. Am I stretching MT in a direction it isn't designed for here? OR is there a real work-around here??
The one plugin I found does not seem too recent or solid...

erinther [TypeKey Profile Page]:

I need to do something with my category archives pages but I can't figure it out. I have 3 different piece of codes which I want to use in deferent levels of categories. I mean:
If I want to use code1 for category level1 and code2 for category leve2 and code3 for category leve3, what can I do?
( level2 is subvategory of level1 and level3 is subcategory of level2).

Hi Jordan -

One option would be to use Arvind's MT-Protect plugin.

Another would be to use the power of MT's built-in template tags to do the job. The MTEntries container will allow you to specify the category of those entries. Just add category="This" to the container. Using this method, you can select all categories you want to appear on the main index (and leave out those you don't), but it might get a bit long if you have a bunch of categories.

There are also alternatives if you'd like to work with dynamic publishing (Smarty) or even custom plugins, but I'm not aware of any that are currently available to the public at large. Contact me if you're interested in that sort of solution.

As to different levels of code for different levels of your categories: That is possible, but it gets a bit tricky, and you may have trouble doing it at multiple levels.

Essentially you have to use the conditional tags, such as MTHasNoParentCategory (for top-level) or the MTIfIsAncestor and MTIfIsDescendant tags. You could also assign the CSS style (class and/or id) based on the category name, then style that category in your CSS.

erinther [TypeKey Profile Page]:

Yes. I could do that. thanks a lot. But it is usable only for 3 levels.Any way. Now One problem is left: how to do this with monthly, weekly and daily archives.I need to define a path to a php file in each of these pages, but It works only for monthly pages.Is there any tag inside date-based archives to determine which archives is being processed?What am I supposed to do?

Well, I'm not really sure what you are after. There are lots of things you can do with archives, and especially in conjunction with PHP. But it's not really appropriate to this tutorial - so it would probably be better focused on another tutorial (there are many!) or on the support forums (link just below).


I'm interested in splitting my categories into more pages.

Let's say I have 150 posts in 1 category. How can I make it display only 10 posts per page within that category?

Thanks in advance :)

You have a few options for paginating your archives. If you use dynamic publishing, you can use the power of Smarty to do this right within your templates.

Though slightly dated, you may also be able to use MTPaginate for your needs if you use static publishing (it still requires PHP).

And if you don't understand any of this, there are a number of options available for Movable Type Consulting - of which I am just one.

Taran, maybe u can answer this

People linnking to my blog from technorati recieve a link that looks like this...


which is a greta article about Cell Phonnes for dogs.

which brings them to the category page but not to the article... how do I fix this?

and why is technorati only picking up my story by categories and not individual archive?

I use MT


Hi Justin -

Not sure who Taran is, but that's not too important.

The problem appears to be one of the preferred archive type that you have chosen.

Go into the settings for this blog (config if prior to 3.2) and look for "preferred archive type". Looks like yours is set to "category". Change it to "individual", save and rebuild the entire site.

This will change your preferred entry link from the category page to the individual page (which I notice you have already, so it should do the trick).

Hope ths helps!

Hi there, I'd like to make the subcategories collapsile, like I found it on this page http://performancematters.europe.yahoo.com/. You can easily copy the JS of the source code, but I don't know, how to arrange the categories tags, that the subcategories collapses. There are two <ul> tags needed, one for the complete categories section and one only for the subcategories. Any hints?



Is there a way to create "hot categories"? a list of 5 categories that have the most posts in them? I tried asking in MT Forums but nobody seems to know.

There is nothing within MT to do this, but I have created a plugin that can handle the task. If you are interested, please contact me directly (you may leave a comment here and I will see it, or use one of the contact methods on my web site).



It's possible to show only one category and link it to his archive, ignoring the other categories? How can I do that?

Hi Jose -

It depends a bit on what you need. You can include a single category and the link to the category by just creating the HTML. For the work that's involved to do it, that's probably the best route.

Alternatively, you could try the MTCategories loop along with something like the FilterCategories plugin. But you'd have to build a loop, then specify the category along with the tags you need - so it's really a lot of extra work (for you and for the rebuild) to do it this way.

Merv [TypeKey Profile Page]:

I use up to 4 levels of categories. The main index displays all levels in the sidebar with links to category archives. If any selection is made at any level to its category archive, I want to display the categories and all subcategories from the top level "parent" of that category (or sub category) through all subcategories of the parent in the sidebar. I can't seem to figure this one out...

The user guide seems to indicate MTParentCategories should do this for me.

The result is always the full category list.
Any help?

Agred, MTParentCategories seems to be what you'd want here, as the manual appears to indicate that it would show you the ancestors for the current category.

If this behavior isn't what you're getting, have you tried reporting it to Six Apart? I've not actually used this category, but it does sound like it's the tag you'd want to use here.


Hi, is this any way to display categories as a cloud?

Hi Sue. Unforunately, the tag cloud (in 3.3) uses a ranking tag, not present in the category code. It's possible that a ranking plugin could be built, which you could use to make a category cloud. It's actually not a bad idea, but I've not seen one to this point.



Thanks so much for this tutorial. I am using this tutorial to display all the topics from all the categories on the right hand side. However, since some of the articles have more than one category, I'm receiving duplicate listings. Is there any way to fix that?

<li><a href="<$MTEntryPermalink$>"><$MTEntryDate format="%m/%d/%y"$> - <$MTEntryTitle$></a></li>

Glenn Fleishman [TypeKey Profile Page]:

I didn't see a solution for having one treatment for top-level categories and another for those below that category. I played around with the advice here and came up with something that works. I wanted this to run together and use brackets to indicate sub and sub-sub categories. This seems to work just fine:

<MTIfArchiveTypeEnabled archive_type="Category">
<MTTopLevelCategories> <b> <a href="<$MTCategoryArchiveLink$>"><MTCategoryLabel></a></b>

<MTSubCategories include_current="0">
<MTSubCatIsFirst>[ </MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<a href="<$MTCategoryArchiveLink$>"><MTCategoryLabel></a>

<MTSubCatIsLast> ]</MTSubCatIsLast>

Hi Marianne -

The way that MT works is that each entry is assigned a placement record that attaches it to the category, so that's what is causing the behavior that you are seeing.

These placement records do have an indicator to tell if they are for a primary category, so there could be a plugin written to only pull primary category records, but to my knowledge there isn't one out there right now.

Hi Glenn -

That should indeed work, just keep in mind that each time through the loop you'll be adding a set of brackets.

If you have only two or three layers of categories, that's not a big deal. But for those of you that use five or six layers in your categories, that might make for a messy display. :)


I am a beginner with MT and have what may be a silly question. I use MTEntries category="CategoryName" to create menus on my pages.

The only problem is that when you are in one category archive page, it does not display the entries from any other categories in the menus I have set up.

I am not sure if this makes sense... you can visit my site to see what I mean.

I would love some help sorting this out.


Hrm, does anyone know of a way to exclude certain categories from being listed in the categories list in the sidebar? I have an "Upcoming" section as a category, that I post upcoming events in (the titles are posted in the sidebar in another module, similiar to recent posts but ascending, and the entires are excluded from the main index). I'd like to try and keep "Upcoming" hidden off of the categories listing...

Amy, the answer is really "it depends". That is, it depends on your menus. Can you post that code?

Randall, probably the easiest way that you can exclude categories is to use something like the FilterCategories plugin.

Zeb [TypeKey Profile Page]:

Hiya :)
I was wondering if someone could help me work out the code I needed to display a list of all the categories on a single page (in alphabetical order) with the names of the entries underneath each category.

Category = Masamune Shirow
Entries = Intron Depot 1, Ghost in the Shell


Masamune Shirow
Intron Depot 1
Ghost in the Shell

... and so forth?

I'm using MT to manage my artbook review site, and thought this may be the best method in terms of listing the reviews of artbooks under their associated artist.
Thanks :)

Hi Zeb - you should be able to do this with something like this:

<$MTEntryTitle$><br />

Obviously, you may want a lot more formatting, but you should be able to tell what you need from this small example.

Hi - I'm trying to create two drop-down menus to select posts that correspond to certain categories. I have two top-level categories, so it's easy to split them. The problem I'm having is with creating a drop-down menu that contains subcats with their children -- where can the <MTSubCatsRecurse > tag go? Here's the code for the working menu (it's working for a subcat with no children).

<form name="byauthor">
<MTSubCategories category="by Author:">
<select name="author">
<MTIfNonZero tag="MTCategoryCount" >
<option value="<$MTCategoryArchiveLink$>">

<option value="">


<input type="button" onClick="location=document.byauthor.author.options[document.byauthor.author.selectedIndex].value;" value="GO" />

Hi Stephanie -

The use of the undocumented "category" attribute will definitely help you out in generating two separate lists like you have. The problem you're going to have is the one you mention - the recursion of the loop.

This is because the tag just rebuilds the structure over and over again, one level down. So if you rebuild the structure again, your selected category isn't going to work unless it exists in the next level of your categories. So what you want is to only use the selection tag on the top level, not on the lower ones.

You might be able to do that by placing your MTSubCategories code as it is, at the top level with a selector in the attribute, and then using the more detailed iteration below it with a recursion on it. But I suspect you'll still run into the same problem because the MTSubCatRecurse will rebuild the entire container tag, which is going to create the same problem for you.

Depending on your programming prowess, you could try saving your categories into a multidimensional array (either JavaScript or PHP should work for this) and then writing it back out, but only if the top-level category was correct. I don't think you're going to have much luck with just template tags. Sorry!

I have hierarchical categories on my blog, but I have found that Parent categories are not populated with the entries of their Children.

I am looking for a way to make a Parent category show all the posts for the Child categories within it.

Any solutions?

If you just want to show the entries, then add the include_subcategories="1" attribute to your MTEntries container at the category level (this replaces the deprecated MTEntriesWithSubcategories container, which should still work, but may not in the future).

If you want to include a count of those entries, then you won't be able to do it with MT. For that, you can use my MT-SubCatCount plugin. It will probably do what you want.

Chad, thanks so much for such a quick reply!

I tried what you said - in the category archives template, I pasted this code (it's an excerpt - only the relevant part) :

<MTEntries include_subcategories="1">
                     <MTDateHeader><h2 class="date-header"><$MTEntryDate format="%x"$></h2></MTDateHeader>
                     <a id="a<$MTEntryID pad="1"$>"></a>
                     <div class="entry" id="entry-<$MTEntryID$>">
                        <h3 class="entry-header"><$MTEntryTitle$></h3>
                        <div class="entry-content">
                              <MTIfNonEmpty tag="EntryBody">
                              <div class="entry-body">
                              <MTIfNonEmpty tag="EntryMore" convert_breaks="0">
                              <p class="entry-more-link">
                                 <a href="<$MTEntryPermalink$>#more">Continue reading "<$MTEntryTitle$>" »</a>

Unfortunately, it's still only giving me the posts that are assigned to the specific category. I have three layers of categories: two parent categories, subcategories under those, and another layer of subcategories under those.

Anything I'm doing wrong?

Ah - you didn't mention that this was in a category archive. That may be a part of the problem. It may not, I can't say. I haven't tested this recently, but I've got this working in a number of places.

One thing that I may be doing differently however is that I often use dynamic publishing for category archives. This allows me to specify the category on the MTEntries container.

I know this sounds odd, but at one point it was required. I don't really know if it is any longer, but since it works I just do it. Something like this:

{{* Archive Category *}}
{{capture assign="cat"}}{{/capture}}
<MTEntries category="`$cat`" include_subcategories="1">

And it seems to work just fine. If I get the chance, I'll do some playing with it to see if it works without specifying the category, though I don't know if I have an installation that uses static publishing for category archives, so I don't know if I'll be able to test that anytime soon.

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)