Conditionally Display WordPress Widgets with PHP
Displaying widgets selectively based on page context, user conditions, or post-specific rules is a common requirement in WordPress. Rather than relying on legacy plugins or wrestling with limited built-in options, you can implement this directly in your theme or custom plugin using WordPress hooks and conditional tags.
Why Custom Implementation Over Plugins
The Widget Logic plugin was the historical standard, but it’s no longer actively maintained. Modern WordPress has better native solutions. Building conditional widget logic yourself gives you full control, eliminates plugin dependencies, reduces performance overhead, and ensures compatibility with current WordPress versions.
WordPress Conditional Tags
WordPress provides conditional tags to detect the current page context:
is_single()— Single post pageis_page()— Static pageis_home()— Blog homeis_archive()— Archive page (category, tag, author, custom post type)is_category()— Category archiveis_tag()— Tag archiveis_search()— Search resultsis_404()— 404 error pageis_user_logged_in()— Current user is authenticatedis_singular( 'post' )— Single post (more specific thanis_single())is_front_page()— Site homepage
Method 1: Filtering Sidebars at Widget Render Time
The most reliable approach uses the sidebars_widgets filter in a must-use plugin or your theme’s functions.php:
<?php
add_filter( 'sidebars_widgets', 'conditionally_hide_widgets' );
function conditionally_hide_widgets( $sidebars_widgets ) {
// Don't modify in admin
if ( is_admin() ) {
return $sidebars_widgets;
}
// Hide ad widget on single posts unless explicitly allowed
if ( is_singular( 'post' ) ) {
$sidebars_widgets = remove_widget_from_sidebar(
$sidebars_widgets,
'adsense',
'primary-sidebar'
);
}
// Hide newsletter widget from search results
if ( is_search() ) {
$sidebars_widgets = remove_widget_from_sidebar(
$sidebars_widgets,
'newsletter-signup',
'primary-sidebar'
);
}
return $sidebars_widgets;
}
function remove_widget_from_sidebar( $sidebars_widgets, $widget_id_base, $sidebar_id ) {
if ( ! isset( $sidebars_widgets[ $sidebar_id ] ) ) {
return $sidebars_widgets;
}
$sidebars_widgets[ $sidebar_id ] = array_filter(
$sidebars_widgets[ $sidebar_id ],
function( $widget ) use ( $widget_id_base ) {
return strpos( $widget, $widget_id_base ) === false;
}
);
return $sidebars_widgets;
}
Method 2: Post-Level Control with Post Meta
For fine-grained control, use post meta to exclude widgets on specific posts:
<?php
add_filter( 'sidebars_widgets', 'conditionally_hide_by_post_meta' );
function conditionally_hide_by_post_meta( $sidebars_widgets ) {
if ( is_admin() || ! is_singular( 'post' ) ) {
return $sidebars_widgets;
}
$post_id = get_the_ID();
// Hide ads on posts marked with 'disable_ads' meta
if ( get_post_meta( $post_id, 'disable_ads', true ) ) {
$sidebars_widgets = remove_widget_from_sidebar(
$sidebars_widgets,
'adsense',
'primary-sidebar'
);
}
// Hide widgets from certain post categories
$excluded_categories = array( 'announcement', 'breaking-news' );
if ( has_category( $excluded_categories, $post_id ) ) {
$sidebars_widgets = remove_widget_from_sidebar(
$sidebars_widgets,
'sidebar-promo',
'primary-sidebar'
);
}
return $sidebars_widgets;
}
// Set post meta programmatically:
// update_post_meta( $post_id, 'disable_ads', '1' );
Method 3: Block-Based Widgets with Custom Rendering
For modern block-based themes, register custom blocks with conditional rendering:
<?php
register_block_type(
'mysite/ad-block',
array(
'render_callback' => 'render_conditional_ad_block',
'attributes' => array(
'hideOnSearch' => array( 'type' => 'boolean', 'default' => true ),
'hideOnArchive' => array( 'type' => 'boolean', 'default' => false ),
'hideOnHomepage' => array( 'type' => 'boolean', 'default' => false ),
),
)
);
function render_conditional_ad_block( $attributes ) {
// Hide on search results if configured
if ( $attributes['hideOnSearch'] && is_search() ) {
return '';
}
// Hide on archives if configured
if ( $attributes['hideOnArchive'] && is_archive() ) {
return '';
}
// Hide on homepage if configured
if ( $attributes['hideOnHomepage'] && is_front_page() ) {
return '';
}
// Hide if user not logged in
if ( ! is_user_logged_in() ) {
return '';
}
return '<div class="ad-block"><!-- Ad content here --></div>';
}
Practical Example: Role-Based Widget Display
Restrict widgets to specific user roles:
<?php
add_filter( 'sidebars_widgets', 'conditionally_hide_by_role' );
function conditionally_hide_by_role( $sidebars_widgets ) {
if ( is_admin() ) {
return $sidebars_widgets;
}
// Only show premium content widget to subscribers and above
if ( ! is_user_logged_in() ) {
$sidebars_widgets = remove_widget_from_sidebar(
$sidebars_widgets,
'premium-content',
'primary-sidebar'
);
return $sidebars_widgets;
}
$user = wp_get_current_user();
$allowed_roles = array( 'subscriber', 'editor', 'administrator' );
if ( ! array_intersect( $user->roles, $allowed_roles ) ) {
$sidebars_widgets = remove_widget_from_sidebar(
$sidebars_widgets,
'premium-content',
'primary-sidebar'
);
}
return $sidebars_widgets;
}
Debugging Widget Display Issues
Add this to your theme’s functions.php temporarily to see which widgets are registered:
<?php
add_action( 'wp_footer', 'debug_widgets' );
function debug_widgets() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
global $wp_registered_sidebars;
echo '<!-- Registered Sidebars: ' . wp_json_encode( $wp_registered_sidebars ) . ' -->';
}
Use your browser’s developer tools to inspect the HTML comment.
Where to Place Your Code
- Must-use plugin (recommended):
wp-content/mu-plugins/widget-conditions.php— loads before regular plugins - Theme functions:
wp-content/themes/your-theme/functions.php— loads with theme - Custom plugin: Standard plugin in
wp-content/plugins/— easier to maintain separately
Key Advantages
- No plugin dependencies or version conflicts
- Faster performance than plugins with additional hooks
- Full control over your logic
- Easy to version control
- Simpler debugging since the code is yours
- Works consistently across WordPress updates
