In the WordPress Codex where it talks about the “strip_shortcodes()” function it includes this example of how to selectively disable shortcodes on the Home page but show them elsewhere:

1
2
3
4
5
6
7
function remove_shortcode_from_index($content) {
  if ( is_home() ) {
    $content = strip_shortcodes( $content );
  }
  return $content;
}
add_filter('the_content', 'remove_shortcode_from_index');

But the problem with this is it is an “all or nothing” deal.  You either show all shortcodes or hide all shortcodes.  What if you want to selectively show some shortcodes and hide others?  Let’s say you have three custom shortcodes you created.  As you may have found out, if you don’t register your shortcodes in the functions.php file then the actual [shortcode]…[/shortcode] code itself will show up in your posts, which you obviously don’t want.  Let’s say we have three custom shortcodes:

[shortcode_a] you want to show pretty much everywhere, except on your home page.

[shortcode_b] you ONLY want to show when posts are being shown in your archives.

[shortcode_c] should show up on both single posts and on your home page, but not in archives.

Ok, so how would you do that?  Well one method is to set up your shortcodes in functions.php (or your plugin functions) with conditional statements checking the current page:

1
2
3
4
5
6
7
8
9
10
11
12
function my_shortcode_c( $atts, $content = null) {
     extract(shortcode_atts(array(
     'color' => 'blue',
     'class' => 'monkey'
     ), $atts));
     if ( is_home() || is_single() ) {
          $C = '<div class="'.$class.'"><span style="color:'.$color.'">'.$content.'</span></div>';
     } else {
          $C = '';
     }
     return $C
}

That sort of structure will handle most of your conditional shortcode needs. Also, if you wanted it to return the content of the shortcode without the wrapper you could make the “else” paret read “$C= $content” and it would just echo back whatever is in between the [shortcode]..[/shortcode].  All you need to do is swap out the conditional tags in the “if” statement and those pesky shortcodes will dance to whatever tune you play.

But what if they don’t?  I ran into an issue with a custom post type where, because it wasn’t a “template” or an “archive” but a post itself AND it was pulling in other posts in the same category, the conditional function logic above wouldn’t work!  If I used the shortcode in the body of the custom post itself, then adding something like “mytype” == get_post_type()  to the “if” statement worked, but ONLY for the shortcodes actually attached to the custom post itself.  If I tried to use that same shortcode on a regular post being displayed within the custom post, so far as WordPress was concerned the post_type was “post” and NOT “mytype.”  I had a secondary problem that I needed to run two loops with the custom post_type content, and in the first extract only [shortcode_a] content but not [shortcode_b] and in the second loop vise versa.  Which meant I needed to redefine the conditional selection mid-page as well.  So, how would I go about doing that?

Well, as it turns out you aren’t restricted to placing your shortcode functions in your functions.php or plugin functions files.  They CAN be placed in code on the front-facing template pages, which means we can define or redefine shortcodes on a local basis!  I know I was talking about doing it in a custom post_type page, but you can actually do it with any of the front-facing pages:

In functions.php:

1
2
3
4
5
6
7
8
9
10
11
12
function my_shortcode_a_include( $atts, $content = null) {
     return '<div class="monkey">'.$content.'</div>';
}
<pre>function my_shortcode_b_exclude( $atts) {
     return '';
}
<pre>function my_shortcode_c_exclude( $atts) {
     return '';
}
add_shortcode('shortcode_a','my_shortcode_a_include');
add_shortcode('shortcode_b','my_shortcode_b_exclude');
add_shortcode('shortcode_c','my_shortcode_c_exclude');

Ok, what that does is is creates [shortcode_a] so it works by default.  [shortcode_b] and [shortcode_c], however, are set to return nothing by default (this prevents the actual bracketed code from showing).  Now, for each of the aforementioned conditions we add shortcode functions to the pages. . .

In index.php:

1
2
3
4
5
6
7
8
function my_shortcode_a_exclude( $atts) {
     return '';
}
function my_shortcode_c_include( $atts, $content = null) {
     return '&lt;p class="important"&gt;'.$content.'&lt;/p&gt;';
}
add_shortcode('shortcode_a','my_shortcode_a_exclude');
add_shortcode('shortcode_c','my_shortcode_c_include');

Now on the Home page [shortcode_a] content is hidden, [shortcode_b] is still set to be hidden by functions.php so we don’t need to change it, and [shortcode_c] content will now show up.

In my single.php file:

1
2
3
4
function my_shortcode_c_include( $atts, $content = null) {
     return '&lt;p&gt;'.$content.'&lt;/p&gt;';
}
add_shortcode('shortcode_c','my_shortcode_c_include');

In this case [shortcode_a] will use the default “include” setting in functions.php, [shortcode_b] will also use the default “exclude” setting in functions.php, so we only need to “include” [shortcode_c] and our single posts will now show content from both shortcodes “a” and “c” but not “b.”

In my archive.php file:

1
2
3
4
function my_shortcode_b_include( $atts, $content = null) {
     return '&lt;p&gt;'.$content.'&lt;/p&gt;';
}
add_shortcode('shortcode_b','my_shortcode_b_include');

Here [shortcode_a] will appear because that’s the default setting in functions.php, [shortcode_c] will not be included because that is the default setting in functions.php, so we only need to “include” [shortcode_b] content.

And, lastly, you can redefine them “on the fly” in the same page if you repeat the loop and want to change your selectors.  Just switch the “add_shortcode” to the “include” or “exclude” function as needed.