Michael Curren Web Design logo markThe international icon for currency, whose html entity is declared &curren.

My First WordPress Plugin

I have been working with WordPress for a long time now and I finally found a use case to build a plugin!

Open Source Software

One of the best features of this open source platform is the community that has formed around it. The participation comes in the form of support as well as free software: themes and plugins. Many talented minds have taken time out of their lives to develop plugins and themes extending the core WordPress functionality. I have realized that I need to start giving back to the community that has nurtured my freelance career for almost 10 years, so I have been looking for a good opportunity to build my own plugin for some time now.

WordPress Plugin Repository

So I want to release my own plugin, but… there are so many plugins already out there! I rarely come across a feature for a WordPress site that someone has not already built a plugin for and released it in the WordPress Plugin Repository. For more common or mundane features there are likely several plugins that do the exact same thing!

Beyond the official WP Plugin Repo, there are many and more great plugins available on Github or other various code repos online.

Enter the Client Request

I recently had a client request to be able to generate short links for the blog posts on their WordPress site that I built a custom theme. The catch was that they wanted their short links to be branded using a custom URL instead of using a service like bit.ly.

Short URL Options

There are a handful of options out there using services like bit.ly to host your own branded short URLs but most of them that I could find come with a monthly cost after a certain number of hits to your branded domain per month. This could end up being very costly.

I also looked into self-hosting my own URL shortener software but ended up abandoning this option pretty early on because it requires a certain amount of control over the server, which I did not have with the web host my client is currently using.

Finally I found a service called Rebrandly which ticked all the boxes:

  • Allows custom domains for branded Short URLs.
  • 100% free to use (premium accounts give tracking statistics on Short URL clicks, but this was not a requirement from the client).
  • Offers a solid, full-featured API with really comprehensive documentation.

Getting to know the API

The Rebrandly API v1 has 3 endpoints available for use:

  1. /v1/account
    GET account details.
  2. /v1/links
    GET a list of links associated with an account, or details about a specific link.
    POST a new link, or an update to an existing link.
  3. /v1/domains
    GET a list of domains associated with the account.
    GET details about a specific domain associated with the account.

Every link created in Rebrandly has a unique ID so you can reference it later via the API.

Using the API inside the WordPress Admin

Now that we have looked through the API documentation, it’s time to start interacting with the API system from our WordPress site. Since I am building a plugin, I will be coding in a separate directory from my theme, but the same effect can be achieved by adding the PHP I am discussing here in your theme functions file.

Building out the Plugin Settings

I started by building out a settings page using the add_submenu_page() function that will show up in the admin interface under the default “Settings” dashboard section once the plugin gets activated.

This gives a place for the user to enter their Rebrandly account API key and store it in the database for later use. This step verifies that the user has a Rebrandly account and gives a link to sign up for a Rebrandly account in case the user has installed this plugin without understanding the requirements.

Once the API key is saved in the settings page a new button appears labeled “Get Rebrandly Domains”. When the user clicks this button the plugin fires off some JS to make its first API call using the /v1/domains endpoint to return a list of all the domains associated with the API key. Then the user is able to select the domain they want to use as a base for their Short URLs on the site and save that to the database as well.

Once our Rebrandly domain has been saved to the database I wanted to add one more feature to the settings page to allow the user to choose which Post Type(s) they want to interact with the plugin. I used add_settings_field() to create a group of checkboxes, one for each of the Post Types currently registered on the site. This allows the user to display the plugin’s Edit Screen meta box only on the post types they wish to create short URLs for. This is useful so that you won’t see the Plugin Edit Screen meta box when adding/editing a Page, for instance, unless the user wants to make short URLs for pages.

Using the API in the Post Edit Screen

Now that we have the settings for our plugin worked out to (A) verify the API Key, (B) the custom domain name to use from our Rebrandly account and (C) which Post Types we will be generating short URLs for, we need to start making short URLs for our posts.

I started by constructing a new PHP Class that gets instantiated when the load-post.php or load-post-new.php actions are called on the post types we have chosen in our settings page. Using the add_meta_box() function, I am able to output a new meta box on our post edit screen.

This new Edit Post screen meta box has one visible input for the Short URL slug and 2 hidden input fields for the full Rebrandly URL and the Rebrandly URL ID number. When the post gets saved or published, these input fields get saved as post meta linked to theist we are editing in the database.

The meta box displays the custom domain we have chosen in our plugin settings page in front of the input field for the Rebrandly slug to imitate the native “permalink” meta box you normally see on the post edit screen.

Interacting with the Rebrandly API

Once the user saves/updates the post a function fires off using wp_remote_post() to make a call to the /v1 API that creates a new short URL in Rebrandly, and returns that new short URL and Rebrandly URL ID to the hidden input fields in the post meta box to save to the database. It also returns the “slug” of the new short URL to the visible input in the post meta box, making that slug editable on the post edit screen.

Now the user can choose to enter their own slug in place of the one randomly generated by Rebrandly if they want to use a custom slug for the post’s short URL. If the user edits the slug and updates the post, another wp_remote_post() call is made using the hidden Rebrandly ID field to update the short URL in the Rebrandly system to reflect the new slug.

But what if the post gets deleted at some point? Good question! I added another function in my PHP class that uses wp_remote_post() to remove the URL in the Rebrandly system when it’s post is deleted in WordPress.

Using our new Shortened URLs

Now that we have the capability to create short URLs in Rebrandly for our posts it seemed like a good idea to provide some other functionality to allow users the ability to use the new short Rebrandly URLs.

There is no clear way to do this, since the short URLs created would theoretically be used to share the WordPress posts in places where it would be useful to have a shorter representation of a URL, like Twitter. Originally I was hoping to find a good way of using my plugin to interact with any old social media sharing plugin one might use on their site to allow users to share a WP post. The issue is that there does not seem to be a way of universally doing this.

Instead I decided to make a shortcode (classic WordPress!) to output the new short URL when used within the loop of a post. The last function I added to my plugin is a function to generate this shortcode which can be used by typing [rebrandly_url] inside the post body content.

I has also planned to create the functionality in the post edit screen meta box to be able to click a button to copy the Rebrandly URL to the clipboard. This proved more complicated than I had originally thought, and required including a whole Javascript library with the plugin in order to achieve this functionality. Further, the JS library warned that it does not even have 100% compatibility across operating systems so I decided not to include it in the end until I could better understand the intricacies of this functionality.

Best Way to Build the Plugin

Since this is my first plugin I’m not entirely confident that I coded it using the best methods and practices available, but it seems to work, and I’m sure my next plugin will be even better!

Next Steps

I still need to do some more testing and revisions to make sure the plugin is solid before any sort of public release. So far I have used the plugin on 2 different client sites with good results. Everyone seems to be happy with the functionality and it is hard to beat the price point for the Rebrandly URL shortening service.

That said, I already have some ideas for how to re-tool the settings page for this plugin to make it more intuitive and user friendly. I would also like to do some AJAX calls on the Settings page to communicate with the Rebrandly API without having to save/reload the page.

I also plan to make some improvements to the meta box for the plugin on the post edit screen to make selecting/copying the generated short link easier.

And then there’s some refactoring that should be done before a public release. If I end up doing a major refactoring of the plugin code I would probably move the code base into a format that more closely follows something like The WordPress Plugin Boilerplate. As of right now it seems like a simple “single file” approach to house all of the functions for my plugin gets the job done well enough.

At some point I would like to submit my plugin to the WordPress Plugin Repository. I think it would be wise to refactor the code as mentioned above before I submit it to increase my chances of being accepted to the repo on the first go. If anybody has good experience with submitting plugins to the official repo please let us know if you have any tips in the comment section below!

In the meantime, the code for this plugin is up on my GitHub account now. Feel free to take a look or fork it for your own use!