Nested WordPress Shortcodes

Have you tried calling a shortcode within another shortcode and discovered it doesn’t work?

WordPress makes nested shortcodes possible but requires each shortcode to actively participate by calling do_shortcode() when exiting.

For a recent client’s needs, I created a simple shortcode in the child theme’s functions.php that allowed to them to display different content to logged-in and non-logged-in users. I needed to wrap that around Events Manager‘s event_list shortcode to display different calendars in the same widget based on the user’s logged-in status.

Because the “outer” shortcode was my own, I could modify it without fear that a plugin update would overwrite the change.

Here’s the modification in the non-logged-in user’s version. Note the use of do_shortcode wrapped around the $content in the return line.

function visitor_check_shortcode( $atts, $content = null ) {
if ( ( !is_user_logged_in() && !is_null( $content ) ) || is_feed() )
return do_shortcode($content);
return ”;
}

With this one small change, the shortcode will now pass the content on to the next shortcode for further evaluation (or return nothing if the conditions are not met). In this client’s use scenario, the next shortcode displays the correct event list for non-logged-in users. Here’s what is in the text widget:

[visitor][events_list scope=”future” limit=5 pagination=1 category=9,10,12][/visitor]

Easy enough but what if you need to nest two 3rd party shortcodes and neither calls do_shortcode() properly? You are left with three choices, none of them ideal:

  • Modify their code (and wait for an update to overwrite your changes and break your site)
  • Use a plugin such as Outerbridge Nested Shortcodes
  • Live with using one shortcode at a time

In many cases requiring nested shortcodes, one shortcode is controlling visibility and the other is providing content. The visibility shortcode is almost always the outermost shortcode when nesting. If it is doing something simple, another option is to replace it with your own shortcode where you can properly use do_shortcode(). If the shortcode is part of a plugin with more complex functionality, does it offer an API you can call to still create your won shortcode? If yes, you may still be able to do nested shortcodes without yet another plugin.