Show or Hide a WP widget only on specific page/s without using a plugin

1 Sep

Widgets make a WP theme’s sidebar alive. Small but important pieces of info which shouldn’t be restricted to a single page, can be put into a widget and made available on all the pages through the sidebar. But sometimes you might want to show a widget only on specific pages or page. One would code multiple sidebars and call them according to the pages, by adding different widgets to them or simply use a plugin to do this. But you don’t need to code multiple sidebars, just follow this simple piece of code, and you’ll know how to show/hide widgets according to the pages without using a plugin.

Obviously, you should know the following before you read further:
1. WP – Yeah, of course ;) But more on the developer level.
2. WordPress Filters – What, Why, How, When?
3. Firebug powered FireFox – Stop developing websites if you don’t know what Firebug is :P !

You reached here? Kewl! Let’s get to work…

Consider the following use case – We don’t want to show the default ‘Archives’ widget on the home page of our site.

When a new widget is coded, a unique identifier is added for it. Look at the code for the default ‘Archives’ widget that comes along with WordPress (‘default-widgets.php’, line no. 214):

class WP_Widget_Archives extends WP_Widget {

	function WP_Widget_Archives() {
		$widget_ops = array('classname' => 'widget_archive', 'description' => __( 'A monthly archive of your site’s posts') );
		// The first argument to WP_Widget, 'archives' is the identifier we're talking about
		$this->WP_Widget('archives', __('Archives'), $widget_ops);
	}
// blah blah.....
}

Here, the identifier is ‘archives’. This identifier is also used to generate an id for the ‘<li>’ tag that holds the widget in the sidebar, by dynamically appending a number to its end. You can examine the id by using Firebug. See the following screens for an idea:

‘archives-4′ was generated from ‘archives’ in the code. You can get the identifier for any widget you want to show/hide by examining it using Firebug.
Now we get to the ‘meat of the matter’, hiding the widget according to the page.
We’ll use the Filter Hook ‘sidebars_widgets’ for accomplishing this. Let’s hook a function to this filter. You can put this code in the ‘functions.php’ file of your theme.

add_filter('sidebars_widgets', 'hidemywidget');
function hidemywidget($all_widgets)
{
    echo "<pre>";
    print_r($all_widgets);
    echo "</pre>";
//comment the following and tell me what happens!
    return $all_widgets;
}

We’ve hooked the function ‘ hidemywidget’ to the ‘sidebars_widgets’ filter hook. The argument to this function contains the array of generated identifiers for all the widgets active in the sidebars, as well as the inactive ones. We’re interested in the id for the ‘archives’ widget. Observe the contents of the ‘$all_widgets’ array. It contains an array that holds the id’s of all the inactive widgets, ‘wp_inactive_widgets’, and the arrays of widget id’s corresponding to the dynamic sidebars/widget areas that you register using ‘register_sidebar’. I’m using the ‘primary-widget-area’ from ‘Twenty Ten’ theme. So my array of widget id’s looks as follows:

Now we check if we’re on the homepage, and if yes, remove the ‘Archives’ widget, by removing the ‘archives-4′ id from the ‘primary-widget-area’ array. We cannot use the generated id ‘archives-4′ directly to remove the widget, as the number ’4′ is dynamically appended to it and may change depending on the widget’s position, and some other factors (which I seriously don’t know :P )
Modify the code as follows:

function hidemywidget($all_widgets)
{
    //this should run on the homepage / frontpage only! you can use more conditions here
    if(is_front_page() || is_home())
    {
        foreach ($all_widgets['primary-widget-area'] as $i => $inst)
        {
            //check if the id for the archives widgets exists.
            $pos = strpos($inst, 'archives');
        
            if($pos !== false)
            {
                //remove the archives widget by unsetting it's id
                unset($all_widgets['primary-widget-area'][$i]);
            }
        }
    }
//comment the following and tell me what happens!
return $all_widgets;
}

Visit your site’s homepage, and wallah, the ‘Archives’ widget has disappeared from the sidebar! Don’t forget to check the other pages to make sure it shows up in the sidebar!

There might be better ways to do this, please let me know if you find one! In case of a doubt, feel free to mail me at ‘mail@rutwick.com’.
Adios!

16 Responses to “Show or Hide a WP widget only on specific page/s without using a plugin”

  1. Michael Dorf September 1, 2011 at 4:32 pm #

    Great advice, thank you! I prefer this method over a plugin because I know exactly what code gets executed here!

    • rutwick September 2, 2011 at 3:20 am #

      Exactly!
      I did this for the same reason, I didn’t wanna use another plugin just to show/hide a widget and wanted to have a better control over my code!

      You’re welcome!
      -Rutwick

  2. Renji September 4, 2011 at 4:15 pm #

    Hey rutwick, unfortunately this didn’t work for me.

    I want to hide tag_cloud widget which is on sidebar-1. This is what I am using:

    .
    .
    foreach ($all_widgets['sidebar-1'] as $i => $inst)
    {
    $pos = strpos($inst, ‘tag_cloud’);

    if($pos !== false)
    {
    unset($all_widgets['sidebar-1'][$i]);
    }
    }
    }
    .
    .

    What’s wrong with it??

    • rutwick September 5, 2011 at 3:19 am #

      Hi,
      As far as I can see, there seems nothing wrong with this code.
      Aren’t you checking which page you’re on to hide the widget? Could you paste/mail me the code you’re trying and the $all_widgets array (print_r > copy > paste)? I’ll need to see the array and what you’re trying to figure out what’s wrong.

      -Rutwick

  3. Roberto December 19, 2011 at 4:54 pm #

    Good morning, I apologize in advance because I do not understand English but I will translate through google, I hope my words are understood.

    I asked a question through “WordPress answers” in which I answered very timely because my problem is with the error that I mark on my blog, I can not get into my desktop the message is:

    Warning: require(/home/miyamoto/public_html/blog/wp-includes/classes.php) [function.require]: failed to open stream: No such file or directory in /home/miyamoto/public_html/blog/wp-settings.php on line 68

    Fatal error: require() [function.require]: Failed opening required ‘/home/miyamoto/public_html/blog/wp-includes/classes.php’ (include_path=’.:/usr/lib/php:/usr/local/lib/php’) in /home/miyamoto/public_html/blog/wp-settings.php on line 68 as I realize that I have is like the file that says “clase.php” so that gives me the error What I can do or how to fix it?

    Gracias por la respuesta.

    Bendiciones

    Roberto.

    • rutwick December 24, 2011 at 3:42 am #

      Hi Roberto,
      It’s a commonly known error with WordPress upgrades. Google around for that error message you’re getting, and I’m sure you’ll find something. Let me know if you found anything, if not, I’ll do the favor!
      Gracias!

  4. Abid December 24, 2011 at 12:39 am #

    Thanks man it works for me. I use the code like this,

    add_filter(‘sidebars_widgets’, ‘hidemywidget’);
    function hidemywidget($all_widgets)
    {
    //comment the following and tell me what happens!
    if (is_page(’5′)|| is_page(’9′)){
    unset($all_widgets['sidebar-1'][2]);
    return $all_widgets;
    }
    else if (is_page(’33′)||is_page(’45′)){
    unset($all_widgets['sidebar-1'][2]);
    unset($all_widgets['sidebar-1'][1]);
    return $all_widgets;
    }
    else{return $all_widgets;}
    }

    • rutwick December 24, 2011 at 3:46 am #

      Hi Abid,
      Glad it worked !
      But what is if (is_page(’5′)|| is_page(’9′)) doing in your code? Let me warn you it can and will fail if you transfer the code between 2 sites as the page ids will change! Use the Conditional Tags provided by WordPress instead. Let me know if I can assist you.

      - Rutwick

  5. marbie design March 6, 2012 at 8:50 am #

    Hi All,

    I do this using css.
    I find the pageID and widgetID and hide it like this

    .page-id-47 #text-2 { display:none;}

    • rutwick April 6, 2012 at 3:39 pm #

      Yep… That’s a quick solution too!

    • Peter November 21, 2012 at 5:08 pm #

      Hi Marbie,

      Thanks for the short solution. In what file to do you add that css code for wordpress
      Thanks
      Peter

      • rutwick March 2, 2013 at 9:03 pm #

        The styles.css file if its a theme, or make a new css file and enqueue it using wp_enqueue_styles.

  6. Matt December 13, 2013 at 2:59 pm #

    Thanks Rutwick, very handy!

    • rutwick December 27, 2013 at 10:07 am #

      You’re welcome! Glad I could help!

  7. Nicole August 12, 2014 at 4:47 am #

    Ok, phew – I have fixed it, but I still have some questions about this hide sidebar code and if you would be available for hire? Would you be able to email me? Thanks!

  8. rutwick August 14, 2014 at 2:09 pm #

    Hi Nicole,

    Sure! I’ll send you an email. What exactly happened? Do you see any errors?

Leave a Reply