Custom WordPress Shortlinks
Christopher Davis has written this article. More details coming soon.
WordPress ships with the ability to create shortlinks for you. Most of the time that means something like http://yoursite.com/?p=123. Or, if you opted in, a wp.me shortlink.
Those are solid options, but what if you want to use your own shortlink service? Or you want short links that are a little bit prettier? Fortunately nearly everything in WordPress has a hook attached to it, meaning it’s very easy to modify that built in shortlink functionality without changing the code.
?p=123 at the end of a URL is not so pretty. The first half of this tutorial will be learning how you can create a better, cleaner shortlink. This involves using WordPress’s built in Rewrite API.
1. Setting Up a Rewrite
The first thing we’re going to do is add a rewrite rule. add_rewrite_rule takes three arguments: the regular expression that WP will try to match a URL against, the rewrite destination, and the priority.
add_action(‘init’,‘pmgtut_add_rewrites’);functionpmgtut_add_rewrites(){ add_rewrite_rule(‘^s/(d+)$’,‘index.php?short=$matches[1]’,‘top’);}
We’re hooking into init here because need to be sure the entire WordPress environment (including our add_rewrite_rule function) is loaded. The add_rewrite_rule says, “whenever someone visits a URL that starts with s, followed by a slash and one or more digits, rewrite that URL to index.php?short=the_digits.
Unfortunately WordPress will see that short query argument on the URL and not recognize it. As such, it will get stripped out. So we need to tell WordPress that short is a valid query argument by hooking into the query_vars filter.
add_filter(‘query_vars’,‘pmgtut_query_vars’,10,1);
functionpmgtut_query_vars($vars)
{
$vars[]=‘short’;
return$vars;
}
Aside: Rewriting vs. Redirecting
When a URL is redirected, it changes. When it’s rewritten, it’s done so transparently at the server level without the user knowing: the URL does not change. Rewrites are how the WordPress permalink system works. What we’re doing here is harnessing that system to roll our own rewrites.
2. Dealing With the Rewritten URL
Despite us telling WordPress that short is a valid query argument, it still has no idea what to do. For that, we need to hook into template redirect, a hook that fires right before WordPress chooses which PHP file in your current theme to use.
First, we’ll check to see if short argument is there with
. If it isn’t, we’ll bail and let WordPress continue doing its thing.get_query_var
add_action(‘template_redirect’,‘pmgtut_shortlink_redirect’);
functionpmgtut_shortlink_redirect()
{
// bail if this isn’t a short link
if(!get_query_var(‘short’))return;
}
Next we’ll try to turn our query argument into an absolute integer, and get a permalink out of it. If either of those fail, we’ll say that this is a 404, error page and return out of our function. The last step is calling
to send people on the canonical URL.wp_redirect
add_action(‘template_redirect’,‘pmgtut_shortlink_redirect’);
functionpmgtut_shortlink_redirect()
{
// bail if this isn’t a short link
if(!get_query_var(‘short’))return;
global$wp_query;
$id=absint(get_query_var(‘short’));
if(!$id)
{
$wp_query->is_404=true;
return;
}
$link=get_permalink($id);
if(!$link)
{
$wp_query->is_404=true;
return;
}
wp_redirect(esc_url($link),301);
exit();
}
That’s it! you now have custom shortlinks, but we’re not done yet.
3. Modifying the Shortlink API
WordPress lets you click on that handy Get Shortlink button to grab your shortlink in the admin section. It also adds the shortlink into the <head> section of your site. We need to modify that output to reflect our new, pretty shortlinks.
The filter in question here is get_shortlink.
add_filter(‘get_shortlink’,‘pmgtut_get_shortlink’,10,3);
functionpmgtut_get_shortlink($link,$id,$context)
{
if(‘query’==$context&&is_single())
{
$id=get_queried_object_id();
}
returnhome_url(‘s/’.$id);
}
You can see this entire thing in action as a plugin.
If you’re using an external service, you don’t need to worry about steps one and two above. Instead, you’ll need something that interacts with a service’s API, grabs the shortlink and puts it int he correct places.
For this tutorial, we’ll be using dlvr.it as our external shortlink provider.
To start, we’ll keep a good portion of our get_shortlink function above. This will be in a plugin, so we’ll also include PHP class that encapsulates the Dlvr.it API.
// plugin header here
// call in our dlvir API.
require_once(plugin_dir_path(__FILE__).‘api.php’);
add_filter(‘get_shortlink’,‘pmgtut2_get_shortlink’,10,3);
functionpmgtut2_get_shortlink($link,$id,$context)
{
if(‘query’==$context&&is_singular())
{
$id=get_queried_object_id();
}
}
Now it gets a bit tricky. We don’t necessarily want to hit the API every single time we get the shortlink. Remember the mention above about how WordPress put the shortlink in the <head> section? Hitting the API on the load of every single post page is probably not a good idea: extra HTTP requests, etc. Instead, we’ll store our shortlink as a value in the wp_postmeta table. The first step is seeing if that value is there. If it is, we’ll return the short URL right away.
functionpmgtut2_get_shortlink($link,$id,$context)
{
if(‘query’==$context&&is_singular())
{
$id=get_queried_object_id();
}
if($dlvrit=get_post_meta($id,‘_pmg_dlvrit_url’,true))
{
return$dlvrit;
}
If we dont’ have a stored value, we’ll create a new wpDlvrit object, then get the posts permalink, and fetch the short url.
functionpmgtut2_get_shortlink($link,$id,$context)
{
if(‘query’==$context&&is_singular())
{
$id=get_queried_object_id();
}
if($dlvrit=get_post_meta($id,‘_pmg_dlvrit_url’,true))
{
return$dlvrit;
}
else
{
$dlvrit=newwpDlvrit(‘your_api_key’);
$long=esc_url(get_permalink($id));
$short=$dlvrit->get_shortlink($long);
// If there’s a problem, return the original link
if(!$short)return$link;
Since the API class doesn’t handle json decoding or any of that jazz, we’ll have to take care of that ourselves here. Assuming everything goes according to plan, we’ll update the
table and return the shortlink.postmeta
functionpmgtut2_get_shortlink($link,$id,$context)
{
if(‘query’==$context&&is_singular())
{
$id=get_queried_object_id();
}
if($dlvrit=get_post_meta($id,‘_pmg_dlvrit_url’,true))
{
return$dlvrit;
}
else
{
$dlvrit=newwpDlvrit(‘your_api_key’);
$long=esc_url(get_permalink($id));
$short=$dlvrit->get_shortlink($long);
// If there’s a problem, return the original link
if(!$short)return$link;
$body=json_decode($short[‘body’]);
if(!isset($body[0]->short))return$link;
update_post_meta($id,‘_pmg_dlvrit_url’,esc_url($body[0]->short));
returnesc_url($body[0]->short);
}
}
Stay in touch
Subscribe to our newsletter
By clicking and subscribing, you agree to our Terms of Service and Privacy Policy
The entire example is available as a WordPress plugin.