WordPress 2.5 Shortcodes

Warning: Shortcodes are affected by Trac ticket 6444, which was fixed in WordPress 2.5.1.

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.

About Aaron D. Campbell

Owner and lead developer at BlueDog, Aaron has 10+ years of web development experience, it a regular core contributor to the WordPress project, and has released many WordPress plugins.
This entry was posted in Wordpress, WordPress Shortcodes and tagged , , , . Bookmark the permalink.

62 thoughts on “WordPress 2.5 Shortcodes

  1. jeremyclarke says:

    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?

  2. 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.

  3. Adam Hearn says:

    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!

  4. phalkunz says:

    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 :)

  5. Marcus says:

    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.

  6. 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.

  7. albandi says:

    is there a way to add a shortcode to a sidebar textwidget?

  8. 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');

  9. albandi says:

    thanks Aaron!! It works fine :-) I’m happy!!

  10. albandi says:

    now I try to include template-tags in a shortcode-function, but it doesn’t work.
    Is it possible?

  11. albandi: could you give me an example of what you are trying to do? Maybe a snippet of the code you are using?

  12. alibandito says:

    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]

    • lilianev says:

      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]

  13. Anup says:

    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]

  14. Pingback: Wordpress Shortcodes » brams.dk

  15. Numismatic says:

    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.

  16. 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.

  17. Dhawal says:

    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 ?

  18. Dhawal: Shortcodes need something to process them, which means a plugin. I don’t think you can do that with a wordpress.com blog.

  19. Dhawal says:

    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?

  20. Sean says:

    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!

  21. Sean: I haven’t really had time to play with it, but couldn’t you just use html_entity_decode() to decode it back to what it should be?

  22. Sean says:

    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.

  23. Beckett says:

    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

  24. Without looking into the code of that particular plugin to see how they handle everything, there’s really no way for me to know. I’d recommend contacting the plugin developer.

  25. Pingback: Mastering WordPress Shortcodes | How2Pc

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

  27. Pingback: Mastering WordPress Shortcodes - HTD-34

  28. Y920 says:

    You are rocking with the best best example in your hand.

  29. osu says:

    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

  30. You're function (subReel) needs to accept parameters. Add two parameters to it and make them both optional.

  31. osu says:

    Thanks for getting back to me Aaron,

    I'm a little new to this, could you give me an example please?

    Thanks

    osu

  32. There are examples in the post that show that shortcode functions need two parameters. Make your function definition like this:
    <code>function subReel($attr=null, $content=null) …</code>

  33. Pingback: ???????? » WordPress Shortcodes

  34. Shamess says:

    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.

  35. Pingback:   5 Tutorials um WordPress ShortCodes zu verstehen

  36. Pingback: 5 Tutorials um WordPress ShortCodes zu verstehen

  37. Navjot Singh says:

    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.

  38. Pingback: Mastering WordPress Shortcodes | Bookmarks

  39. Brucem says:

    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.

  40. 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.

  41. 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!!

  42. 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″]

  43. 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 .= '<ul>';
    
    		if ( $num_items !== -1 ) {
    			$rss->items = array_slice( $rss->items, 0, $num_items );
    		}
    
    		foreach ( $rss->items as $item ) {
    			$return .= sprintf(
    				'<li><a href="%1$s" title="%2$s" rel="nofollow">%3$s</a></li>',
    				clean_url( $item['link'] ),
    				attribute_escape( strip_tags( $item['description'] ) ),
    				htmlentities( $item['title'] )
    			);
    		}
    
    		$return .= '</ul>';
    	} 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(
    		"feed" => 'http://',
    		"num" => '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"]

  44. 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!

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

  46. Rich Pedley says:

    and 2 years on I finally found this.

    Many thanks, has saved me lot of time for a little project I’m working on.

  47. Hi Aaron,

    I am using a WordPress (2.9.2) template (InFocus from Themeforest.net) and have encountered a problem. If I use [frame_right] or [frame_left] WP’s shortcode function replaces the character ‘x’ in a filename/URL with ×, read: the HTML entity resulting in no image being displayed.

    Addendum: A sample of the bug can be viewed here:

    http://www.constellationhouse.co.za/practitioners/bill-petrie/

    Any advice is really appreciated.

  48. Andy says:

    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!!!!

    • The script works fine with selects (the dropdowns you’re talking about).

      • Andy says:

        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

        • Andy says:

          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

  49. 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.

  50. victor says:

    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 ?

  51. 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!

  52. tony says:

    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:)

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

  54. Brilliant!!! It works for me :D thanks so much Aaron!!! hah! My wordpress now rocks m/

Leave a Reply

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

Note: If you are replying to another commenter, click the "Reply to {NAME} ↵" button under their comment!