Tutorial Details
- Technology: WordPress
- Difficulty: Beginner - Intermediate
- Estimated Completion Time: 30 Minutes
Many popular blogs these days are authored by multiple contributors. Today, we’ll create a simple WordPress plugin that will allow us to add the post author’s biography to the conclusion of each post, much like you see on Nettuts.

1. Have a Bio Ready
If you don’t already display authors’ biographical info, then the you can add and edit biographical info by heading to the users pane from within the WordPress dashboard, selecting a user, and filling in a quick bio. We’re also going to be adding a gravatar for the author, so ensure that you also set an email address.

2. Create the Necessary Files
We’ll need to create a single file that contains the functionality of our plugin. Fire up your FTP of choice, and, within the wp-content/plugins/ folder, create a file called ntauthorbio.php. In order for WordPress to recognize our plugin, we need to create a quick header comment in our file, much like you do at the top of style.css. Paste the following code into your file, and, of course, make adjustments accordingly.
/* Plugin Name: Nettuts Author Bio Plugin URI: http://www.nettuts.com/ Description: This plugin adds an authors bio to his/her post Author: nettuts Version: 0.1 Author URI: http://www.nettuts.com/ */
3. Functions & Actions
Next, we’ll create the base for our plugin. Paste the following after the opening comment header.
function author_bio_display($content)
{
// this is where we'll display the bio
}
function author_bio_style()
{
// this is where we'll style our box
}
function author_bio_settings()
{
// this is where we'll display our admin options
}
function author_bio_admin_menu()
{
// this is where we add our plugin to the admin menu
}
add_action('the_content', 'author_bio_display');
add_action('admin_menu', 'author_bio_admin_menu');
add_action('wp_head', 'author_bio_style');
“Hooks are provided by WordPress to allow your plugin to ‘hook into’ the rest of WordPress; that is, to call functions in your plugin at specific times, and thereby set your plugin in motion.”
Above we’ve created four functions that our plugin will require to work properly. Each function has a specific purpose (as commented above), and also, each is tied to a specific action (apart from author_bio_settings, which will be called from another function.
When developing plugins, it’s important to understand what a ‘hook’ is. A hook is a place in the running cycle where we can hook into WordPress, and call our functions. For example the hook used above, for author_bio_display, is the_content; this means that when WordPress uses the_content (used for displaying a post/page’s main content), it will first call the function we’ve given it.
- the_content – the content of the page/post is displayed
- admin_menu – called when the sidebar in the admin dashboard is created
- wp_head – lets us add code to the head tags of the page. This is why you include wp_head() when designing your themes.
4. The Display Function
The most important function in our plugin is the display function, which will handle the process of actually displaying the information after the content. Before we start, it’s important to note that this function accepts a parameter, called $content. This means that the content of the page/post is passed to our function, so we can then append our author bio.
Let’s start with a simple if/else statement.
function author_bio_display($content)
{
// this is where we will display the bio
if ( is_single() || is_page() )
{
$bio_box = // placeholder;
return $content . $bio_box;
} else {
return $content;
}
}
Above, we check to see if the content is being displayed on a single post using is_single(), or a page using is_page(). If either returns true, we can post our box which will be placed in the $bio_box variable. Otherwise, if we’re on some different page, such as the archives or front page, we should simply return the content untouched.
Now we need to add our code for the box to appear, change your $bio_box to match the following code.
$bio_box =
'<div id="author-bio-box">
'.get_avatar( get_the_author_meta('user_email'), '80' ).'
<span class="author-name">'.get_the_author_meta('display_name').'</span>
<p>'.get_the_author_meta('description').'</p>
<div class="spacer"></div>
</div>';
The styling, of course, can be changed later to fit your own tastes, but for now, we’ll use a simple box, and will add some CSS to style it shortly.
We’re using a few functions above to retrieve our required data. get_avatar() is a built-in function in WordPress that will return a user’s gravatar, if they have one, according to their email. We pass the get_avatar() function two parameters; the author’s email, and a size for the image (80px*80px in our case).
The function get_the_author_metacan retrieve any piece of information about a registered WordPress user. A full list of the items you can return can be found on WordPress Codex.
If we now run our plugin, we should see something that resembles this:

It’s not the prettiest looking biography, but we now have the basic functionality we’re after. If you’re still having problems, ensure that the author of the post/page has a biography and/or gravatar, and also ensure that the plugin has been activated in the plugins section of the dashboard. Let’s next style things a bit.
5. Making it Pretty
If you’re a designer, here’s your chance to do as you please! My code below is just enough to make our box look clean and simple. To provide an example of how wp_head() can be used, we’ll insert the CSS for this box into the head tag of our document. However, you can also simply place this within your stylesheet.
This author_bio_style() function needs to return a simple block of CSS.
function author_bio_style()
{
// this is where we'll style our box
echo
'<style type='text/css'>
#author-bio-box {
border: 1px solid #bbb;
background: #eee;
padding: 5px;
}
#author-bio-box img {
float: left;
margin-right: 10px;
}
#author-bio-box .author-name {
font-weight: bold;
margin: 0px;
font-size: 14px;
}
#author-bio-box p {
font-size: 10px;
line-height: 14px;
font-style: italic;
}
.spacer { display: block; clear: both; }
</style>';
}
The above code doesn’t require much explanation; CSS is beyond the scope of this tutorial. Generally, we’re just creating a box with a border, and floating the image left. Finally, we add a spacer to make sure the box is big enough to fit the image and text in. You could also use the clearfix hack, or even overflow:hidden to achieve this effect. Ultimately, that will depend on your specific layout.
Your new fangled box should look similar to mine now; see below.

6. Making a Settings Page
Before we wrap up, let’s take a look at adding a settings page in the dashboard for our plugin. Most plugins rely on some sort of settings section to provide a bit more flexibility without the user having to edit any code.
There are numerous options we could add; such as, where the box appears (top or bottom), the colors used, exclude certain users, and so on. For this tutorial, I’ve chosen to specify if the plugin can appear on only pages, only posts, or both. Hopefully this will be enough to show you the ropes. At that point, you can extend the functionality how you see fit.
Making the Page
We need to setup a page in the admin dashboard. To do so, we need to tell WordPress what to do when the admin_menu action triggers. To compensate, we’ll edit our author_bio_admin_menu() function to look like the code below:
function author_bio_admin_menu()
{
// this is where we add our plugin to the admin menu
add_options_page('Author Bio', 'Author Bio', 9, basename(__FILE__), 'author_bio_settings');
}
The above code creates an options page in the dashboard, and passes the following parameters:
- Menu Name – Author Bio
- Page Title – Author Bio
- Access Privilege – 9 – or, only Administrator access
- Handle
- The required function – author_bio_settings()
We next need to provide the page some content. Since we called author_bio_settings() when creating the page, that’s the function we’ll be using to display our options form and update the database.
The Settings Function
Simply put, this function needs to display a form with the options. It also needs to check whether the form has been submitted, and, if so, store the new values in the database. First, let’s concentrate on creating the form.
function author_bio_settings()
{
// this is where we'll display our admin options
$options['page'] = get_option('bio_on_page');
$options['post'] = get_option('bio_on_post');
echo '
<div class="wrap">
'.$message.'
<div id="icon-options-general" class="icon32"><br /></div>
<h2>Author Bio Settings</h2>
<form method="post" action="">
<input type="hidden" name="action" value="update" />
<h3>When to Display Author Bio</h3>
<input name="show_pages" type="checkbox" id="show_pages" '.$options['page'].' /> Pages<br />
<input name="show_posts" type="checkbox" id="show_posts" '.$options['post'].' /> Posts<br />
<br />
<input type="submit" class="button-primary" value="Save Changes" />
</form>
</div>';
}
We start by grabbing some options from the database. Of course, we don’t currently have a method for setting them yet, so they’ll be blank for now. Next, we display the form, which is already styled by WordPress’ dashboard CSS. You’ll notice we’re displaying a (currently unset) variable called $message; this is so we can notify the user when we update the settings if it was successful.
We print our options at the end of the checkbox code. If the user turns an option on, we need to store it in the database as ‘checked’ in order to check the checkbox. The functions we use to get and set options are get_option() and update_option() respectively. The get function requires the name of the option (so it’s important to be unique), and the update option needs the name of the option and the new value. If the update function doesn’t find the option, it simply creates a new one.
So far your page should look like do:

Now, let’s add our code to take the values sent by the form, and update the options in the database. The form contains a hidden value, called action, which is set to ‘update.’ We’ll check if that value is set, and if so, we update our options. This code should be placed at the top of our autor_bio_settings() function.
if ($_POST['action'] == 'update')
{
$_POST['show_pages'] == 'on' ? update_option('bio_on_page', 'checked') : update_option('bio_on_page', '');
$_POST['show_posts'] == 'on' ? update_option('bio_on_post', 'checked') : update_option('bio_on_post', '');
$message = '<div id="message" class="updated fade"><p><strong>Options Saved</strong></p></div>';
}
If the form has been submitted, we use the ternary operator (if you’re unsure of how these work, look them up – they’re a simple form of if/else) to check whether the checkboxes are checked or not. If they are, then we set the option as ‘checked;’ otherwise we set it as blank. Finally, we set the message displayed to a successful dialog, already styled by WordPress.
Changing the Output
Now, we should be able to set options and see them change in our options page; however, the functionality of our plugin will not alter yet as we’ve not told it to do so. So the final step in our project is to make the display function react to these options. In our author_bio_display() function, prepend the following code to the top, in order to get the options previously set.
$options['page'] = get_option('bio_on_page');
$options['post'] = get_option('bio_on_post');
Now that we have these values, we only need to execute the display code if the option is set. To do so, we change our if statement accordingly.
if ( (is_single() && $options['post']) || (is_page() && $options['page']) )
Here we have implemented two conditions that, if met, will cause our box to display. Not too hard, right? Here’s our full plugin:
<?php
/*
Plugin Name: Nettuts Author Bio
Plugin URI: http://www.nettuts.com/
Description: This plugin adds an authors bio to his/her post
Author: nettuts
Version: 0.1
Author URI: http://www.nettuts.com/
*/
function author_bio_display($content)
{
// this is where we will display the bio
$options["page"] = get_option("bio_on_page");
$options["post"] = get_option("bio_on_post");
if ( (is_single() && $options["post"]) || (is_page() && $options["page"]) )
{
$bio_box =
"<div id="author-bio-box">
".get_avatar( get_the_author_meta("user_email"), "80" )."
<span class="author-name">".get_the_author_meta("display_name")."</span>
<p>".get_the_author_meta("description")."</p>
<div class="spacer"></div>
</div>";
return $content . $bio_box;
} else {
return $content;
}
}
function author_bio_style()
{
// this is where we will style our box
echo
"<style type="text/css">
#author-bio-box {
border: 1px solid #bbb;
background: #eee;
padding: 5px;
}
#author-bio-box img {
float: left;
margin-right: 10px;
}
#author-bio-box .author-name {
font-weight: bold;
margin: 0px;
font-size: 14px;
}
#author-bio-box p {
font-size: 10px;
line-height: 14px;
font-style: italic;
}
.spacer { display: block; clear: both; }
</style>";
}
function author_bio_settings()
{
// this is where we will display our admin options
if ($_POST["action"] == "update")
{
$_POST["show_pages"] == "on" ? update_option("bio_on_page", "checked") : update_option("bio_on_page", "");
$_POST["show_posts"] == "on" ? update_option("bio_on_post", "checked") : update_option("bio_on_post", "");
$message = "<div id="message" class="updated fade"><p><strong>Options Saved</strong></p></div>";
}
$options["page"] = get_option("bio_on_page");
$options["post"] = get_option("bio_on_post");
echo "
<div class="wrap">
".$message."
<div id="icon-options-general" class="icon32"><br /></div>
<h2>Author Bio Settings</h2>
<form method="post" action="">
<input type="hidden" name="action" value="update" />
<h3>When to Display Author Bio</h3>
<input name="show_pages" type="checkbox" id="show_pages" ".$options["page"]." /> Pages<br />
<input name="show_posts" type="checkbox" id="show_posts" ".$options["post"]." /> Posts<br />
<br />
<input type="submit" class="button-primary" value="Save Changes" />
</form>
</div>";
}
function author_bio_admin_menu()
{
// this is where we add our plugin to the admin menu
add_options_page("Author Bio", "Author Bio", 9, basename(__FILE__), "author_bio_settings");
}
add_action("the_content", "author_bio_display");
add_action("admin_menu", "author_bio_admin_menu");
add_action("wp_head", "author_bio_style");
?>
Voila
Hopefully if everything went according to plan, you should now have a working authors’ biography box after your posts/pages. Further, you now have a custom settings page in your WordPress dashboard, that you’re free to extend how you see fit.
Thanks for reading my first post here on Nettuts. If you have any questions feel free to leave a comment below!




Bookmarked! Like to read wordpress tuts. I hope that will be more about creating wp plugins. Cheers!
It’s kind of ironic that Dan wrote a tutorial about displaying the authors bio when he hasn’t written one for himself on tutsplus
Nice tutorial BTW.
Keeping the CSS inside the plugin file isn’t a very good practice, is it?
Well you could store it as a .css and then simply add a line of HTML in to the header to call the .css file, the focus of this tutorial was more just to learn the ropes of how plugins work however, but thanks for the idea
Agree, we should keep CSS file separately and use wp_enqueue_style to get it.
One more thing, we should use register_setting() function to keep all settings in one row in database. It’s not very good when we store them in 2 rows.
Also, using ’9′ to define access is a bad idea per WordPress:
“capability
The minimum capability required to display and use this menu page. Whilst for legacy reasons, you may also use user level – the usage of user level is discouraged for future compatibility and has been deprecated since WordPress 1.5. “
Good call Jason, the use of user level is deprecated now. Thanks for the heads up
Your welcome! Thanks for taking the time to write the tut!
Thanks for the extra bit of info.
What would an example of good practice be for defining access for add_options_page? Thanks.
Hey theone, you can read more about the newer capabilities feature of WordPress that has replaced user levels here http://codex.wordpress.org/Roles_and_Capabilities
Thank you
More WordPress related tuts please
Excellent plugin. Although I agree that with a plugin like this, you need to create a separate stylesheet and add it through wp_enqueue_style function.
This will make things easier for users who are trying to optimize the site load time. They will simply disable your style filter and add the styling in their main css file.
Good job on the tutorial.
Nice work! I especially like the part dedicated to the admin page – which is something that plugin consumers will more likely than not need to use!
Thanks.
Love the tutorial. Good work Dan, keep it up! More please
OMG this is an awesome tutorial, keep them coming!
Great Tut, I was looking for this for a long time…really helpful..
Thanks for the tutorial, this is a good way to start leaning the ins and outs of wodpress development. Does anyone know any decent books on this matter?
Thanks
Great post Dan! Great information and great tutorial
Nice tutorial. Thank you so much.
Thanks so much! This is a great feature and very customizable. Thanks again!
Thanks for the write up, this a very thorough look into the building of a bio-centric wordpress plugin.
It’s ironic that the author of this post has yet to update his bio
Nice article. I have yet to write a WordPress plugin but this looks way easier than I anticipated.
Haha thanks, yeah I tried to update but unfortunately this is my first post so I haven’t sorted out an account yet
It’s not easy to find a clear and easy to understand tutorial on how to build a plugin, but this one is exactly that! thanks, Dan.
Nice tutorial, will come in useful. Bookmarked!
Very useful tutorial I think it covers the whole thing completely !
Good Job
Something is going on with that list in the article. Which is causing the last list item to be formatted weirdly and the bullet element to be applied to every line of code in subsequent code snippets.
Ahh yes, thanks Ian. Just notified the list wasn’t closed properly, should be rectified shortly! Apart from that, hope you enjoyed the tutorial
great tutorial thanks lot
Thank you, thank you, thank you! I was looking for something like this today! Appreciate it, Dan!
I don’t know where I’d be without you guys. Always amazing tutorials! I’m a sucker for clean code!
Maybe it’s just me but wouldn’t it be more useful for nettuts if their author section showed the author bio and only had a rollover if the bio is too long, instead of explaining the behavior of how to find the bio.
I agree
The Beggining Of Something New For Me. Thanks =)
Follow me @dmanzur Twitter
Im from Argentina.
This is what I’m waiting for..
Nice tutorial, thanks!
Why a plugin if you could add this easily to the functions.php. Less plugins is better.
The idea was to concentrate less on the functionality of the plugin, more on actually how a plugin is created so people can use their own ideas to create anything they want
Thanks a lots for great tutorials.
Even am searching for something like this.
Once again thanks
Oh!!! I can’t get it work in my theme
Do I need to edit single.php file in my theme? If so… what do I need to add?
And I can’t find “author bio settings” widget anywhere in my dashboard
The pluging is activated.
I found it
But Avatar isn’t working
Where did you find it? I’ts not working for me….
Hey Dasani, I don’t mean to sound patronising, but are you sure you have a gravatar associated with your email address?
Ok my bad, I did not add the file to the plugins folder… Works great now.
How can I get the bio to appear below the other meta info? It is above the category and tags now….
Can I have the name of the author link to the author’s profile page?
is not working since it is not inside the loop….
Hi, just wondering if you could call the author bio using tags in certain post, rather than it being in every post?
Thanks
I think you forgot the backslashes “” i think there needed when using tags on HTML elements in PHP.
I’m not sure why it was posted that way, the echo statement should use single apostrophes rather than double in order to function correctly, I’ll have a word with the editor, thanks for noticing
No problem, Thank you for a great tutorial.
That was one of the most straightforward WordPress plugin tuts I’ve ever read, even if it only added minor feature…
Thanks Matt, I tried to pick an easy feature as a complex one would detract from the actual writing of the plugin itself and concentrate too much on what the plugin was trying to achieve!
I hope this kind of tuts will always shared.Really appreciate it and I will implement it to my WP blogs
Hello.
Well… I have gravatar associated with my email address, but it isn’t coming up. Does anyone have the same problem?
Is it possible, that the theme doesn’t support gravatar? I can’t find any other reasons
I see a gravatar of a cat, i just signed up to Gravatar (explains my rubbish avatar) and my’n is showing.
Awesome, just what I needed, cheers!
Could you call the author bio using tags in certain post, rather than it being in every post?
Thanks.
You certainly could, if you used a custom field on the post called something like “show_bio”, you could use a similar method as above to check whether it’s true or false then if it’s true dump the code to show the bio and if not don’t!
I’ve seen in the comments on some other tutorial something like “nettuts reads my mind!” and I just wanted to confirm it.
Very useful and good explained tutorial on topic that as a new WordPress user I was struggling with
Thanks!
Why you don’t use the new WordPress plugin class ?
I think it’s so prettier and easier than just some functions.
Thank you for the tut, can you guys help if possible.
I have this site with different templates in different categories and I will like to know how to remove the author info depending the category
Hey Angel, glad you enjoyed! Similar to some of the methods we use above, what would be best is where the code is displaying the authors bio, wrap a conditional round that such as if ( category == ‘example’) then show the bio!
Thanks for the article. The plugin writing is like a myth to me. But after reading the article i have got more clearer about it. The best thing about the article is that it is very clearly explained.
One thing i would like to ask is that how can we make the styles dynamic . I mean we should ask the user about things like color and font and then display them?
That’s a personal preference I believe, I think it looks better when all authors bios are of the same style/design but with a different avatar – it’s good for consistency which is important to any design.
i like it. look easy to do. thank.
Simplesmente perfeito,
Eu coloquei em um site em faço atualizações
http://internacionalizasc.com.br/?p=670
Obrigado
Thanks for this interesting article !
Would you have an idea about how adding a Twitter address in the biography ? Thx in advance !
Question:
When someone uses:
$x = apply_filters('the_content', 'some content here');
echo $x;
Your Author Bio will end up applied to $x and if $x is echoed out in the middle of some page… you Author Bio would be in the middle of some page… correct?
Is there a better way to do this, other than your example of add_action(‘the_content’, ‘your_function’) or is apply_filters(‘the_content’, ‘some content here’) not something people should be using inside there WordPress templates… ? (which seems pretty much the norm, at least upon Google-ing it)
Great post i will try it on my blog, i HAVE A QUESTION can you tell me the name of the plugin that your are using for the “Related post” section. This section is a great way to increase the page view number
my email befashionlike@gmail.com best
ps : sorry for my bad english i’m french
Thank you for your tutorials, it’s really helpful for me to understand more about WordPress plugins. Again, thanks. I know when this plugin is actived , the author bio will be placed automatically in the entry but I have a question, can you tell me how can I set a desire position in entry to show author bio ? I mean can I use a given function to add into file single.php like other plugins.
P/S: I not good at English, I am Vietnamese. Thanks !
Thanks for this interesting article !
Would you have an idea about how adding a Twitter address in the biography ? Thx in advance !
Once simple, yet very effective. Thanks for the article I was actually looking for a nice plugin like this.
I was looking this code for my blog.
thanking for your enough statements.
Great! Clearly describe.
Thanks so much.
I really like your writing style, and I’m hoping for more posts like this one.
Great info…i was wondering how to add author info….it has surely helped me a lot….thanks for sharing
Thanks for the tutorial, this is a good way to start leaning the ins and outs of wodpress development. Does anyone know any decent books on this matter?
Thanks
nice walk through .. love it
This is helpful! Thanks for sharing. It works great.
One lesson finished! Got more from this blog to do. Please, post more lessons for wordpress. It´s really awesome!!!
Great tut! This came in handy, i’m using it on a project now … thanks!
Great. This totally took me from ‘never wrote a wordpress plugin’ to ‘ive done some wordpress plugin work’
Thanks!
Good post, I am building this function into my wordpress blog as we speak. Thanks!
Thanks for this tutorial. It’s a quite simple approach to write WP plugins.
Thank you!
Awesome Plugin… A million thanks for this…
I’m currently using it in my blog Coding Whiz
Nice bro… i tried already…. heheheheh…. great plugin…
this is what i need!
Nice tuts..! Thx!
How would you specify the author presentation for a few categories?
Would the following work?
if ( (is_single() && $options['post'] && ‘cat=21,23,1874,1668,1860,1909,-22′) )
where I want to include some categories and exclude others?
Can’t read up a bit,
HELP! I get the following error:
Parse error: syntax error, unexpected T_STRING in /var/www/atheistforums.org/public/blog/wp-content/plugins/userbio/ntauthorbio.php on line 21
Any advice?
WordPress is very flexible CMS, i love it.
HELP! I get the following error:
Parse error: syntax error, unexpected T_STRING in /var/www/atheistforums.org/public/blog/wp-content/plugins/userbio/ntauthorbio.php on line 21
Any advice?