Retiring entries with Movable Type

Okay, that idea I had about writing a plugin to add a “Retired” status for Movable Type entries? Not going to happen. At least not any time soon. The post status types are pretty well hard-baked into the core MT code, and adding a new status would require some hacking around in places like as well as additional plugin code. Modifying core files means re-modifying them every time you install a new version, and that’s just a pain.

(However, while digging around in the posting status area of the MT core, I found a bunch of dormant code relating to scheduled posting of entries. There is a posting status code of “Future” defined right next to “Draft” and “Publish”. On the other hand, there has been a status code of “Review” in there for some time, too, and it hasn’t appeared in the UI yet, either. It’s probably not worth getting excited about scheduled postings coming to MT in the next version.)

In the absence of a simple plugin, here is a relatively simple alternative way for “retiring” outdated entries in Movable Type.


  • Movable Type 2.2 or later.
  • An Apache web server, and permissions to change your .htaccess file, and override the server’s default settings. This solution will not work if you’re running your MT installation on Windows/IIS. Contact your web host directly to find out if they allow you to edit your own .htaccess files.
  • A SQL database as your data store for your MT installation (e.g. MySQL).
  • Brad Choate’s MT-SQL plugin.

The “Retired” category

First of all, create a new posting category called “Retired”, and take a note of its category ID (you’ll need it in the final step below.) Now, when you want to retire an entry, you should set its Post Status to “Draft”, and assign the “Retired” category to it (using the “Assign Multiple Categories” option). This has the following consequences:

  • The Draft status means that the entry will no longer show up in any entry lists or category lists.
  • By adding a new category to the entry, we’re not destroying any existing metadata. So if the entry was originally posted to the category “Medieval Weaponry”, it will still have that category assigned to it. Only now it has the additional “Retired” category attached.
  • But what about category lists? Won’t “Retired” show up between “Quaggas” and “Swordfish”? No–that’s where the “Draft” status comes in. If none of the entries in a category have a status of “Publish”, then the category itself doesn’t show up in a category list. Nifty.

If you want to bring an entry back out of retirement, all you have to do is use the “Multiple Categories” option to remove the “Retired” category, and set its posting status back to “Publish”.

That takes care of the main visibility of an entry–all references to it should now be removed from your pages. However, if you are using individual archives, then the archive page that was generated when he entry was published will still be present on your web site. If it has been linked to, bookmarked, or indexed by a search engine, then you might still be getting traffic to the page. That’s not what we want, so this is where the “HTTP 410: Gone” error code comes in.

The familiar HTTP 404 error message means that a web server cannot find the file you were trying to go to. Web servers can tella browser that a page has moved by sending it an HTTP 301 (or 302) code, which means “the file you were looking for is actually over here.” An HTTP 410 error code, however, means that there was a file here once upon a time, but it has been removed.

With a 404 error code, you might think that you’ve just got the wrong URL, and that if you were to re-type it you might find what you were looking for. The 410 error code is a very explicit way for a web server to say that you came to the right place, but the information you were looking for is no longer available any more. Not here, and not anywhere else on the site.

Creating a HTTP 410 error page

Just like a custom 404 error page, you can make your custom 410 error page as simple or as complex as you like. Here is an extremely basic example:

Just creating the 410 page isn’t enough, though. Your web server needs to know where the custom 410 error page resides, and under what circumstances it should serve up this error. On an Apache web server, this is the job of the .htaccess file. I’m going to assume here that you know where it sits on your web server, and roughly what it does. If you don’t, searching for “htaccess tutorial” will give you the background information you need.

Adding an MT template for .htaccess

  1. Back up your .htaccess file. Editing it isn’t quite as hazardous as editing the Windows registry, but it’s still easy enough to mess up your site configuration. Safety first, kids.
  2. Go to the MT template management screen, and create a new index template.
  3. Set the Template Name to whatever you like, but “htaccess” is nicely descriptive.
  4. Set the Output File to the location where you want this .htaccess file to end up, e.g. “/martin/.htaccess”.
  5. Leave the “Rebuild this template automatically…” checkbox ticked.
  6. If you already have an .htaccess file, copy its contents into the Template Body.
  7. Press Save

Tell your .htaccess file where to find the 410 error page

In your new template, add the following line, and rebuild the template:

(Make sure to replace “/file/path/to/410.html” with the full path to your own custom 410 page.)

Identifying retired pages in .htaccess

Now that your web server knows where your 410 error page lives, you still have to tell it which pages it should flag as “gone.” Add the following code to your htaccess template, replacing “XXX” with the ID of the “Retired” category in your own installation:

Some notes are in order here:

  • You can’t use the normal <MTEntries> tag for producing a list of entries in the “Retired” category, because it excludes Draft entries, and that’s how you’re indicating that an entry has been retired. <MTSQLEntries> (part of the MT-SQL plugin) gives you much finer control over exactly what entries to show: you want to create a list of entries that have a status of “Draft”, and are in the category “Retired”. Note that the unfiltered="1" attribute is necessary: it tells MT not to discard the Draft entries from our list, which is what you’re trying to avoid in the first place.
  • The series of <MTEntryDate> and <MTEntryTitle> tags is necessary to produce the correct virtual path to the file being retired. The <MTEntryPermalink> tag won’t work here, because it sticks the base site URL (http://…) in front of the virtual path. The code shown above produces output formatted like “/martin/archives/2004/06/30/test_entry/index.html” because that’s where my entries are archived on my system. If you use a different archiving scheme, then you’ll have to tweak the tags to match it.

When you rebuild the template, the code above will produce a chunk of output in your .htaccess file similar to the one below:

Whenever someone requests these pages from the web server, it now knows that these pages have been marked as explicitly gone, and it will return the custom 410 error page instead. It’s not as elegant as having a “Retired” status on the Movable Type entry screen, but it’s a step up from deleting archive files manually.

Related Links