With each new version of WordPress, the argument whether or not it qualifies as a CMS gets a little quieter.
In the WordPress core we have widgets, custom fields, custom taxonomies, and with version 2.9, an expansion of get_post_type. Add a few plugins and all sorts of post-types and custom write panels become a reality.
All this functionality is great so long as you, the developer, implement it in a way that is tough to break. Because once in the hands of the client, anything goes.
Flexible Layout
Then there is the issue of layout. For clients, moving content from one column to the other can be a technical hurdle, particularly for dynamic sites which rearrange content frequently to satisfy advertisers, audience demands, and so on.
Default drag-and-drop widgets are a great part of our arsenal, but adding your own custom widgets can really make life simpler for both developer and client.
Example Custom Widgets
In the quest to give more control to end users, Pro Theme has been experimenting with more custom widgets. Check out the demo for themes like The Local and Elemental for examples.
Below are widgets we’ve started including with most themes, including Mimbo Pro:
- Google Adsense. In the control panel you enter your Adsense ID and the widgets display ads accordingly. Works in any of the standard block sizes.
- Community Tweets. Aggregates Twitter activity according to location latitude/longitude. Contains fields for Number of Tweets and Mile Radius.
- Latest Tweets. Contains fields for Username and Number of Tweets
- Post Author Details. Contains author avatar, date and comments feed.
- Upcoming Posts. Displays a list of future-dated posts.
- More from this Author. For single-post pages. Displays five headlines from the same author.
- More from this Category. For single-post pages. Displays five headlines from the same category.
- Print Preview. Uses javascript to render the page print-friendly and free of images.
- Share This. Lets you post the current page to Twitter, StumbleUpon, Digg, Delicious and Facebook.
- YouTube. Displays a featured video with fields for Embed Code and Description
- Map Your Location. A Google Maps widget with fields for Location, Zoom Amount and Type of Map View (Roadmap, Satellite or Terrain).
- Popular Posts. Displays five headlines of most-commented posts.
- Subscribe to Feed. Includes an RSS icon and feed link.
We’ve gotten tons of great feedback from users who rely on positioning Google Adsense blocks and want to adjust their content accordingly. In the case of The Local, the entire homepage is 90% widgetized, with four columns to configure. Not to mention writers in the hyperlocal space who write unique content, but also rely on aggregating from other sites and social media sources.
How Do Custom Widgets Work
At the simplest possible level, custom widgets are implemented by 1) creating a class, and 2) registering a new widget. Forget about functionality within the widget for a moment and look at the basic setup which you would paste inside functions.php:
class My_Widget extends WP_Widget {
function My_Widget() {
parent::WP_Widget(false, 'Our Test Widget');
}
function form($instance) {
// outputs the options form on admin
}
function update($new_instance, $old_instance) {
// processes widget options to be saved
return $new_instance;
}
function widget($args, $instance) {
// outputs the content of the widget
}
}
register_widget('My_Widget');
That’s it. We can now visit our widgets panel to confirm:

Adding editable functionality into our widget is another story. Using the “Popular Posts” widget as an example, my partner Ben Gillbanks will walk us through creating the rest.
Creating a “Popular Posts” Widget
Firstly we have to name the widget class. I prefix my functions and classes with bm_ (Binary Moon) as it means there will never be any clashes with other functions and plugins.
We can then name the widget in the constructor, which is the first function, and it should have the same name as the class. This will be called when the class is first created and it defines the name you see in the widget editor.
Next up, I create the last method which is a form function which defines what data can be editable within the widget. In this case, it’s simply the title of the widget to be displayed on the blog. The update method can often remain as it is, although you may want to do some data validation (make sure the data input is safe/ allowed).
Then finally, the widget method. This is where the widget itself is displayed. You’ll notice I am actually passing the arguments to another function that is elsewhere in the theme. The reason I do this is because I like to split the display out separately so that I can use the function directly in the theme without widgets as well.
Notice the $args parameter in the widget method. These args are actually the arguments you pass to the register sidebar method, before_widget, after_widget etc. You can read more about these and creating custom widgets on the WordPress Codex Widget API page.
Here is the final code:
<?php
class bm_widget_popularPosts extends WP_Widget {
function bm_widget_popularPosts() {
parent::WP_Widget(false, 'Popular Posts');
}
function widget($args, $instance) {
$args['title'] = $instance['title'];
bm_popularPosts($args);
}
function update($new_instance, $old_instance) {
return $new_instance;
}
function form($instance) {
$title = esc_attr($instance['title']);
?>
<p><label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:'); ?> <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" /></label></p>
<?php
}
}
function bm_popularPosts($args = array(), $displayComments = TRUE, $interval = '') {
global $wpdb;
$postCount = 5;
$request = 'SELECT *
FROM ' . $wpdb->posts . '
WHERE ';
if ($interval != '') {
$request .= 'post_date>DATE_SUB(NOW(), ' . $interval . ') ';
}
$request .= 'post_status="publish"
AND comment_count > 0
ORDER BY comment_count DESC LIMIT 0, ' . $postCount;
$posts = $wpdb->get_results($request);
if (count($posts) >= 1) {
if (!isset($args['title']) {
$args['title'] = 'Popular Posts';
}
foreach ($posts as $post) {
wp_cache_add($post->ID, $post, 'posts');
$popularPosts[] = array(
'title' => stripslashes($post->post_title),
'url' => get_permalink($post->ID),
'comment_count' => $post->comment_count,
);
}
echo $args['before_widget'] . $args['before_title'] . $args['title'] . $args['after_title'];
?>
<ol>
<?php
foreach ($popularPosts as $post) {
?>
<li>
<a href="<?php echo $post['url'];?>"><?php echo $post['title']; ?></a>
<?php
if ($displayComments) {
?>
(<?php echo $post['comment_count'] . ' ' . __('comments', BM_THEMENAME); ?>)
<?php
}
?>
</li>
<?php
}
?>
</ol>
<?php
echo $args['after_widget'];
}
}
?>
Further Uses for Custom Widgets?
Clients frequently need special notifications and other dynamic bits to display on their site with minimal setup. What other content that’s frequently handled via plugins would make a great custom widget?


7:38 pm
Thanks for posting this tutorial Darren, fantastic information and well presented as always. Using custom widgets for a client project is always my preferred option.
3:06 am
Great tutorial. For all those who couldn’t get the popular posts example to work as published, you need to correct the syntax error on line 46 and register the widget by adding
register_widget(‘bm_widget_popularPosts’)
3:55 am
This Tutorial makes me want to try my hand at custom widgets, nice work !!
THANKS
4:48 pm
Thanks for a detailed and easy to follow tutorial!
1:54 am
i agree with you it’s really nice work
thanks a lot
10:41 pm
Hey Darren,
Thanks for the mention, I’m honored. Keep up with the killer designs. I especially love the blog overview page you’ve designed.
Thanks!
12:48 am
Wonderful Tricks, I will try it
9:54 pm
Great job, Thank you! Now I am learning to creat my own widgets~
10:12 pm
Hi,
Great Information!!
On your ‘The Local’ site how are you processing the featured post with the image in the middle? Is this a special widget?
Thanks
Karen
10:14 pm
Yep, Featured Content is just another custom widget that pulls the latest story and whatever image is attached.
10:46 pm
I have been trying to hunt around and find this widget with no luck. Any chance you tell me where to find it?
Thanks
Karen
11:53 am
It’s included with The Local theme. If you open your widgets panel you’ll see it.
3:09 pm
Thank you for your refreshing article.
It was a pleasure reading it. Look forward to more articles from you!
3:13 pm
it is good, i want to tried but i had a error :(
7:14 am
Thank you for your wonderful post. Very informative and I enjoyed reading it along with your other articles. Thanks for sharing and continue the great work.
3:57 pm
This is great article! Thanks for share this!
7:18 am
i try that with WP 2.9.2 but it doesnt show any in user side of site however it has been showed in widget area
9:41 am
good…like this….very help me..
1:44 am
thanks for sharing…very good tutorial
7:27 am
Hello Dearen, I have just read full article and I must admit its was of great specially because in my job I use WordPress Widgets a lot so thank you very much and keep up the good work!!
11:46 pm
Wow, I cant believe the whole site is literally made with widgets! I think after reading this article, it really isnt that hard to make a widget! Hopefully, I can make one that have as much features as your site.
3:37 am
thanx for this tutorial I keep working on wordpress as well.
I need to say that your site is first class for user friendlyness and a design
12:03 pm
excellent article. I am planing to create one new plugin and want to learn how to create widgets. your article help me alot while creating this plugin. thanks for this article.
5:42 pm
Your examples does not work with WordPress 3.0
I was able to get the final code to be seen as a plugin by WP 3.0 by inserting this header
/*
Plugin Name: TEST
Plugin URI: http://etc.com
Description: blah blah
Version: 1.00
Author: test boy
Author URI: http://etc.com
*/
but when i tried to activate it, I got the following error code
Parse error: parse error in D:\Web\voivod.net\wp-content\plugins\voivodtwitter\functions.php on line 73
also, inserting this header in the first barebones example code, doesn’t work..
1:31 am
dear mr hoyt,
i’ve been following your site more than other sites which wp is the main content.
those sites are few months to a year old vs. your site and i believe you are one of the ‘foundation’ of wordpress (for being one of the few who have been sharing info about wp).
but i think you missed one thing along the way. you have not published a book yet (or did you?).
i wish you could have time to publish a kick-ass wordpress book. theme design, plugin dev’t, and so on.
throwing my coin to the wishing well now…
6:33 am
I have just read full article and I must admit its was of great specially
because in my job I use WordPress Widgets a lot so thank you very much and keep up the good work!!
excellent article..Thanks
4:55 am
I have just read full article and I must admit its was of great specially because in my job I use WordPress Widgets a lot so thank you very much and keep up the good work!!
3:16 am
Its really working.I searched this for one day.It was really good and usefull one.I learned how to create it.
Thank u.
5:29 pm
excellent article. I am planing to create one new plugin and want to learn how to create widgets. your article help me alot while creating this plugin. thanks for this article.
5:30 pm
excellent article. thanks for this article.
5:30 pm
excellent article. thanks for this article.
5:33 pm
excellent article. thanks for this article.
6:24 am
A whole site based on widgets!!! That sure is amaizing considering how limitations a widget could have. Great post. Please keep providing such informations
5:20 am
excellent article. thanks for this article.
12:08 pm
great tutorial, but it wasnt warking for me. :) i tried add this to my plugin, even i copied exact your code and it doesnt workd. i saw blank page.
i dont know if something was changed in wordpress since you wrote this tutorial, or maybe it depends if you create widget in functions.php or in plugin, but i found SOLUTION.
in my case i had to not to call function register_widget() directly but pack it in action hack ‘widgets_init’. and after this everything work ok :)
10:36 am
I used this post to create my own custom widget. Worked great!!
I do have a question, though. How do get WP to display a text description of this widget. I have the code:
function SmallPic_Widget() {
parent::WP_Widget(false, ‘Sidebar Picture Widget’);
}
and this displays “Sidebar Picture Widget” as both the title and description of the widget.
Thanks, Dan
3:27 am
fantastic tutorial
Thanks for share this!
4:31 am
Thanks a lot for detailed explanation, got a custom widget working in no time thanks to your post!!
2:21 am
Good example,thank you
Protecting the earth,Loving our world,Starting From here—-
Led Tube Light, Led Panel Light, T8 Led Tube , Led Flood Light, Led Grow Light
Car AC Parts, Car AC Hose,
LV包包, Gucci包包, Bally男包
5:19 am
Useful post and nice clear code, thxx
4:38 pm
The new kind of custom post types are awesome too! I just saw a website from New Zealand with people using them to create games.
9:50 am
Very nice article ! We thank you very much about this article.
7:32 am
excellent article. thanks for this article…thank you.Very nice article ! We thank you very much about this article…
6:17 am
thanks for sharing…
9:48 pm
thanks for sharing…
thank u
2:47 am
Exactly what I was looking for… gonna digg a little deeper into coding, customizing makes the whole thing a lot more fun :)
3:04 pm
yhanks good sharing
3:59 am
10x a lot darren..
Hmm.. getting an error trying this on
unexpected ‘{‘ on line 57..
Only me ?