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.
Most advice on this converges to this simple line of code:
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.
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.
- The WordPress plug-in load order is one of the bigger mysteries in the universe 😉 [↩]