John Godley’s WordPress Redirection plugin seems to be the hands-down best URL management/redirection plugin. That’s not really news, since it has been around for several years. However, I recently set out to get a post’s or page’s ID to act as a working short URL via the Redirection plugin’s regular expressions functionality, and that’s what I’ll show you how to do.
This will let you keep your permalinks unchanged, for SEO and readability reasons, while allowing you to use succinct URLs with your own domain name in offline advertising (where long URLs just don’t look good), and in online communities like Twitter. Additionally, since we’re using the Redirection plugin, we’ll be able to keep track of the number of hits each URL receives.
Along the way, we’ll learn some regex and add some code to functions.php. Let’s get started.
What are Regular Expressions?
Regex, short for regular expression, “…provides a concise and flexible means to ‘match’ (specify and recognize) strings of text, such as particular characters, words, or patterns of characters.” (source: Wikipedia)
I’m not a regex expert by any means, but I spent some time researching regex matching and using some regex testers. I tried a few and really preferred Regex Tester 2.0 Alpha (the successor of REGex TESTER ver. 1.5.3, which has a list of some commonly-requested regular expressions).
The goal was to get example.com/1234 to redirect to example.com/?p=1234 because, with Permalinks enabled, /?p=1234 will redirect to the “real” link (i.e. the permalink). In case you didn’t know, “permalink” is a portmanteau word combining “permanent” and “link” to signify “this is the permanent link to this post“. It also works for pages and custom post types (CPT). Jean recently wrote The Ultimate Guide to WordPress Permalinks, which is a good reference.
If you follow these steps, you too can get /1234 and /1234/ to become working links — effectively short URLs — for all your WordPress pages, posts, and CPTs.
- Install and activate Redirection plugin.
- Go to wp-admin -> Tools -> Redirection (located at wp-admin/tools.php?page=redirection.php )
- In the Add new redirection box, insert the following:
- Source URL: ^/(\b\d+?\b)(?:/)?$
- Check the “Regular expression:” check box
- Target URL: /?p=$1
- Click the “Add Redirection” button to save
- Edit the redirection you just added and enter this as the Title: /1234 and /1234/ to /?p=1234 — an alternate title could be /1234[/] to /?p=1234
UPDATE: The code above is new/better than the screenshot below, thanks to Jrf’s comment. Both my version (referenced throughout the rest of this post) and his (displayed in Step 3, above) work properly. It’s just that Jrf’s version (above) is optimized by fitting my two rules into a single rule, which is also easier and quicker to enter into the Redirection plugin’s settings page. I left the references to my regex rules throughout the post because they’re still able to help you learn regex rules.
Here’s what it should look like once you’re all done (see note above):
Explaining the Regex Rules
The regex tester can help us learn regex quickly when we already know we have a working regular expression statement.
- Go to Regex Tester 2.0 alpha (in a new window)
- Copy one of the rules above and paste into the “Regex:” text box.
- Type /post-name/1234 into the large “Test:” text box.
- Copy and paste $1?p=$2 into the “Replace:” text box.
If you did all that, it should look like the following, indicating that the regex isn’t working.
The reason is because that example in the “Test:” text box is for when you have permalinks set to something like %postname%/%post_id%. Change the “Test:” text box to just /1234, and you’ll see that it works.
Referencing the image of the regex tester results above, we can see that $& reinserts the whole regex match, $1 inserts the regex match within the first set of parentheses, and $2 inserts the regex match within the second set of parentheses.
Here are all the regex items explained for the /1234 scenario (i.e. no trailing slash):
- ^ (caret) matches the start of the string the regex pattern is applied to, which is needed so we don’t match permalink structures like /%postname%/%post_id%.
- (/) matches the leading slash and stores it as $1 (since it is in the first set of parentheses)
- \b matches, effectively, whole words only. It is called a word boundary, which is why there’s a starting \b and an ending \b to indicate the start and end of the word boundary.
- \d matches digits, which is appropriate since all WordPress posts have an integer for their post ID.
- + (plus sign) matches the previous item, which is necessary for posts with IDs greater than ‘9’ (i.e. more than a single digit post ID). I used +? because it’s not as greedy and works as needed.
- $ (dollar sign) matches the end of the string the regex pattern is applied to, which is needed so we don’t match permalink structures like /%post_id%/%postname%.
Here are the regex explanations for the /1234/ scenario (i.e. with a trailing slash):
- ^ (caret) matches the start of the string.
- (/) gets stored as $1 (sans-parentheses).
- (\b\d+?\b) gets stored as $2 (sans-parentheses).
- That’s all the same as the non-trailing-slash scenario, above.
- (/) matches the trailing slash. It gets stored as $3 (sans-parentheses).
- $ makes sure the trailing slash is at the end of the string. This is to make sure that /1234/post-name/ doesn’t match the redirection, because that could be your permalink setting.
There are some scenarios when you definitely should not enable this, or else you’ll end up with infinite redirect loops (I haven’t confirmed this, but it makes sense):
- DO NOT use this (exactly as written anyways) if you do not have Pretty Permalinks enabled. For example, if you have index.php in your URLs, you’d need to to change the Redirection “Target URL:” field as appropriate.
- DO NOT use this if your permalink settings are a single number-based setting, including but not limited to:
- Clarification: /%year%/%post_id% would be fine, but just /%year% would result in a broken site.
- DO NOT use this if you have some other way of accomplishing the same thing (e.g. in .htaccess or via functions.php or another plugin). There’s no point in having two things setup to accomplish the same thing, and they might get in each other’s way and break your site.
- DO NOT use this if you might ever have a page, post, or CPT slug of just a number because then that single post would break even if the rest of your site doesn’t. Warning: this can occasionally happen if you write a post without a title and then Save or Publish it and later add a title and don’t edit the slug manually.
- Other situations may apply.
How to Find Each Post’s ID, Set it as the Shortlink, and Display it
In order to know what the post ID of each page, post, and CPT is, you’ll need to look at your browser window’s address bar when editing a post, or you’ll need to install a plugin like Reveal IDs to display it in plain sight in the wp-admin area.
Another option is to write your own code to get this set as each post’s actual shortlink (using pre_get_shortlink). Or copy from here: I did it for you.
By storing this as the actual WordPress shortlink, it’ll automatically add it to the < head > section of your site, which works well when people go to share pages via Twitter and other services.
We can even finish it up in a pretty package by displaying it on the front-end in a selectable text box.
Hopefully you’ve learned a digestible bit of regex and where to go for more regex information. Regex knowledge is always valuable.
Now you also have the ability to use much shorter links for typing into an offline document (e.g. flyers, business cards, etc.), for sharing on mobile devices, or for inputting to QR code destinations, all while not changing your permalink structure. It came in very handy for me when preparing my Tulsa real estate brokerage‘s offline documents, allowing me to succinctly reference the online information sources.
I hope this introduction to regex was interesting and that the functionality has been valuable. I like that the Redirection plugin tracks the hits, too.
Image adapted from a great regex tutorial.
What if we use a custom post type and instead of it being like “/?p=18” it’s more like “/book/?p=18” ?
I tried figuring it out but can’t get it to work.
Anybody have any ideas?
Hi Cal, the info you give is a bit too limited to be sure, but I guess you’re looking for something along the lines of:
Source URL: ^/book/(\b\d+?\b)(?:/)?$
Check the “Regular expression:” check box
Target URL: /book/?p=$1
Hope this helps. if not, please provide some real examples of source urls and desired target urls to base the regex on.
Works like a charm! Thank you very much… 🙂
Hi Clifford, nice article.
FYI: there is absolutely no reason to have two rules for this in the Redirection tool.
Regular expressions are powerful, so you can just combine them into one. To clarify, replace your step 3 and 4 with this one step:
In the Add new redirection box, insert the following:
Source URL: ^/(\b\d+?\b)(?:/)?$
Check the “Regular expression:” check box
Target URL: /?p=$1
Click the “Add Redirection” button to save
Edit the redirection you just added and enter this as the Title: /1234[/]? to /?p=1234
Oh, and on the regex optimization front: only ‘remember’ what you need to. Hard-coded strings such as the first / is a ‘known’, so no need to remember it through the regex.
The (?:/)? I added at the end means: match zero or one /, no need to remember it.
Thanks for the regex! It works! 🙂
I initially didn’t manually add the leading slash and I thought things were screwy, but once I did that, it worked as desired. (copy/paste is always best for code)
You’re very welcome 😉
P.s.: oh and it’s ‘her’ not ‘his’ 😉
If you want to use your own domain to create shortlinks to other sites, I can highly recommend Blair William’s Pretty Link – http://blairwilliams.com/pretty-link/
Pretty Link Lite is free in the WordPress repository, but I don’t think it does what this regex does, does it? Maybe the Pro version does with “Automation” features, but even if it does, I don’t know that it uses the post ID as the shortened link. I’d be interested to hear your feedback on this. Thanks for sharing though; from what I can tell, it is a good plugin.