First I touched on the topic in my first impressions of WordPress 2.5. Then I whined a little about the tickets relating to them, and eventually I released my Google Maps Plugin that uses them. In the end, WordPress’s new shortcodes are really nice.

What are they?

First of all, a shortcode called “mycode” can look like any of these:

[mycode]
[mycode foo="bar" id="123" color="red" something="data"]
[mycode]Some Content[/mycode]
[mycode]<p><a href="http://example.com/">HTML Content</a></p>[/mycode]
[mycode]Content [another-shotcode] more content[/mycode]
[mycode foo="bar" id="123"]Some Content[/mycode]

As you can see, shortcodes allow a user to put a code into a post or page, and a plugin can then easily handle those codes. They can be nested, contain content (including HTML), attributes, etc. Sounds great, but how can you leverage shortcodes for your benefit?

How can I use them?

You want to leverage the new, powerful shortcode system in WordPress 2.5, but where do you start?

First of all, you need to add your shortcode:

add_shortcode('mycode', 'yourFunction');

Your function should take two arguments and return the content that you want to replace the shortcode with. The first argument will be an associative array of attributes (keys will be the attribute names, and the value will be the corresponding attribute value), and the second will be the content between the tags.

To handle default attributes, you can use shortcode_atts($defaultsArray, $attributesArray):

function yourFunction ($attr, $content) {
    $attr = shortcode_atts(array('foo'   => 'bar',
                                 'id'    => '',
                                 'color' => 'blue'), $attr);
    return '<h2>Attributes</h2><pre>' . print_r($attr, true) . '</pre><h2>content</h2>' . $content;
}

That’s it! That’s why they are so great, it takes next to nothing to handle! However, maybe you’re thinking about a relatively complex way to use these, and you want to take it to the next level.

The Next Level

Maybe you’re worried that you’re users won’t grasp the intricacies of your shortcodes, or will be plagued by typos. It’s a valid concern. For example, I don’t want to assume that my users will be able to create a Google map by flawlessly entering:

[googleMap width="100%" height="400" name="Aero Rental - Phoenix" directions_to="true" directions_from="true"]3432 W. Clarendon, 85017[/googleMap]

The solution is to create a way for your users to generate the shortcodes and have them sent to the editor, but where to start? First, you need to add a meta box to the writing/editing pages (these are the dropdown boxes below the editor, such as Tags, Categories, etc). To do this, create a function that you will use to display the form used to generate your shortcode (I’m going to call it “insertForm”). Then you need to hook into the admin_menu action, and use it to create the metaboxes:

<?php
function handleAdminMenu() {
    // You have to add one to the "post" writing/editing page, and one to the "page" writing/editing page
    add_meta_box('yourMetaBoxID', 'Your Meta Box Title', 'insertForm', 'post', 'normal');
    add_meta_box('yourMetaBoxID', 'Your Meta Box Title', 'insertForm', 'page', 'normal');
}

function insertForm() {
?>
        <table class="form-table">
            <tr valign="top">
                <th scope="row"><label for="wpYourPluginName_content"><?php _e('Tag Content:')?></label></th>
                <td>
                    <input type="text" size="40" style="width:95%;" name="wpYourPluginName[content]" id="wpYourPluginName_content" />
                </td>
            </tr>
            <tr valign="top">
                <th scope="row"><label for="wpYourPluginName_foo"><?php _e('Foo Attribute:')?></label></th>
                <td>
                    <input type="text" size="40" style="width:95%;" name="wpYourPluginName[foo]" id="wpYourPluginName_foo" />
                </td>
            </tr>
            <tr valign="top">
                <th scope="row"><label for="wpYourPluginName_bar"><?php _e('Bar Attribute:')?></label></th>
                <td>
                    <input type="text" size="40" style="width:95%;" name="wpYourPluginName[bar]" id="wpYourPluginName_bar" />
                </td>
            </tr>
        </table>
        <p class="submit">
            <input type="button" onclick="return wpYourPluginAdmin.sendToEditor(this.form);" value="<?php _e('Send Map to Editor &raquo;'); ?>" />
        </p>
<?php
}

function adminHead () {
    if ($GLOBALS['editing']) {
        wp_enqueue_script('wpYourPluginNameAdmin', 'path/to/yourJsFile.js', array('jquery'), '1.0.0');
    }
}

add_action('admin_menu', 'handleAdminMenu');
add_filter('admin_print_scripts', 'adminHead');
?>

The specifics:
yourMetaBoxID becomes the id of the metabox div.
“Your Meta Box Title” will be the displayed title for the metabox.

You may have noticed that the submit button calls some javascript (specifically wpYourPluginAdmin.sendToEditor(this.form)), and we enqueue a JavaScript file. Here is that file:

/**
 * Handle: wpYourPluginNameAdmin
 * Version: 0.0.1
 * Deps: jquery
 * Enqueue: true
 */

var wpYourPluginNameAdmin = function () {}

wpYourPluginNameAdmin.prototype = {
    options           : {},
    generateShortCode : function() {
        var content = this['options']['content'];
        delete this['options']['content'];

        var attrs = '';
        jQuery.each(this['options'], function(name, value){
            if (value != '') {
                attrs += ' ' + name + '="' + value + '"';
            }
        });
        return '[googleMap' + attrs + ']' + content + '[/googleMap]'
    },
    sendToEditor      : function(f) {
        var collection = jQuery(f).find("input[id^=wpYourPluginName]:not(input:checkbox),input[id^=wpYourPluginName]:checkbox:checked");
        var $this = this;
        collection.each(function () {
            var name = this.name.substring(13, this.name.length-1);
            $this['options'][name] = this.value;
        });
        send_to_editor(this.generateShortCode());
        return false;
    }
}

var wpYourPluginAdmin = new wpYourPluginNameAdmin();

This JavaScript parses items from the form, formats a shortcode, and sends it to the editor! Now you can create an interface for your user, to allow to easily generate VALID shortcodes for you to parse.

63 thoughts on “WordPress 2.5 Shortcodes

  1. wow. Great article, it really summarizes the whole thing perfectly. Bookmarked!
    One thing i’m a bit confused about is send_to_editor(this.generateShortCode());

    Where is that defined? Part of the general wp admin js?

    • It is defined in wp-admin/js/media-upload.js, which is enqueued in:
      wp-admin/page-new.php
      wp-admin/post-new.php
      wp-admin/page.php
      wp-admin/post.php

      Basically, it’s enqueued on all write/edit pages.

  2. Brilliant article thanks! Was processing my own content using regex and string replacement. Finding this tidied up the code somewhat. Thanks for the tips on the admin panel as well!

  3. I just started playing with shortcode. I wrote a short function to display site url. It works fine with Post but it doesn’t work with Page at all. For instance, my shortcode is [url]. When put it in a page it shows [url] itself, instead of the site url.

    First I assumed that it works only for Post. But in this post of yours and you said “As you can see, shortcodes allow a user to put a code into a post or PAGE”. Did I do something wrong? or do I have to write extra code?

    Hope to hear from you soon.

    Cheers :)

  4. You seem to know a lot about short codes , I got a issues you may be able to help me with. On my wordpress blog my short codes stopped working , at the moment anything with a gallery short code only shows up with [gallery]. before that it all worked well and the galleries showed up. Do you have any idea what could cause them not to show up.

    • Marcus: Unfortunately there are a lot of reasons. First, try disabling all your plugins. If that fixes the problem, re-enable them one at a time until you find the one that is causing the problem. If that doesn’t work, feel free to contact me.

    • albandi: Not by default. However, the way WordPress applies shorcodes is by adding a filter on the_content:
      add_filter('the_content', 'do_shortcode', 11); // AFTER wpautop()
      You could add that same filter to “widget_text” and shortcodes should start working in them. Try adding this line to your theme’s functions.php file:
      add_filter('widget_text', 'do_shortcode');

      • Can you explain to me what 11 number mean on
        add_filter(‘the_content’, ‘do_shortcode’, 11); // AFTER wpautop()

        What will happen when I changed 11 with 10 or 20?

        • 11 is the priority. The default priority that most existing filters use is 10 (including wpautop()). We’re trying to make sure this runs AFTER all of those so we set it to 11. Any number greater than 10 would work, but if you make it too high (like 999) it’s likely that other plugins will do stuff between wpautop() and our filter.

  5. Aaron, here it is:
    a) shortcode as plugin:

    function shortcode_readrecent() {
    wp_get_archives(‘type=postbypost&limit=15′);} (or other template-tag)
    add_shortcode(‘readrecent’, ‘shortcode_readrecent’);

    b) modified functions.php: add_filter(‘widget_text’, ‘do_shortcode’);

    c) add to text-widget: [readrecent]

    • Did you ever get this to work for you? I’m attempting to do the something similar.

      I have multiple widgets registered (named uniquely), and one widget per dynamic sidebar.

      1) example shortcode functions:
      function archive_shortcode() { dynamic_sidebar(‘archive’); };
      add_shortcode( ‘archive’, ‘archive_shortcode’ );

      function tags_shortcode() {
      echo ‘What’s Going On?’;
      $tags=wp_tag_cloud( );
      return $tags;
      echo ”;
      };
      add_shortcode( ‘tags’, ‘tags_shortcode’ );

      2) example of calling shortcode in page:
      [archive]
      [tags]

  6. Thanks for this article. One note, I found that the method signature to handle the short code had to have the content parameter be optional. That is this:

    add_shortcode(‘mycode’, ‘yourFunction’);

    function yourFunction ($attr, $content = null) {
    // etc…
    }

    Without the above, I was getting error messages trying to just use

    [mycode]

  7. Pingback: Wordpress Shortcodes » brams.dk

  8. Great information on shortcodes. I also realized you can call your shortcode function directly anywhere in your wordpress blog.

    To use your shortcodes outside of posts, pages, and the text widget, you could always call your shortcode function directly like this:


    $text = yourShortCodeFunction('[your shortcode tag here]');
    echo $text;

    I’m not sure if the code will display here, always have problems posting code.

    Very informative blog, keep up the good work.

  9. Numismatic: You can apply all your active shortcodes to text using the do_shortcode function like this:
    $text = do_shortcode($text);
    or using a filter like this:
    $text = apply_filters('do_shortcode', $text);
    Using the filter is probably better just in case any future plugins want to hook into the do_shortcode filter.

  10. I am trying to figure out how to write a shortcode that will work on a wordpress.com blog
    I wish to be able to embed a video from sites currently not supported by wordpress.com and I was told the best way to do this would be thru a shortcode. Any idea what the process is for getting a shortcode to work on wordpress.com ?

  11. Aaron: Thanks for the reply. So how do companies like flickr, vimeo, youtube, kyte etc. get their short codes used on wordpress.com blogs? Do I have to write a plugin that works on blogs not hosted on wordpress.com before approaching WordPress.com to host the plugin or is there a different way to write a short code for use by WordPress.com?

  12. Hey there, first of all thank you for an awesome article. This was exactly what I was looking for and I’m lucky that several months later you’re still maintaining it.

    I’m having a problem (my code: http://pastebin.com/m413e8342) where I’m using a shortcode attribute to define a mysql table selection. I.e. [wplinkdir category="Blogs & Blogging"] would select links from the Blogs & Blogging category.
    The problem is that the shortcode version is returned with an htmlentities() equivalent and so mysql doesn’t accept it as the same as the category title. I looked through shortcodes.php and I believe it’s being affected by the shortcode regexp. I know it’s a long-shot but I figured you might be able to offer a solution or work around.

    If not, thanks regardless!

  13. That’s the first thing I tried, but no unfortunately not, even with the optional quotestyle argument. I’m working on pulling from the raw attributes instead which I think will work just as well.

  14. Hello there, I’m trying to call for the shortcode (in my case ‘[contact-form]‘) outside the loop, but the plugin (Grunion Contact Form) have several functions in it, not just one.
    I’ve tried the code avobe:
    ‘‘
    and I’m able to print the form, but the function to send me the e-mail when a visitor make its submit it’s not working.
    Then, for the next code, I don’t know how to manage it very well ‘$text = do_shortcode($text);‘
    Do you have some idea about how to use the shortcode somewhere in the templates, when the plugin have several functions ? Thanks

  15. Pingback: Mastering WordPress Shortcodes | How2Pc

  16. Pingback: Mess like the Best: Wordpress Shortcodes: | Orange Market

  17. Pingback: Mastering WordPress Shortcodes - HTD-34

  18. Hi Aaron,

    I have this in mt functions.php file:

    // Create shortcode function for Showreel page
    function subReel() {
    if(is_page(15)) {
    wp_list_pages('title_li=&child_of=15');
    }
    }

    // Create shortcode
    add_shortcode('subpagesReel', 'subReel');

    // allow shortcodes in widgets
    add_filter('widget_text', 'do_shortcode');

    But I can't get the template tag to work – is there anything I'm doing wrong? I'm placing the shortcode in a text widget.

    Thanks,

    osu

  19. Pingback: ???????? » WordPress Shortcodes

  20. Aaron, awesome post, you've helped me hugely. You should help out in the WordPress codex sometime, you seem to explain it much easier than some of the articles over there are. :)

    I was just wondering if you've noticed any bugs with 2.8 (bleeding-edge). At the moment my defaults, set by shortcode_atts seem to always be overwriting my attributes, which is annoying to say the least. Or, maybe I'm just doing it wrong? I've knocked up a little dry run here if you could take a second to check for me.

  21. Pingback:   5 Tutorials um WordPress ShortCodes zu verstehen

  22. Pingback: 5 Tutorials um WordPress ShortCodes zu verstehen

  23. I have a shortcode which does not accept content, infact it works like this: [shortcode id="value"]

    Any idea how to make meta box work correctly in such case? I tried but it sends [shortcode [id="value"] which is incorrect.

  24. Pingback: Mastering WordPress Shortcodes | Bookmarks

  25. It appears that shortcodes are not parsed in rendering comments. Is that correct? Is there a way to enable that? The reason (specific example) is that I wanted to use WikiPop in a reply to another comment.

    I see that there could be security risks with this, but I’m just making sure.

    Thx.

  26. Sure, you can process shortcodes anywhere you want using the do_shortcode function. Just pass it the text you want to process shortcodes in and it passes back the processed text:

    echo do_shortcode('some text with a [shortcode] to process');
    

    If you want to process comments though, just add it as a filter to the comment text like this:

    add_filter('comment_text', 'do_shortcode');
    

    You may want to give it a high priority (high number means it runs later) so that it runs AFTER wpautop runs like this:

    add_filter('comment_text', 'do_shortcode', 35);
    

    You should be able to put either of those into your theme’s functions.php file or run it on init from a plugin.

  27. Hello Aaron,

    Your post was very helpful. I am having a little problem with shortcodes on my website though.

    I have [rss feed="http://feeds.digg.com/digg/popular.rss"] which call a fucntion that displays feeds on to my page.

    The feeds are working, however they move right to the top of my content page instead. (check sosmos.com/testing). How can i fix this?

    Thanks!!

  28. Forgot to Add: Funtion;

    include_once(ABSPATH.WPINC.’/rss.php’);

    function readRss($atts) {
    extract(shortcode_atts(array(
    “feed” => ‘http://’,
    “num” => ’1′,
    ), $atts));

    return wp_rss($feed, $num);
    }

    add_shortcode(‘rss’, ‘readRss’);

    And Shortcode =
    [rss feed="http://feeds.feedburner.com/wprecipes" num="5"]

  29. The problem is that wp_rss echo’s out the content rather than returning it. What you can do is create your own custom RSS function and use it instead:

    function my_wp_rss( $url, $num_items = -1 ) {
    	$return = '';
    	if ( $rss = fetch_rss( $url ) ) {
    		$return .= '&lt;ul&gt;';
    
    		if ( $num_items !== -1 ) {
    			$rss-&gt;items = array_slice( $rss-&gt;items, 0, $num_items );
    		}
    
    		foreach ( $rss-&gt;items as $item ) {
    			$return .= sprintf(
    				'&lt;li&gt;&lt;a href=&quot;%1$s&quot; title=&quot;%2$s&quot; rel=&quot;nofollow&quot;&gt;%3$s&lt;/a&gt;&lt;/li&gt;',
    				clean_url( $item['link'] ),
    				attribute_escape( strip_tags( $item['description'] ) ),
    				htmlentities( $item['title'] )
    			);
    		}
    
    		$return .= '&lt;/ul&gt;';
    	} else {
    		$return .=__( 'An error has occurred, which probably means the feed is down. Try again later.' );
    	}
    	return $return;
    }
    
    include_once(ABSPATH.WPINC.'/rss.php');
    
    function readRss($atts) {
    	extract(shortcode_atts(array(
    		&quot;feed&quot; =&gt; 'http://',
    		&quot;num&quot; =&gt; '1',
    	), $atts));
    
    	return my_wp_rss($feed, $num);
    }
    
    add_shortcode('rss', 'readRss');
    

    And still use the shortcode like you did before:
    [rss feed="http://feeds.feedburner.com/wprecipes" num="5"]

  30. You are amazing! I tried every thing but did not think that could be the problem. I looked into the fetch_rss and apparently its deprecated. It replaced with the fetch_feed function which i was easily integrate into your code. Thanks again!

  31. Pingback: ??API|????|WordPress ???? » ??????-DD456.com

  32. Hi, thanks for the great script.

    I was hoping you could tell me how to get the value of a drop menu. The script works great with text fields but I want a drop menu with options and when you hit submit it will copy the selected option.

    Can you help.

    Thanks!!!!

      • Hi Aaron,

        I’ve just tried with the raw script above (incase I implemented something wrong) and it still doesn’t recognise the select box value. I replaced the wpYourPluginName[content] text box for a select menu.

        someitem
        someitem2

        And the result is:

        [googleMap foo="foo" bar="bar"]undefined[/googleMap]

        Thanks

        • That should have read

          someitem
          someitem2

          And there doesn’t need to be an exception here?

          var collection = jQuery(f).find("input[id^=wpYourPluginName]:not(input:checkbox),input[id^=wpYourPluginName]:checkbox:checked

          I really appreciate your help, I need this to work.

          Thanks

  33. thanks, that quick note about creating custom shortcode saved me a lot of time.
    I’m not a programmer or developer… but know my way around a bit… so…

    Added to functions.php file. and roaring away now…
    excellent!

    cheers.
    And many thanks.
    Vince.

  34. hi

    can anyone let me know what code above i can use to hide specific contet if user logged in (loged in form) but another of user is logged in (hidden text)

    let say following senario:
    I have a chunk of text i want to hide, in its place i want to show log in form
    when user have logged in i want the form to be hidden and the chunk of text that were hidden to be shown

    any idea ?

  35. I just started with using WordPress, but I have a broad background in computers and used to fabricate websites (ages ago) in NotePad and Internet Explorer. My reaction upon learning a bit about WordPress? “Where you been all my life!” LOL

    I am dealing with an “assumed knowledge” issue (I suspect) where I understand what shortcodes do and, to a degree, how to implement them. The problem I have is that I’ve not had that Gestalten “ahah!” moment yet about how to apply, wp-ImageFlow2, in a page! I downloaded and activated the widget and then…. I have no idea. I tend to edit my pages in HTML, so how do I implement the widget’s function on a page? I added some images to a gallery. I know where they’re located. So I just… what?

    I’m sure it’s probably simple, but for whatever reason, it’s non-obvious to me. Help!

  36. Great Article!
    Bookmarked this page for further use.
    I have planned to use shortcodes for a while now.

    Finally i can start doing that because your article made this a lot cleared:)

  37. Pingback: Enable Shortcode in Widget # WordPress Tricks & Tips

  38. Pingback: WordPress ShortcodeAndrew Grant

Leave a Reply

Your email address will not be published. Required fields are marked *