Custom Shortlinks for WordPress

I was lucky and managed to get my hands on a neat little .co domain, djr.co, and I decided that since it is now the shortest domain that I own that I'd first put it to use for the short links on my blog, and as my own personal url shortener.

The (really) short version

  • I've set up Lessn to take care of the personal url shortener side of things
  • And I'm using a simple combination of a WordPress filter function and an .htaccess/index.php redirection combo to handle the shortlinks for my blog.

The long version (for those who want more info)

Personal URL shortener

For the general url shortener there a few different options floating around, but I didn't need anything super fancy with graphs and counters and all that stuff, I just wanted something simple and easy to setup - and most importantly something that worked. So I went with Shaun Inman's nice little Lessn script and its working great.

Summary - if you want to set up your own url shortener using your own domain, then give Lessn a go. It is dead simple to setup.

Custom WordPress 'shortlinks'

As of version 3.0, WordPress now come with a built in function called 'wp_get_shortlink' which, as you can probably guess, returns a 'shortlink' for the relevant post/page.

By default these 'shortlinks' take the form of http://deanjrobinson.com/?p=1345 - which also happens to be the default post links if you don't have pretty permalinks set up, I'll explain why this point is important shortly.

Getting djr.co ready for redirection

The first thing I needed to do was to set up things on djr.co and make sure it was working as I expected.

I had considered using the api built into Lessn to auto generate a shortlink when I publish a post, I even found a plugin that would have done it for me pretty easily, however I rules this out for a couple of reasons:

  • It would have meant adding additional meta data fields against posts - not necessarily a bad thing, but also not really necessary for my needs
  • I would have had to either modify my templates to output the new short links, or create a filter to take care of it for me
  • And the main reason was that I wanted 'shortlinks' to be available for all my old posts as well - without me having to go back and generate them.

The 'solution' I decided on is essentially a really stripped back version of Lessn - without the need to call off to the Lessn database etc because our WP posts already have unique ids which we can use for the redirection. More specifically it just two files a .htaccess file and an index.php file.

First, the .htaccess file, this is exactly the same as the one from Lessn.

This takes the url, eg. http://djr.co/m/1345, and passes it to
http://djr.co/m/index.php?token=1345 ready for the redirection.

<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteCond	%{REQUEST_FILENAME}	!-d
  RewriteCond	%{REQUEST_FILENAME}	!-f
  RewriteRule	(.*) index.php?token=$1	[QSA,L]
</IfModule>

You might be curious as to why I haven't just redirected it to my primary url using the htaccess, I'll get to that in a sec.

Second, the simple index.php

This is based on the index.php file from Lessn, but cut down to just what I needed for my blog redirection. That means no need to call any of the Lessn includes, or make any database queries, just grab the id and redirect it off to my blog.

If no 'token' is passed though the page will simply return a 404. The two reasons for using this index.php file to handle the actual redirect are so that I can clean up the token (using strip_tags) just in case someone tries something nasty, and so that I can check that the token is numeric (using is_numeric) - this is because WordPress post/page IDs are only numeric, so any other values obviously aren't going to work anyway.

This is what the cut-down, modified index.php file looks like. You'll notice that the url format for the 'Header Location' matches the default WordPress 'shortlink' format I mentioned above. This is because no matter how you have your pretty permalinks set up, these default links will always work.

<?php

if (!empty($_GET['token'])) {
  $id = strip_tags($_GET['token']);
  if(is_numeric($id)) {
    header($_SERVER['SERVER_PROTOCOL'].' 301 Moved Permanently');
    header('Location:http://deanjrobinson.com/?p='.$id);
    exit();
  }
}

header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
header('Status:404');
die('404 Not Found');

?>

Getting WordPress to use these custom shortlinks

To get this working, all I needed to do was add a really simple 'filter' to the functions.php file in my current theme.

I'm using a filter so that I can continue to use the built-in 'wp_get_shortlink' function that is available in WordPress (since 3.0). This function can be used something like this:

<a href="<?php echo wp_get_shortlink(); ?>" title="ShortURL for this post">Short URL</a>

By running the filter over the standard function not only do I not have to update any of my theme templates, I will also be able to retrieve my custom short url by using the "Get Shortlink" button that has been added to the create/edit post screen in the WordPress admin, just below the post title.

<?php

function my_custom_shortlink_filter() {
  global $post;
  return 'http://djr.co/m/'.$post->ID;
}
add_filter('get_shortlink','my_custom_shortlink_filter');

?>

Best of all, because the shortlinks are based on the unique post ids (which every post has) the shortlinks will instantly work for all my posts going right back to the beginning of this blog without me needing to change anything else. Yay.