PMG Digital Made for Humans

Custom WordPress Shortlinks

5 MINUTE READ | September 6, 2011

Custom WordPress Shortlinks

Author's headshot

Christopher Davis

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 

get_query_var
. If it isn’t, we’ll bail and let WordPress continue doing its thing.

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 

wp_redirect
 to send people on the canonical URL.
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

postmeta
table and return the shortlink.

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

Bringing news to you

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.


Related Content

thumbnail image

AlliPMG CultureCampaigns & Client WorkCompany NewsDigital MarketingData & Technology

PMG Innovation Challenge Inspires New Alli Technology Solutions

4 MINUTES READ | November 2, 2021

thumbnail image

Applying Function Options to Domain Entities in Go

11 MINUTES READ | October 21, 2019

thumbnail image

My Experience Teaching Through Jupyter Notebooks

4 MINUTES READ | September 21, 2019

thumbnail image

Working with an Automation Mindset

5 MINUTES READ | August 22, 2019

thumbnail image

3 Tips for Showing Value in the Tech You Build

5 MINUTES READ | April 24, 2019

thumbnail image

Testing React

13 MINUTES READ | March 12, 2019

thumbnail image

A Beginner’s Experience with Terraform

4 MINUTES READ | December 20, 2018

ALL POSTS