DiggingIntoWordPress

by Chris Coyier & Jeff Starr

Add Private Content to Posts via Shortcode

Posted by on

Recently, WPRecipes posted an incredibly useful technique that uses a shortcode to add private content to blog posts. This functionality makes it easy to manage leftover data, miscellaneous notes and other communication by keeping everything together with its corresponding post. Consolidating information like this helps to streamline flow and organization into the future.

Combine the power and elegance of shortcodes with the convenience of private post content

For those unfamiliar with shortcodes, they are basically short strings of bracketed text used in post content to run functions and output content. Since WordPress 2.5, WordPress’ Shortcode API provides a set of functions for creating macro codes. Here are some hypothetical examples:

  • [homepage] – displays your blog’s home URL
  • [navigation] – displays a list of links to your categories
  • [copyright] – displays your copyright information

For shortcodes to work, you just add a custom function to your theme’s functions.php file. Once that’s in place, you simply type the shortcode text-snippet anywhere in your post content. When such posts are viewed on your blog, the shortcode will run its function and output content, filter posts, or whatever else you’ve rigged it to do. Shortcodes can really simplify and speed up content creation.

You can create shortcodes for just about anything, including custom permalinks, calling widgets, Google Maps, and even custom queries. In this post, we’re combining the power and elegance of shortcodes with the convenience of private post content. And the best part is that it’s so easy..

Step 1: Add some code to your functions.php file

Slap the following code into your active theme’s functions.php file:

// add private content via shortcode
function private_content($atts, $content = null) {
	if (current_user_can('create_users'))
		return '<div class="private-content">' . $content . '</div>';
	return '';
}
add_shortcode('private', 'private_content');

What we’re doing here is creating a function that will recognize a shortcode named “[private]” and only display its contents if the user is logged in as an Administrator. For everyone else, the private content remains just that – completely private.

Step 2: Be a private-content shortcode ninja

Once you have the custom function in place, you are ready to add some private content to any of your posts. Here is an example of how to use the shortcode:

[private]
Note to self: this post contains some private content!
[/private]

Then, when the user is logged in as Admin, this private content will be displayed wrapped with the following markup:

<div class="private-content">
Note to self: this post contains some private content!
</div>

By using the “private-content” class, you can style your private content with a little CSS to make it all sweet ;)

Now in plugin flavor!

Since posting the article, we have seen two different plugins for this “private-content shortcode” functionality. After reading this post, Aldo Latino whipped up UBN Private Content, which takes it to the next level by using shortcode attributes to enable private content for any user-permission level (i.e., not just Admin). Download here!

There is also the The Esconder Shortcode Plugin is in Portuguese, and enables private content that is viewable by any logged-in users (i.e., not just Admin). See the linked post for download.

As Barry points out in the comments, using a plugin for private post content is a better idea if you ever plan on switching themes. Plugins work across themes, so your private content will always stay private. Conversely, when implemented via your local theme’s functions.php file, the shortcode function will keep your content private only for the current theme.

28 Responses

  1. Leaf. May 5, 2010

    Hi. Thanks for the write up.

    I want to ask what the best method to insert custom content, but outside of the content (in the template files). Can you declare some variables in your functions file, and then call these it in your templates (outside of the content). If so, do you have any links you can point to demonstrate.

    • I think custom fields might help you with that. Check out these tutorials for more information.

      • Leaf. May 5, 2010

        Thanks Jeff. But I’m not wanting to do it for post-level content, but for site-level info.

        I’m basically wanting to set just a few site-specific options (much like the bloginfo Admin > Settings > General) which can be set and called in (like bloginfo(‘name’) etc are).

        I just don’t know how this is achieved in WordPress? I figured you could define them in functions.php, but despite much Googling, I can’t find the answers.

        Even if I could call the timezone setting in Admin > Settings > General, that’s one of the site-options I’m using (I need to call the city set here). But I don’t think you can.

        If anyone can point me to where I need to be looking, I’ll love you for ever.

  2. Hi,
    Its a deep code. Please make a plugin so I can install it and configure it.
    Thanks

    • Looks like we now have at least a couple of plugins for this.. There’s one mentioned further in the comments, and then somebody else just sent one via email. I will update the post with links to both here in a bit.

  3. What a great bit of cheeky code! great stuff!

    As to the comment about a plugin – that really would be overkill, its only a bit of code in functions.php.

  4. Barry May 5, 2010

    Until, of course you change your theme, and then all your private information becomes visible to all. Put it in a plugin and you won’t have this problem.

  5. I guess the [note] shortcode in the example above should really read [private]

  6. Matthew Muro May 5, 2010

    One thing to note is that by using current_user_can('publish_posts'), it is not limited to only Administrators. ‘publish_posts’ is a capability for Administrators, Editors, and Authors. If you truly wanted the private content limited to only Administrators, you would need to choose one of the capabilities limited to that role such as current_user_can('create_users').

    With a site where you are the only author, this probably doesn’t make a difference, but in multiple author sites it makes all the difference who is allowed to see private content.

    • Yes, good call – I have updated the function with the ‘create_users’ criteria. I think it’s a definite improvement. Thanks!

  7. I had the same idea some days back, and I also made a plugin for it. :)

    http://dicaswp.com/2010/04/23/esconder-texto-para-leitores-nao-registados/

  8. mikemick May 5, 2010

    An improvement…

    I just did something similar to this a few weeks back, but ran into a little issue. Instead of returning $content, you should return do_shortcode($content). That way, you can use shortcodes in the content that you are making private, and they will work. Otherwise, the shortcodes won’t process properly.

  9. To all: There are now a couple of different plugins available for private-post-content shortcode functionality. See the added section at the end of the article for details. Thanks!

  10. Hey Jeff, it’s not Spanish, but Portuguese! ;)

  11. Jean-Baptiste Jung May 9, 2010

    Thanks for the mention, Jeff!

  12. Random tip: If “private” you are looking for “password protected”, you can always password protect posts and pages right from the admin before publishing. And if you wanted to password protect additional content from the template files themselves, anything you put between a set of tags like this will also be password protected.

    <?php if ( !post_password_required() ) { ?>
    <p>I'm protected</p>
    <?php } ?>

  13. just curious as to what kind of private info you’d want to post along with your posts, instead of keeping it in a seperate more private file, as these might be accidentally revealed during upgrades or swapping themes.

    just curious

    • Valid question, and briefly explained in the first paragraph. Just helps to keep all of your notes and everything in one spot. I tend to write extremely extensive/exhaustive articles that require much research, notes, and snippets. Not all of them are used/presented in the article, but I keep things together for future reference purposes. Granted, the typical blogger probably has fewer reasons to implement this functionality.

      Accidental exposure is another valid point, and is addressed in the last paragraph.

  14. Warez sites are a good example for this, they can hide the URL’s for the non-registered user.

  15. Panos June 3, 2010

    Amazing article!
    I’m a totally new in php and I’d like to create a shortcode to show the post ID inside some of my posts. The php code is simple and I need to create a shortcode like [post_id] . Can you help me with the code for the functions.php???? Thank you all in advance!!

    • Panos June 3, 2010

      I found tha the php for the id is simple,

  16. Jeff,
    I found your site yesterday and I love it. I started a blog that turned into a community newspaper and is now growing like crazy. It is on the Swift theme.
    We are bringing new writers on board. Each writer has their own seperate blog under the paper’s name. This way we can run seperate ads for everybody.
    What we are trying to do is make it so that when a writer makes a new post, it will update automatically on the James River Journal’s home page. We would also like to display the last five comments next to the writer on the home page.
    This is how we do it for the feature stories up top. Swift posts it automatically and then over to the right, the comments show.
    Any ideas how to do this linking to the seperate blog? Thank you so much.

  17. Jeff,
    wonderful post.
    I have tried your example and it works great.

    Then I wanted to go a bit further and try to display content from a custom field using the shortcodes.

    My idea was this:
    // add custom fields code
    function customtext_content($atts, $content = null) {
         $key="mycustomkey";
         $outputtext = get_post_meta($post->ID, $key, true);
         return ($outputtext);
    }
    add_shortcode('customtext', 'customtext_content');

    In the post the shortcode [customtext] was supposed to look up the value of the custom field labled “mycustomkey” and put that text into the posts content.

    However, the variable $outputtext is not getting the value from the get_post_meta function. Does anyone know what I am doing wrong? When I am using the get_post_meta function in my single.php it works just fine but not in combination with the shortcodes.

    Thanks for reading this :)

    • Just figured out the solution to the question above. In case someone else wants to do the same, you need to add:

      global $wp_query;
      $postID = $wp_query->post->ID;

      to get the post ID (obviously)

      Working example:

      // add custom fields code
      function customtext_content($atts, $content = null) {
           $key="mycustomkey";
           global $wp_query;
           $postID = $wp_query->post->ID;
           $outputtext = get_post_meta($postID, $key, true);
           return ($outputtext);
      }
      add_shortcode('customtext', 'customtext_content');

Comments are closed. Contact us with any critical information. Thank you!

Code is poetry