The Right Way To Shortcodize WordPress Widgets

Dec 28, 2008   //   by Hackadelic   //   Featured, WordPress  //  26 Comments

Code washingA couple of days ago, I’ve been asked how to make Sliding Notes work in sidebar widgets. The general answer is, as with any shortcode: “Enable shortcodes in widgets”.

As it turns out, finding out how to do it right is not nearly as easy as it should be, due to some tricky interweavement with plug-in loading and execution order.

The Punchline

Most advice on this converges to this simple line of code:

add_filter('widget_text', 'do_shortcode');

Though a wide spread method, this is not quite correct. The more correct way would be:

if (!is_admin())
  add_filter('widget_text', 'do_shortcode', 11);

That is, (a) process shortcodes only if outside the admin area, and (b) process them at priority 11, where they belong.

BTW: Ideally, the code should even read

if (!is_admin())
  add_filter('widget_text', 'do_shortcode', SHORTCODE_PRIORITY);

to avoid guessing what the number 11 means, but SHORTCODE_PRIORITY is a constant the WordPress team has yet to provide.

Update: The place to insert the above code is not arbitrary. Many WordPress functions don’t work as expected when WordPress initialization has not reached a certain point.

It is safest to put the code in a plugin.

πŸ’‘ The Widget Tweaks Composer, a free online tool for WordPress, can create a plugin for you that does the trick, and more.

The Background

Shortcode processing is a WordPress filter – one out of several filters applied when WordPress renders the page HTML, many of which stem from various plug-ins.

The above code, however, adds shortcode processing at the default priority of 10. This is different to the shortcode priority in posts, which is 11.

This means, some filters may be executed before, some after the do_shortcode filter. Should there be filters that execute with both, content and widgets, it may very well happen that the output in widgets is different then the output in posts. (Depending on plug-ins used, and their loading order, the issue may or may not manifest.)

To illustrate the situation, imagine two plug-ins, one implementing a shortcode, the other implementing a filter. The filter is running at default priority 10, and checks if a particular shortcode (or any other pattern of text for that matter) is present in the content.

In posts, the filter would see the shortcode, because it has not been processed yet. In widgets, it may as well not see it, if the filter plug-in is loaded after the shortcode plug-in.1 Hence, the overall result is likely to be different in widgets, then it is in posts.

  1. The WordPress plug-in load order is one of the bigger mysteries in the universe πŸ˜‰ []

26 Comments

  • When I try this in my child theme’s functions.php (both the widespread way and the correct way), it works fine on the frontend but then when I try to create a post it gives me this error:
    Warning: Cannot modify header information – headers already sent by (output started at /home2/manna/public_html/wp-content/themes/responsive-child/functions.php:6) in /home2/manna/public_html/wp-admin/post.php on line 222

    Warning: Cannot modify header information – headers already sent by (output started at /home2/manna/public_html/wp-content/themes/responsive-child/functions.php:6) in /home2/manna/public_html/wp-includes/pluggable.php on line 899

    Any ideas? I know there are plugins that do this, but I like your plugin-less way.

    • I figured it out…your code was spot on of course, but I had extra white space in my functions.php when I copy/pasted

  • Do you have tips of how to add a clickable text inside the tag cloud widget in WordPress? Just like adding a link in the hard coded wp_tag_cloud in the sidebar, I also want to add a clickable text (or link) inside the widget tag cloud, but I don’t know how to do it. πŸ™

  • Maybe this is a dumb question, but am I supposed to change the first argument (‘widget_text’)? I can’t find a reference to that filter name anywhere.

    • Tough guy, “widget_text” is good as it is. WP does not have the worlds most up to date documentation, but the filter is there nonetheless.

  • Do you know of any way to utilize shortcodes in theme options text areas? Thank you in advance.

    • Jason, yes, I know, and even you are basically a “competitor” of mine, I’ll tell you nonetheless. πŸ˜‰

      The way I do it is to pass the option through do_shortcode right after obtaining it from the database.

  • I love your articles, really helped me in gaining knowledge

  • Will this do anything different than just calling do_shortcode($content)

    http://codex.wordpress.org/Function_Reference/do_shortcode

    • Andrew, do_shortcode($content) on widget content? Any widget content? Doesn’t make much sense outside theme code, does it? πŸ˜›

  • Thanks for the tip man, I was actually looking for a hook on which I could run the ‘the_content’ filter on text widgets to get all its effects, but now that I think of it really I just wanted shortcode support so this works great (and you pointed out the right filter anyway). Glad to learn about the priority considerations as well. Keep up the god work, I love your slogan πŸ™‚

    • Jeremy, you are welcome. πŸ™‚

  • Any idea why this is not working on my end? Using WP 2.9.2 with inFocus premium theme (however it doesn’t work when I revert back to Kubrick either). I’m trying to use [audio] (MP3 Audio Player plugin) which works fine in a post but not in the text widget. I’ve tried adding the filter to functions.php, then the Hackadelic plugin method, but nothing works.

    • Saul, I don’t know the plugin. However, your issue looks like the plugin doesn’t use the shortcode API, but the filter API to emulate a shortcode (perhaps because there’s been no shortcode API when the plugin was first created). Another plugin, WPaudio MP3 Player, seems to be widget-enabled though, so you might want to switch.

  • In this case, what is needed is:
    add_filter( ‘widget_text’, array(&$wp_embed, ‘run_shortcode’), 8 );

    • gilek7, thanks for the hint. Since they disable other shortcodes during run_shortcode(), you’ll have to have both run_shortcode and do_shortcode in place in order to make [embed] available in widgets alongside with other shortcodes.

  • What if a shortcode hacks the way other shortcodes are loaded, such as embed? See:
    http://phpdoc.wordpress.org/trunk/WordPress/Embed/WP_Embed.html#run_shortcode

  • Hello

    Maybe you can help me with this : I added a text widget with a shortcode to a function I wrote, basically it calls an include file which displays a div on the page.
    But the div doesn’t appear inside the text widget div, but before the widget div.
    Example :
    contents
    empty
    instead of

    <contents

    Is there a way to fix this?
    thanks

    • Paul I’m afraid the comment editor ate your tags. Please use entities (“&lt;” => “<“, “&gt; => “<“).

  • Hi Hachadelic.yes, i used your Tweak widget and it worked.thank you.

  • Can you explain what you ment by putting it in a plugin?

    • Yoav, you could put that code into a theme file, your wp-config.php, or a plugin. I consider the last to be the best way. Actually, meanwhile there exists a plugin that does things like that in a very optimal way: My WordPress Tweaks Bundle. Put together your own tweaks with my WordPress Tweaks Composer.

  • I added the correct code to my functions.php but my ics-calendar shortcode (and others) won’t be executed.. any ideas?

    • Lasse, functions.php may not be the right place to do it. It is because many WP functions (including conditional tags like is_admin) don’t work as expected unless WP initialization has reached a certain point. I use a small plugin for this kind of tasks.

  • Hi – I landed on your page looking for a way to “shortcode” a widget without coding another template or plugin. It turns out what I wanted was kinda the other way round I think from what you are talking about….

    I wanted to use a widget as a shortcode…. and so a trial version of “shortcode_any_widget” was born. I thought I’d post a comment here in case other readers were looking for a similar thing. I hope that’s okay? See
    http://webdesign.anmari.com/shortcode-any-widget/

    • Anmari, sure it’s okay. (I understand when you try to use my blog to promote yours πŸ˜‰ )

      A nice idea BTW!

Blog Categories

I have come here to chew bubblegum and kick ass...
and I'm all out of bubblegum.
-- Nada in They Live