How to Publish to Multiple WordPress Sites from a Single Install

How would you like to be able to publish to as many different WordPress sites as you liked from a single install? So you only need one configured install of editflow and one set of plugins (listed below)  together with one place to login and manage your content.

feature

Welcome to the WordPress Content Hub – a solution for push syndicating content to any WordPress install, be it multisite or on WordPress.com… let’s get publishing!

Hub and Spokes

All content management systems, from the simplest blogging platforms to the most complicated enterprise-level applications perform two major tasks: content management, providing the tools to create, review and ultimately publish content; and, content delivery, actually putting that content into the hands of users.

Splitting the content management and delivery functions
Splitting the content management and delivery functions

The Content Hub splits out those two functions using a “hub and spoke” model. The Hub is a single WordPress site dedicated to content management which pushes content to one or more Spokes that handle the content delivery.

There are a number of reasons why you might opt for a Content Hub:

  1. You have separate sites for mobile and / or tablet visitors
  2. You manage a network of sites within a niche and you often cross-post content
  3. You have a team of authors that write content for any part of your network
  4. You have a tried and tested suite of admin plugins driving your publishing process that you currently have to install and maintain on every new site you launch
  5. You want a “staging” site – somewhere outside of the live site where content can be created, reviewed and tested

Benefits of the Hub and Spokes model

Single location for content management

With a Content Hub, all your content is managed in a single spot. Not only does that make it easier to manage your user accounts but publishing content to multiple sites and to your social media sites is a breeze.

Simpler WordPress installs

No longer do you need to install that potentially conflicting mix of admin and front-end plugins. The Hub needs only the plugins required to create and manage content; the Spokes only need the plugins and themes required to deliver the content. The end result is leaner and easier to maintain WordPress sites.

Security

With no requirement for public access, the Hub can be tightly locked down. You can restrict the entire site to logged-in users only, only allow access from specified IP address and put the entire site under SSL. You can even host the Hub locally so long as it has a pathway out to the internet.

Push to multiple sites in single action. Delete too!

Push a post to multiple sites by simply clicking a few checkboxes. No more cutting-and-pasting from one site to another. And move the post to the Hub’s trash and it’ll be trashed on all the Spokes too.

Publish to social media

Set-up one of the many social posting plugins in the Hub and publishing to social media accounts is also centralised.

Using a CDN for images and attachments

A CDN will vastly improve your hub
A CDN will vastly improve your hub

In the Hub and Spoke model, images and other attachments are not pushed to each Spoke’s environment – it’s needless duplication. By default, all the network’s images, video, audio and documents are uploaded to and served from the Content Hub which, depending on the number and size of files, may stress your Content Hub’s hosting platform. It also means that you will not be able to host your Content Hub locally.

To maintain maximum flexibility and reliability, improve backup and recovery and to generally make your Hub and Spokes easier to manage, you should use a content delivery / distribution network (CDN) to host your non-HTML assets.

Setting up a CDN is outside the scope of this article but Sufyan bin Uzayr has everything you need to know about WordPress and CDNs.

A quick word about APIs

There are two APIs that can power the Hub and Spoke approach: the XML-RPC API and the JSON-based REST API. XML-RPC is supported out-of-the-box by self-hosted and WordPress.com sites. REST API is built into WordPress.com but self-hosted sites will need to install either JetPack or an experimental plugin.

The XML-RPC API is the simplest to use and so that’s what we are going to use here. If you’d prefer to use the REST API, then there’s good documentation on how to set it up in the official plugin repository. Remember, that in order to use the REST API you must create an application in WordPress.com and it must be able to see the Hub which will prevent you from hosting it locally.

Setting up the Hub

1. Select your Hub site

Whilst you can utilise an existing site, it’s better to create a clean WordPress install for the hub. If you want to seed the Hub with existing content then you can always import the content from existing sites using WordPress’ Import Tool.

2. Install and configure the Push Syndication plugin

Push syndication is the key plugin that performs the pushing of content to the Spokes. Once installed, configure the plugins at Settings > Push Syndicate Settings.

The Push Syndication plugin's settings page
The Push Syndication plugin’s settings page

Select the post types you want to syndicate (don’t select attachment) and check the option to Delete Pushed Posts.

The API Token Configuration is only required when using the REST API so you can ignore that.

Once installed, you need to add the syndication key to your Hub’s wp-config file. Open the file in your favourite editor and add this line somewhere above the famous /* That’s all, stop editing! Happy blogging. */ line.

{code type=php}define(‘PUSH_SYNDICATION_KEY’, ‘put-your-unqiue-syndication-key-here’);

3. Create Site Groups

The Push Syndication plugin pushes content to selected Site Groups. How you group your sites depends on your needs but unless you have two sites that are very similar, it is likely that each group will only contain one site.

Site Groups are created via the Sites option in the main Admin menu.

4. Set the Permalink structure

To make sure that internal links will work, there are two requirements when it comes to setting the Permalink structure:

  1. Do not use IDs! These will be different between your Hub and your Spokes. Any links containing IDs will likely give unintended results
  2. Be consistent! The Hub and all your Spokes must use the same permalink structure. If any of your Spokes are on WordPress.com structure then you must use the WordPress.com default of Day and name.

5. Create a category structure

How you structure the categories in your Hub will depend on how many Spokes you have, how many categories appear in multiple sites and your personal preference.

The key points to remember are:

  1. The push syndication process uses category names so these need to be the same in the Hub as they are in the Spokes
  2. Hierarchy doesn’t matter
  3. If a Spoke cannot find a matching category, then it will create one.
  4. Additional categories with the same name are ignored
  5. This is only about organisation – the categories do not control syndication

You have three main choices, then, for setting up your category hierarchy. To illustrate, let’s assume you have a network of three Spokes, one a generic site about all things WordPress, one a site specifically for BuddyPress and one a site specifically for Multisite.

Option 1

Screenshot of WordPress category page showing replicated site category structure
The first option is to create top level categories for each Spoke (in this example, BuddyPress, Multisite and WordPress) and then recreate each Spoke’s individual category structure underneath it’s top level category.This approach makes it very easy to determine the intended destination of the content but can result in the duplication of categories as can be seen with the multiple entries of News, Plugins and Themes. However, assigning a post with multiple categories of the same name does not cause any issues with the push syndication process.This approach can become unwieldy if the Spokes have extensive category structures. </p> <p>

Option 2

mage of WordPress category screen showing a simplified structure with common categories grouped and only unique categories under the specific site
The second option groups all the common categories together and only creates a top-level category for those Spokes that have unique categories. In our example, News, Plugins and Themes appear in multiple Spokes and so these categories are grouped under Common.The WordPress Spoke has the unique categories Hosting, Opinion and Reviews and so these are created as a separate structure.This makes for a much smaller and more manageable structure. </p> <p>

Option 3

Image showing a WordPress Category screen with all Spoke references removed
The third option is to remove references to the Spokes altogether and work with a consolidated structure. This will produce the shortest structure, six categories compared to fifteen in Option 1, and the easiest to manage.This approach is best suited to networks where Spokes have a similar structure. </p> <p>

Optional plugins

That’s all you really need to create your Hub but there are some additional plugins that you might want to consider to improve your content management processes:

ABT Relative URLs

By default, the WordPress WYSIWYG editor inserts absolute URLs into content for links to other posts and pages and for media files. This will cause all links in the Spokes to point back to the Hub rather than to the same content in the Spoke. The ABT Relative URLs plugin solves that problem by converting all local absolute links to relative links. Only use this plugin if you are using a CDN for your media files otherwise they will also all get converted.

Restricted Site Access

As mentioned previously, one advantage of splitting the functions of a content management system is that you can fully lock-down the Hub. The Restricted Site Access plugin can limit access to the Hub to logged-in users only or restrict access to specified IP addresses.

Category Checklist Tree

Screen-grab showing the category listing from the Edit Post screen
Categories stay “in place”.

When populating the Categories metabox on the post edit screen, WordPress’ default behaviour is to put any categories assigned to the post at the top of the list. The Category Checklist Tree plugin overrides this behaviour and instead highlights the categories within the category structure.

This is invaluable if you decide to use a category structure with Spokes at the top-level.

Editflow

The ultimate tool in planning your content. In a traditional install it can clutter the interface but it fits well in a content management focussed Hub. Again, Sufyan has more on Editflow in his article Five Free WordPress Plugins to Manage a Multi-Author Site with Ease.

Adding Spokes to your Network

For self-hosted sites we just need to complete a couple of minor preliminary tasks.

  1. Create a new user with the Editor role. This is the user that the Hub will use when pushing the content and so it has to have full publishing rights. Don’t forget, this user will appear as the Author if your theme is outputting author information in the post meta, so ensure that you give it a suitable name.
  2. Ensure that the permalinks are set up with the same structure as the Hub (most likely Day and name).

Adding a site in the Hub

  1. Go to the Hub dashboard and click on Sites in the Admin menu.
  2. Click on Add a site. Enter a title for the site; select WordPress XMLRPC as the transport type; enter the root URL for your site; enter the username and password for the Editor role (or the appropriate WordPress.com user); check enable; check the appropriate Site Group; and, click on Add Site. You can click on Add New Site Group if you need to create a new site group.

The plugin will attempt to contact the site using the URL, username and password. If all is good then you’ll get a confirmation message that everything is okay.

Screenshot showing the Push Syndication Add A Site screen
Adding a site. Don’t forget to assign a Site Group!

Repeat this for all your sites.

Syndicating content

Now that you’ve set up your Hub and Spokes, we can finally get to the exciting part: actually syndicating content!

In the Content Hub, open the Add New Post screen and create a post as you would do normally. As post formats, featured images, custom fields and authors are not supported by push syndication process, you may as well tidy up the interface and uncheck these items in the Screen Options pulldown.

Keep in mind that:

  • The Author will be the user you entered when you added the site to the Hub
  • All images and attachments must be embedded – if you are using a CDN then they will be served from there, if not they will be served from the Content Hub (this will also dictate whether you host the Hub locally or not).
  • All internal links must be relative so that they work correctly on the Spokes rather than pointing back to the Hub. If you are using a CDN then you can do this automatically by installing the ABT Relative URLs plugin. Otherwise you’ll need to update the URLs manually before publishing.
  • The category will be created in the Spoke if it does not already exist
  • Tags are pushed to the Spokes
Screenshot showing the list of site groups in the Syndicate metabox
Selecting the site groups that you want to push this post to. Using a 1-to-1 group to site relationship.

Once you have finished drafting your post, you need to select the Site Groups in the Syndicate metabox that you want the content pushed to.

Click Save Draft then click Publish. Sometimes posts are not always pushed if not saved first. If you have author-editor publishing model then the save will happen anyway as part of your process; if you don’t then it’s probably well worth getting into the good habit of using at least a two-step publishing process.

Okay, now go check your Spokes! Your syndicated content should now be there!

Deleting content

An added bonus with the Push Syndication plugin is that it handles deletion of posts as well, so long as you activated support of this feature in the plugin’s settings page. Simply trash a post and it will be removed from the relevant Spokes.

In fact, you will need to trash a post to remove it from a Spoke as simply unchecking it in the Syndicate metabox seems to have no effect. To remove a post from a single Spoke you’ll need to:

  1. Uncheck the appropriate Site Group
  2. Update the post and then trash it (this will remove it from all Spokes)
  3. Go to Trash and restore it.
  4. Update it (this will push it out to the remaining checked Site Groups)

Further considerations

Extending the Push Syndication plugin

Providing more sophisticated push syndication requires significant upgrades.
Providing more sophisticated push syndication requires significant upgrades.

The Push Syndication plugin has been built to provide a one-way, one-time interaction with the WordPress APIs and so its capabilities are fairly basic.

To provide more sophisticated push syndication that caters for featured images, authors and custom fields (and therefore true custom post type support) requires significant upgrades to allow for two-way, multiple interactions.

For example, to be able to set the author to something other than the Editor, requires the Hub to first ask the Spoke for a list of its authors so it can use the Spoke’s author ID in the push process. Supporting custom fields requires the Hub to get a list of the custom fields from the Spoke so that it can use each field’s unique ID in the push process.

Non-WordPress Spokes or even non-WordPress Hub

The real flexibility of the Hub and Spokes model becomes apparent when you start to consider Spokes and even a Hub that are not hosted on WordPress.

Any application that can implement the WordPress API can act as a Spoke and any application that can talk to the API can be the Hub. This means that you can mix and match your applications, swapping the Hub and Spoke platforms without impacting on the rest of your network.

If you’d prefer to use Drupal for content management, or a custom web app, that’s fine, so long so long as they can talk to the WordPress API.

Pulling rather pushing

Just like any WordPress site, the Content Hub supports the WordPress XML-RPC API and, via a plugin, will support the REST API so content doesn’t have to be pushed by the Hub, it can also be pulled by the Spoke.

Content can also be pulled by the Spoke.
Content can also be pulled by the Spoke.

The most likely scenario for pulling is a Spoke that is an application such as an HTML5 web app or an app running on a tablet or smartphone. The app makes use of the Hub’s API to pull new content down to the device. It’s even possible that it may use the Hub (or possibly a dedicated Spoke) for managing memberships and subscriptions.

The Push Syndication plugin may have its limitations but when combined with a CDN, it provides an easy and efficient method for managing the content for multiple sites from a single WordPress install.

If your sites are using the standard post types and you don’t mind using a single author, perhaps you should be considering setting up your own Content Hub?

photo credit: bailey weaver, toffehoff

25 Responses

  • Design Lord, Child of Thor

    Hey Chris.

    Very interesting. Two things

    1) Would adding BuddyPress to the hub change things in any way? Or would that kinda we unnecessary overkill?

    2) Re: ” self-hosted sites will need to install either JetPack or an experimental plugin.”

    Correct me if I’m wrong but if this is the API plugin I think it is then I think it’s worth mentioning that – as far as I know (read: the last time I checked) – it has no authentication. Therefore, in theory, someone could exploit that hole and dump a load of spam into your site.

    Again, I could be mistaken but I’m pretty sure that’s not the case.

    Otherwise, great stuff. Thanks for sharing.

  • CA,

    1) I think the Hub works best in a “private” setting with core content, so BuddyPress with its user generated content wouldn’t fit too well. Would be fine out on a Spoke though.

    2) The plugin (Ryan McCue’s GSoC project) has provision for authentication but does allow for no credentials to be passed. It has a filter as the first step of the authentication check, so it would obviously be advisable to use it to enforce authentication.

    3) That’s a really interesting idea. Allow Editors to browse the content and filter the syndication metabox so that they could only push to their site(s)? A less elegant solution would be to push all content out to the Spokes but in draft format and allow the Editors to publish or trash as appropriate.

  • ghc
    Site Builder, Child of Zeus

    Interesting concept. Interesting enough to not finish, but want to save for later. I clicked the google +1 button (which I almost never do), and nothing happened other than the console spitting out some errors that I thought I’d share:

    Uncaught TypeError: Cannot read property ‘plusones’ of undefined
    Uncaught TypeError: Cannot read property ‘prototype’ of undefined
    Uncaught ReferenceError: iframes is not defined fastbutton?bsv=o&usegapi=1&size=medium&annotation=bubble&hl=en-US&origin=ht…__%2Fam%3DAQ%2Frt%3Dj%2Fd%3D1%2Frs%3DAItRSTOQ24EYekGChHwK0fj3o1FZHHkWdA:21
    Uncaught TypeError: Cannot read property ‘plusones’ of undefined
    Uncaught TypeError: Cannot read property ‘prototype’ of undefined
    Uncaught ReferenceError: iframes is not defined fastbutton?bsv=o&usegapi=1&size=tall&hl=en-US&origin=http%3A%2F%2Fwpmu.org&…__%2Fam%3DAQ%2Frt%3Dj%2Fd%3D1%2Frs%3DAItRSTOQ24EYekGChHwK0fj3o1FZHHkWdA:21
    Uncaught TypeError: Cannot read property ‘plusones’ of undefined
    Uncaught TypeError: Cannot read property ‘prototype’ of undefined
    GET http://a.adroll.com/j/roundtrip.js

  • New Recruit

    thanks for the insight Chris.

    this interests me a great deal. not only a central hub for creating and delivering content, but also finally a solution to using edit flow to manage content creation and publication across a network of sites.

    A couple of questions if I may….?

    Can the ‘content hub’ push content to subdomains on a multisite install? How about for subdomains that have been domain mapped?

    if I want to slightly modify each piece of content before it is published in each spoke for uniqueness, how would you suggest structuring the hub?
    e.g. 1 article, about 1 topic to 10 sites, but slightly re-worded prior to publishing. Can this all be handled within the hub or would the original be syndicated to the 10 sites as a draft, then the final changes made at ‘spoke’ level?

    thanks
    Paul

  • Paul,

    I didn’t test the multisite subdomains but as a WordPress site they will also implement the XML-RPC interface, so there’s no reason why it wouldn’t work, either as straight sub-domain or a mapped domain.

    The uniqueness is a little tricky as obviously syndication is generally about the same content.

    You want to have all your variations in the same post so that you can have that 1 article and syndicate it to the 10 sites.

    The simplest approach would be to wrap the modifications in shortcodes in the Hub. For example,

    This content appears on all sites.

    [site id=”1″]But this content is for site 1 only[/site]
    [site id=”1,2″]This is content for site 1 and 2 only[/site]
    [site id=”3″]This is content for site 3 only[/site]

    Ideally, you want to filter the content during the syndication process so you’ll need to tweak the syndication plugin to call a filter before assigning the post content.

    Alternatively, you could alter the content in the Spoke using the the_content filter. There’s no tweaking of existing code required but you’ll obviously need access either to the theme or the plugin directories in the Spoke.

    Getting posts into the Spokes as drafts can be done with a small tweak to the plugin. By default it uses the post status of the Hub post and as syndication only happens on publish, the Spoke’s status is also publish.

    • New Recruit

      thanks Chris.
      My priority use is to be able to run a ‘newsroom’ concept to publish content across multisites.

      I was toying with the idea of creating a 2-tiered content hub. The first layer is the home for original or seed content, this is created and managed through various statuses with Edit Flow – then pushed out to a second content layer (call it a ‘pre-spoke’ layer :), where the spoke content can be modified centrally, prior to the final syndication push to each spoked live site.

      I may be confusing the issue here, but my main goals are to centrally manage content creation for authors and editors, without them needing or having access to the live sites.

      With this in mind, I’m also interested to know if site and content access can be controlled per author/editor within the content hub/s.

  • Paul,

    If you’ve got multiple authors modifying the content for their own sites then it’s going to be easier to set up a category structure in the (pre-spoke) hub that reflects the spokes’ structures and have multiple versions of the content.

    You can use a plugin such as Restrict Categories to control which categories an author can post to, so if you put sites at the top level category then you can control the sites authors have access to.

    That said, the seed hub is only going to syndicate to the same categories in the pre-spoke (simply having the same name multiple times just confuses the pre-spoke and it won’t create the post). So, you are probably looking at pushing from the seed hub to the same category structure on the pre-spoke and then allowing users to duplicate that content to their own categories, editing it and then pushing it to their spoke(s).

    You could just do that in the seed hub though – have the content seeded to a generic set of categories and then let authors duplicate the posts to their own categories, edit and then push.

    Whether it’s seed hub or pre-spoke you’ll still need to look at either modifying the plugin to restrict site selection on a user basis, or fix the site based on the category and perhaps hook syndication into the publish process to that the push happens automatically.

  • I haven’t used that plugin but it looks interesting particularly as it appears to cover all the shortfalls of the API-based approach by supporting custom post types, attachments, etc.

    If you’re looking at a pure multisite model then it’s difficult to see what advantages the API approach would have.

    Definitely worth further investigation and a follow-up post, I think, so thanks for the heads-up!

  • Sam
    New Recruit

    Hi Chris,

    This is interesting for sure, and close to what we are trying to do but I still can’t seem to find a way of doing exactly what we are after – it would be great if you could tell me whether or not this is possible:

    We want to be able to post all our content from one main site (the root domain) and for it appear on this main site, however, we also want to be able to select mini-sites for it to appear on (potentially 2 or 3 different ones) – but we don’t want each post to be published/republished 3 or 4 different times. We want just 1 post, but it is linked to/viewable from multiple different places.

    Let me give you an example in case my explanation isn’t very clear.

    Let’s say my main domain is soccer.com and we produce news stories about various different players/events/games etc. We produce a number of different mini sites – one about a specific player (let’s say David Beckham), one about a specific event (let’s say the World Cup), and one about a specific league (let’s say the MLS).

    We write a post about a spectacular goal David Beckham scores, the URL is soccer.com/david-beckham-goal

    We want this post to then appear on the root domain at soccer.com and come up in the latest posts feed etc, we also want it to appear on the mini site homepage for the World Cup because it was in the world cup, and we also want it to appear on the MLS mini site because that was the league he was playing in at a time.

    We want each mini site to essentially display the thumbnail/snippet and for it to be indexed there (and appear in the latest post feeds/categories there), but if anyone clicks on that link on any of the mini sites, it takes them to the same url – soccer.com/david-beckham-goal.

    Sorry for the long winded explanation – but I hope that is clear – is this something that is possible? And if so, how can we go about implementing?

    Thanks so much for all your help!

  • Sam,

    You could still use the push syndication as is and just change the spokes’ (mini-sites’) theme to only show the excerpt and to make “post titles” and “read more” links point to the hub (main).

    In fact, you could probably just do it by hooking into a few filters (the_content, the_excerpt, the_permalink) and not have to change the theme at all beyond the functions.php file.

    • Sam
      New Recruit

      Excellent! If we’re still using push syndication though, will this mean there will still be a duplicate of the post somewhere even if we aren’t linking to it from anywhere?

      And secondly, my coding/programming knowledge is nearly non-existent, is this something WPMU can help me get set up (I’m a paying member) or will I need to hire someone?

      Thanks for the reply Chris!

      • Yes, the post will be duplicated.

        If you put this in your theme’s functions.php file then it will override any call to display the full content and on the post pages will add a link back to the hub:

        {code}
        function override_the_content( $content ) {

        global $post;

        $hubdomain = ‘http://yourhubdomain.com’;

        if ( $post->post_excerpt ) {
        $content = $post->post_excerpt;
        } else {
        $content = wp_trim_words ( $post->post_content , 55 );
        }

        if ( is_single() ) {
        $new_permalink = str_replace( get_bloginfo(‘url’) , $hubdomain , get_permalink( get_the_ID() ));

        $content .= ‘

        Read more about this post

        ‘;
        }

        return $content;

        }

        add_filter( ‘the_content’ , ‘override_the_content’, 1 );
        {/code}

        Don’t forget to change $hubdomain to the domain name of your hub and keep the permalink structures between the hubs and spokes the same.

  • New Recruit

    Chris,
    I found this post because I’m looking for a solution for an association site we manage.

    Here’s the scenario for how we would use it.
    We have the association site where the original posts would be published and then pushed out to member companies that opted for the blogging service.

    I’m curious though with all the changes with Google will publishing content in this way be bad in terms of duplicate content?

    Is there anything built in the gives the original author site or domain the credit? Canonical links, Open Graph – publisher reference, etc.

    Obviously we don’t want to hurt the member sites if it is viewed as spam.

    Thanks!

  • New Recruit

    Hi Chris

    Great article! It is helping me do a lot of what I want to, with much less effort. Thanks a bunch!

    Background – I am not a techie but manage to copy paste and apply a little bit here and there using online help.

    I tested the hub and spoke with a couple of spokes, and it works fine when I Save Draft + Publish. But am not able to schedule the posts. While writing the post in hub, if I schedule for, say, the next day, it gets scheduled for the hub but it is visible immediately on the spoke sites. Basically, i want to line up a few posts for different times of the week to show up later on all spokes simultaneously.

    Is this something that can be overcome?

    Best

    • It looks like the plugin will syndicate on any change of post status, so draft to future (scheduled) will kick it off.

      To stop this happening, you probably need to add a check to the syndicate_content function such as:

      if ( get_post_status( $post_ID ) == ‘future’ ) return;

      immediately after the following statement:

      $post_ID = $sites[‘post_ID’];

      I haven’t tested this though, so no guarantees!

  • New Recruit

    This would be the answer to all my prayers, but after hours of trying, I cannot seem to get That One Part right. Namely creating sites. I don’t see such option as “Sites option in the Admin Menu”, and I do get an “invalid taxonomy” error if I try to add a taxonomy from the new post -screen. I would create custom taxonomies, but there are no instructions on how to set them up so I’m a bit lost at this stage.

    I am trying to install this on WP multisite it that makes a difference, so there is that “My Sites” location in the admin bar, but nothing to do with site groups.

    Also, where do you get the Push Syndication key from to add to the Config.php, please?

    This would be so good if I could get it to work – would solve all my problems but… I’m lost. :(

Comments are closed.