Sharing is Caring: WordPress Multisite and Sharing Widgets

WordPress Multisite is a powerful way to manage a network of individual websites from one administration location. You can find plenty of articles about Multisite out there – when it’s appropriate to use it, how it works, how to configure it – but we recently found ourselves with a Multisite-related use case that proved difficult to solve. We wanted to manage a particular widget area from the main site, and have the changes propagate to all of the sites on the network.

WordPress offers a nifty function called switch_to_blog() that can be used in similar situations (spoiler alert: it doesn’t work for widgets!). For example, you can use the following code in a theme or a plugin to display a menu that belongs to your main site:

switch_to_blog( 1 );
wp_nav_menu( $args );
restore_current_blog();

This function won’t work to load widgets because of how/when widget content is loaded. It doesn’t appear that there are any plans to change this.

So, what to do? We found surprisingly few write-ups about how to solve this problem, but there was a post from 2013 by WebDevStudios that started to lead us in the right direction. The solution proposed in their article didn’t work for us – the original author has written a few comment replies indicating that the solution is probably out-of-date. However, there was a more recent and simpler solution (no AJAX!) to be found in the comments.

With a few tweaks, our solution worked.

/**
* When sidebar is edited on main site, update sidebar on all subsites.
*/


// This is the function you use to place / call your sidebar at a specific theme location.
// Accepts the sidebar's id as a parameter.
function example_multisite_sidebar( $sidebar ) {

// Try to get the stored widget content for the sidebar.
$markup = get_site_transient( 'sidebar_cache_' . $sidebar );

// If we're not on the main site and the transient exists, display the stored widget content.
if (!is_main_site() && $markup ) {
echo $markup;
} else {
// If we're not on the main site and the transient doesn't exist, we make a call to the main site, which kicks off example_multisite_sidebar_save().
if (!is_main_site()) {
$url = add_query_arg( array('get_sidebar' => $sidebar), get_site_url( 1 ) );
$request = file_get_contents( $url );
echo $request;

// display the content
echo get_site_transient( 'sidebar_cache_' . $sidebar );
} else {
// If we're on the main site and the transient doesn't exist, store the widget content in the transient.
ob_start();
dynamic_sidebar($sidebar);
$markup = ob_get_clean();
set_site_transient( 'sidebar_cache_' . $sidebar, $markup, 4*60*60 );
echo $markup;
}
}
}

add_action( 'template_redirect', 'example_multisite_sidebar_save' );
function example_multisite_sidebar_save() {

// If we're on the main site and the get_sidebar query var is set,
// start a buffer that will record the widget content.
if ( is_main_site() && isset( $_GET['get_sidebar'] ) ) {
$sidebar = $_GET['get_sidebar'];
ob_start();
dynamic_sidebar( $sidebar );
$markup = ob_get_clean();

// Set a transient to store the HTML of the widget content
set_site_transient( 'sidebar_cache_' . $sidebar, $markup, 4*60*60 );

// Also display the content. This ensures that the content gets displayed if a site other than the main site is the first to be loaded after an update.
echo $markup;

die();
}
}

// Delete all sidebar transients when editing sidebar widgets.
add_action( 'sidebar_admin_setup', 'example_multisite_sidebar_clear_cache' );
function example_multisite_sidebar_clear_cache() {
global $wp_registered_sidebars;
foreach($wp_registered_sidebars as $sidebar){
delete_site_transient('sidebar_cache_' . $sidebar['id']);
}
}

 

With this code, we’re able to update a widget on the main site, and then immediately see the changes on any of the network sites. If you’ve got a suggestion for improvement, we’d love to hear it! Drop us a line on Twitter.

Share

Similar Posts
Also tagged Web Optimization

How many clicks does it take?

Also tagged Web Optimization

Leverage Browser Caching for a Lightning-Fast Website

Also tagged Web Optimization

Decrease load speed on your WordPress website