What are Shortcodes in WordPress?

At some point in your WordPress development career, there comes a time when you ask yourself: “How in the world am I supposed to make that easy for the client to do themselves?!” Of course, by “at some point,” what I mean is “your very first project.” WordPress is incredibly powerful, but just about every project I have completed has needed some sort of additional customized functionality.

Shortcodes are a great way to allow a content writer or client to quickly add a piece of functionality to their post without needing to know html, javascript, or CSS.

Who you callin’ short!?

If the client is adding a piece of functionality to their post, and they don’t know html, CSS, or javascript, how are they supposed to do it? Well, we do it for them — in a way. As developers, we have the ability through WordPress to pre-bake the functionality and give the client a way to call on that functionality through shortcodes inside their WYSIWYG editor or custom field.

Say the client wants to display a blue hobbit in their article, for reasons unbeknownst to us. We create a function that inserts an SVG file and adds the appropriate color where needed. All they have to do is insert the following into their WYSIWYG editor:

[hobbit color="blue"]

Nice, neat; and above all, short. This is translated by WordPress to run the functions we had defined for the “hobbit” shortcode. How unruly is an SVG file? It would be nearly impossible for a client with no dev knowledge to be able to change out the color manually, and even if they did, the WYSIWYG editor would look terrible!

I will never have a client that wants a blue hobbit on their site.

Okay, okay. So that wasn’t the most realistic of examples. Let’s take a look at some instances where shortcodes are the best answer.

WordPress Shortcodes

WordPress actually has some built-in shortcodes. If you enable the gallery post format in your theme, you’re able to use the built-in

shortcode, which takes a set of ids corresponding to the images:

…and outputs a fancy gallery on the site.

Plugin Shortcodes

A lot of plugins use shortcodes for displaying generated content. A favorite of mine is the Contact Form 7 plugin which generates a shortcode that renders out a form created in the admin:

[contact-form-7 id="287" title="Contact us today!"]

Our contact form in the footer is created using this plugin’s shortcode.

Custom Shortcodes

What you’re probably more interested in are custom shortcodes. This very article is implementing a shortcode I built that renders out a table of contents. The blue bar with anchor links at the start of this article is generated with the following:

[quicknav type="{menu|list}"]

List is used to create an ordered list for our tutorials or steps, and menu is used for generating an unordered list for general articles like this one. This shortcode pulls all the h2 and h3 headers out of the content, adds ids to all of them, and then renders out a fancy little animated table of contents with anchor links to those headers.

Show me the codez!

The quicknav shortcode is pretty advanced, dealing with conditional script enqueueing , filter hooks on the_content, dynamic hierarchical html rendering, and all kinds of other stuff. That’s probably a tutorial all by itself (maybe even a couple!), so we’ll pick something a bit more simplistic for this article. How about a shortcode that embeds a google map iframe at a desired width. That oughta be a pretty good starting point.

Prep work

First things first, what does a google maps iframe look like? Well, it’s pretty straightforward, actually:

<iframe src="https://www.google.com/maps/embed/v1/place?key=API_KEY&q=ADDRESS" width="600" height="450" frameborder="0" style="border:0"></iframe>

That’s not too bad! I see there’s a width attribute, height attribute, and some basic styling that removes the iframe border, and the src attribute uses the google maps embed api. Well shoot, this oughta be a breeze! Go ahead and follow the instructions on the google maps embed api page for grabbing your api key. Once you’re done, we’ll knock out the shortcode.

Let’s start by mapping out what our shortcode will look like. I imagine the most semantic name would be “google_maps”, so let’s go with that:

[google_maps]

From here, we’re going to need a couple arguments. We’ll define these arguments in the shortcode itself, and they’ll be automatically passed to our shortcode function. The first argument is the address:

[google_maps address="432 S Farmer Ave, Tempe AZ, 85281"]

Good to go! The next argument we’ll need is one for width and height:

[google_maps address="432 S Farmer Ave, Tempe AZ, 85281" dimensions="250,300"]

That about does it. From here, we’re ready to create the function that’ll tell WordPress what to do with this shortcode.

Simple Addition

We have to tell WordPress what our shortcode is called, and what function it should run. Pop open your functions.php file from your theme (or if you’re feeling froggy, whip up a quick plugin) and add this little gem:

add_shortcode('google_maps', 'my_google_maps');

function my_google_maps( $options ) {
  $api_key = INSERT_GOOGLE_API_KEY_HERE;
}

Setting Defaults

Before we get too far into the function, I want to talk about what just happened. The add_shortcode function is built into WordPress, and takes two arguments.

The first argument is the name of the shortcode — you know, what we’ll be adding into the WYSIWYG editor when we write a post:

[google_maps]

The second argument is the function that will run when WordPress finds this shortcode in our post. If you notice, our function has an argument we’ve called “$options”. When WordPress finds the shortcode, it will automatically parse out all the attributes of the shortcode and send them to the function as an associative array. For our example, the $options variable would look like this:

$options = array(
  'address' => "432 S Farmer Ave, Tempe AZ, 85281",
  'dimensions' => '250, 300'
);

WordPress also comes with a helpful tool for setting defaults called shortcode_atts(). If you’re familiar with jQuery’s $.extend method, then you already know how this function works. If not, here’s what it does:

shortcode_atts($defaults, $passed, $shortcode_name);

Here, we can define some default values for our shortcode attributes, and then use this function to override those defaults with the ones passed to our function. It basically merges the two arrays into one, replacing the defaults with the values that our client has supplied in their WYSIWYG. It doesn’t stop there, it also sanitizes the values and runs a filter across the resulting merge, which is why it’s better than PHP’s array_merge() function. So we could set our defaults to look like this:

$defaults = array(
  'url' => 'United States',
  'dimensions' => '800, 600'
)
);

Now we’ll use the shortcode_atts() WordPress function to merge it into our $options array, and assign the resulting array to a variable:

$settings = shortcode_atts($defaults, $options, 'google_maps');

$settings now contains a merge of the two arrays. In our example, it ends up looking exactly like our original $options array. However, if the client forgets to add a dimension to their shortcode, they’ll still get a default of 800 x 600; if there’s no url, they’ll get a map of the United States.

Hello World!

Okay, we’ve got the basics down. Here’s what we have so far:

add_shortcode('google_maps', 'my_google_maps');

function my_google_maps( $options ) {
  $api_key = INSERT_GOOGLE_API_KEY_HERE;
  $defaults = array(
    'url' => 'United States',
    'dimensions' => array('800','600')
);
$settings = shortcode_atts($defaults, $options, 'google_maps');
}

Before we move on, let’s split our dimensions into an array:

$options['dimensions'] = str_replace(' ', $options['dimensions']);
$options['dimensions'] = explode(',', $options['dimensions']);

From here, we just need to build out our iframe html and return it:

add_shortcode('google_maps', 'my_google_maps');

function my_google_maps( $options ) {
  $api_key = 'INSERT_API_KEY_HERE';
  $defaults = array (
  'address'    => 'United States', // map of USA
  'dimensions' => array('800','600')
  );
  $options['dimensions'] = str_replace(' ','',$options['dimensions']);
  $options['dimensions'] = explode(',',$options['dimensions']);

  $settings = shortcode_atts($defaults,$options,'google_maps');

  $settings['address'] = urlencode($settings['address']);

  $prefix = '<iframe ';
  $suffix = 'border="0" style="border:0;"></iframe>';
  $src    = 'src="https://www.google.com/maps/embed/v1/place?key='.$api_key.'&q='.$settings['address'].'" ';
  $width  = 'width="'.$settings['dimensions'][0].'" ';
  $height = 'height="'.$settings['dimensions'][1].'" ';
  return $prefix . $src . $width . $height . $suffix;
}

What’s returned by us in our function will replace the shortcode in the post. Let’s test this puppy out. We’ll use do_shortcode() for testing. This WordPress function basically just process shortcodes found in any arbitrary string you pass it and returns the resulting code. Just write this in a theme file and take a look:

echo do_shortcode('[google_maps address="" dimensions="250,300"]');

Looking good! Let’s also make sure our defaults are working as well:

echo do_shortcode('[google_maps]');

Nice! You see that map? ‘Merica!

Conflict Resolution

If there’s anything you want to avoid, it’s php errors on your page or breaking some unknown plugin the client might install. We can avoid this by simply checking to make sure the shortcode doesn’t yet exist. If it doesn’t, we should probably also make sure our function name doesn’t yet exist either. We need to wrap our shortcode function with the following:

if( !shortcode_exists('google_maps') && !function_exists('my_google_maps') ) {

// put shortcode stuffs here

}

The first check is a WordPress function that checks the string against all registered shortcodes. The second is a PHP method that makes sure our function hasn’t yet been defined.

That just about wraps it up—no pun intended.

Whatchu Got?

Where else can we take shortcodes? Well, we can pretty much do whatever we want from here. What can you come up with? Shortcodes are a server-side equivalant of HTML5 web components, so as you can imagine, you can do quite a bit with them. Take it from here, and let us know what you come up with via twitter or one of our other social media profiles. I’d be interested to see what you can create.