Using WordPress natively for single source publishing and conditional content
In this series, I'm exploring ways to author in DITA and publish with WordPress. In previous posts, some commenters wondered whether it would be possible to simply author everything in WordPress, rather than continually importing from DITA. In this post, I'll explore that model.
One of the strengths of authoring content directly in WordPress is quick turnaround (or velocity). When someone asks you to make a small update to your help content, such as adding a little note on one page, does it make sense to re-compile and republish all of your help content? No.
I have a friend who was authoring in DITA and using a tool to import the content into Drupal. Eventually he dropped Drupal because he found it extremely annoying to delete and recreate all his Drupal pages when he just wanted to make one small update.
If you're constantly making updates to your content, there is serious merit in authoring natively in WordPress. On the other hand, if you only make updates occasionally, it might not be that important of a consideration.
Single sourcing content with WordPress
Let's jump right into some of the biggest reasons for using DITA, and how you can achieve the same results in WordPress. One common technique in DITA (and tech writing in general) is to conditionalize content from a single source. If I'm creating 2 bicycle manuals, and a lot of the information is the same, I create one source of information and generate it into multiple outputs by applying conditions.
As an example, let's say we have a task that looks as follows:
To assemble your bike: 1. Put on the wheels. 2. Tighten the handlebars. 3. Attach the kickstand. 4. Insert the ergonomic grips.
Suppose for the Trek 7.1 model bike, step 4 doesn't apply because the 7.1 model doesn't ship with ergonomic grips. Those are only available in the 7.2 model.
In XML DITA authoring, we would add attributes to the item that allowed us to apply rules to process it differently:
To assemble your bike: Put on the wheels. Tighten the handlebars. Attach the kickstand. Insert the ergonomic grips.
Then you filter out that content with the product="trek_72"
in the output based on some processing rules. However, this all takes place in an external XML editor.
In WordPress, there's a plugin called ThreeWP Broadcast that allows you to broadcast the same post or page content to other sites in a linked way.
ThreeWP Broadcast works with Wordpress Multisite, which is a network of sites rather than a standalone site. You author all of your content into a WordPress Multisite base site, and then choose which sites you want to broadcast the information to.
I set up a quick demo of a WordPress multisite that contains a base site and two network sites. On my WordPress base site, I have a sample page here: https://idratherbewriting.com/wp/blog/test-123/. ThreeWP Broadcast provides a little Broadcast box in the lower-right corner of your posts and pages. To broadcast the page to other network sites, just select which sites you want to broadcast it to.
Because I selected sites 2 and 3, the post will automatically be duplicated/posted on sites 2 and 3, without my having to do anything:
- Base site: https://idratherbewriting.com/wp/blog/test-123/
- Site 2: https://idratherbewriting.com/wp/site2/test-123/
- Site 3: https://idratherbewriting.com/wp/site3/test-123/
The only thing different in the above content is that the path has site2
or site3
in the URL instead of blog
.
Note that broadcasting a site does not repeat the post through an iframe or other embedded technique. The post is actually duplicated as a separate entity on the other sites. If you update the base site post, the posts on the network sites that are linked to the base site post are updated. The update process rewrites the content on the child site posts.
Conditionalizing content with WordPress
Now let's take it a step further and add the content in our example. On my base site, I have the following:
To assemble your bike:
- Put on the wheels.
- Tighten the handlebars.
- Attach the kickstand.
[site id="3"]- Insert the ergonomic grips
[/site]
That last step is conditional. It should only appear on site 3, so I add the shortcode tags around it like I did.
In my theme's functions.php file (which appears in the wp-content/themes/
directory), I have the following shortcode function:
function site_content_fn( $atts, $content="" ) { $atts = shortcode_atts( array( 'id' => 1 ), $atts ); $ids = explode( ',', $atts['id'] ); $ids = array_map( 'trim', $ids ); if( in_array( get_current_blog_id(), $ids ) ) return $content; } add_shortcode( 'site', 'site_content_fn' );
When you view the page on site 2, step 4 doesn't appear.
When you view the page on site 3, you see that step 4 appears.
Is that cool or what!
(By the way, thanks to wpmudev for developing that shortcode for me. If you're working with WordPress multisites, wpmudev is a must-have resource.)
Admittedly, the shortcode in there is specific to WordPress. This means that if you decide you no longer want to publish in WordPress, but rather Alfresco or Sharepoint, you'll have a lot of square brackets in your code. However, it might not be so difficult to programmatically convert the content back to strict XML or some other format. It's essentially the tradeoff decision you have to make.
Adding variables
While we're on the topic of shortcodes, let me note a few more. Let's say you want to use variables. It's the same technique. Add this to your functions file for a variable of your product name:
function get_product_name() { return 'ACME 531.4; } add_shortcode( 'product', 'get_product_name' );
Now when you insert [product]
into your content, ACME 531.4
will appear instead.
To conditionalize a variable, add some if-then logic to it, like this:
function get_product_name() { if( get_current_blog_id() == 2 ) return 'ACME 531.4'; if( get_current_blog_id() == 3 ) return 'ACME Deluxe 6.0'; if( get_current_blog_id() == 1 ) return ''; } add_shortcode( 'product', 'get_product_name' );
The blog_id values refer to the auto-generated numerical values for your sites. You can find your network site IDs (the blog IDs) by going to your list of network sites (Network Admin > Sites).
Now on my base site page, I'll insert the following:
Thank you for buying [product].
On my base site, the following appears:
Thank you for buying.
(I just put product name in brackets to remind me that this content is conditionalized based on the site).
And on site 2, this appears:
Thank you for buying ACME 531.4.
And on site 3, this appears:
Thank you for buying ACME Deluxe 6.0.
One thing to keep in mind is that you must disable wpautop (WordPress auto paragraphs). Otherwise, each new line will register as a new paragraph. Add a plugin such as wpautop control. Once you disable wpautop, you'll need to use p
tags to tell WordPress when to start a new paragraph.
Links
To handle links on network site pages, you must purchase the ThreeWP Broadcast Premium pack ($100). After you upload and activate the premium plugin, go to your base site and browse to Broadcast > Premium Pack. After you select and activate LocalLinks, the links on your child pages will go to the right pages. (You know Local Links is activated because a new option appears on the Broadcast area for each page that says "Update local links.")
As an example, on my test page, I created another page called Product Warranty and broadcast it to the other sites. I then linked to the Product Warranty from my other page with this text:
This is a link to Product Warranty.
Now if you go to the test page on site 2 or the test page on site 3 and click the Product Warranty link, you'll notice that you go to the Product Warranty page on site 2 or 3 respectively rather than going to the Product Warranty page on the base site.
Menus
One thing that isn't configured is broadcasting menus. Presumably, if you're authoring with this model, you'll want to create a table of contents (menu) in your base site and push it to other network sites. Right now that functionality doesn't exist within the broadcast plugin, but you can contact the ThreeWP Broadcast plugin author and commission an enhancement to the existing functionality. The author is very responsive and open to enhancement projects.
(As a workaround, you can simply export your WordPress content by going to Tools > Export and import the WordPress XML file into your network sites. The menu items are exported as separate content items from your posts or pages. The page/post content won't overwrite the page/post content on your network sites because it already exists, so its import is canceled.)
Canonical content
One thing to consider in this WordPress single sourcing model is canonical content. When search engines see multiples instances of similar pages, they will look for the canonical one (the official one) and prioritize it over the others. Currently, I believe the post on the base site gets listed as the canonical post, but this could probably be altered.
The idea of single sourcing content into separate sites does raise questions about how the search engines will process that content. Do you drive customers to a specific site and provide links to the other sites? Do you minimize the number of sites and try to consolidate information through tabs?
The most common strategy would be to prioritize your latest version or flagship product and provide links in the sidebar to the related sites. At the very least, I would make the base site private so that users don't get confused at seeing the source content there, especially if it has conditional tags.
Tightly versus loosely coupling content
By now you'll be wondering whether you want to pepper your content with WordPress shortcodes in order to add conditions and variables to your content. As some previous commenters noted, there's a tradeoff between tightly coupling and loosely coupling your content with your platform.
Keeping your content platform agnostic makes sense from a theoretical point of view. Theoretically, by keeping it agnostic, you can push the same content anywhere, to any standards-compliant platform, and do anything with it — you just have to write an XSLT transform that will take your tags and transform them into the output you want.
Keeping your content agnostic is a neat idea, but it might fall short in the practical world. In reality, most online CMS platforms will require some special code in order to do special things with your content. You can try continually importing your content from DITA into WordPress, but the workflow is cumbersome. It's not how WordPress was designed to function. WordPress works better when your content stays in there natively.
Once you become familiar with shortcodes and WordPress publishing, you can start to do a lot more. For example, here's a shortcodes plugin that provides all kinds of ready-made shortcodes.
Conclusion
Whether you choose to author natively in WordPress depends on your requirements. If you have to push the same content into PDF, it's probably not the best solution. On the other hand, if you're just publishing in HTML onto one site, does it really make sense to author the content in an external DITA editor? The only advantage is that by authoring in DITA, you ensure that you can port your content to another DITA compatible platform. If you're happy with WordPress, you might want to get comfortable there.
Honestly, I doubt many content management platforms will ever allow you to conditionalize content, show variables, and do other tricks without including some code that is specific to the platform. WordPress' shortcodes aren't that invasive and can easily be converted into some other system code if you decide to move platforms.
Although I worked out a lot of the details for authoring directly in WordPress, right now it's not the model I'm pursuing due to the authentication reasons I listed in my previous post. If you use the model I described in this post, I would recommending creating a project to enhance the ThreeWP plugin to include WordPress menu items in the kind of content that can be broadcast. Also, if you use syntax highlighting, don't use the Crayon Syntax highlighter, since it doesn't seem compatible with ThreeWP's broadcast model.
Overall, what do you think? Does WordPress provide a compelling model to author natively online, or does authoring in an external editor persuade you more?
About Tom Johnson
I'm an API technical writer based in the Seattle area. On this blog, I write about topics related to technical writing and communication — such as software documentation, API documentation, AI, information architecture, content strategy, writing processes, plain language, tech comm careers, and more. Check out my API documentation course if you're looking for more info about documenting APIs. Or see my posts on AI and AI course section for more on the latest in AI and tech comm.
If you're a technical writer and want to keep on top of the latest trends in the tech comm, be sure to subscribe to email updates below. You can also learn more about me or contact me. Finally, note that the opinions I express on my blog are my own points of view, not that of my employer.