One of the many nice new features of WordPress 2.8 is the inclusion of a new widget API. As most of you probably know, my company Spiral Web Consulting maintains Google Analyticator which recently added a Google Analytics stat widget. When I heard WordPress was introducing a new widget API, I decided it would be fun to add API support to the existing Google Analytics stat widget. When looking through the Codex’s explanation of the new API, I realized they did not really include a good tutorial on how to create a widget using the API.
In this tutorial, I will teach you how to create a Hello World sidebar widget using the WordPress 2.8 widget API. I will provide the code throughout this post, and also provide the examples for download at the end of the post. This example will be demonstrated on the Default WordPress theme and provide two configurable lines of text that can be modified.
There are three main functions that every widget must include. These functions include widget(), update(), and form() and are each responsible for a different part of the widget. Let’s take a brief look at each function.
widget()
/**
* Displays the Widget
*
*/
function widget($args, $instance){
extract($args);
$title = apply_filters('widget_title', empty($instance['title']) ? ' ' : $instance['title']);
$lineOne = empty($instance['lineOne']) ? 'Hello' : $instance['lineOne'];
$lineTwo = empty($instance['lineTwo']) ? 'World' : $instance['lineTwo'];
# Before the widget
echo $before_widget;
# The title
if ( $title )
echo $before_title . $title . $after_title;
# Make the Hello World Example widget
echo '<div style="text-align:center;padding:10px;">' . $lineOne . '<br />' . $lineTwo . "</div>";
# After the widget
echo $after_widget;
}
The widget() function will be the first function we delve into. This function is responsible for displaying the widget. The above function was created for the Hello World example. This function will always require two parameters, $args and $instance.
$args contains the native WordPress variables for the widget that some themes use to ensure the widget is used properly. extract($args); creates those variables, such as $before_widget, $before_title, $after_title, and $after_widget. These are important to include to ensure that all themes will be compatible with your widget.
$instance is the instance of your widget that is currently being passed to the function. WordPress 2.8’s widget API adds the ability to have multiple instances of each widget. $instance is an array that will store all of your widget’s configurable options, which in this case is $title, $lineOne, and $lineTwo. It is important to note that when calling for each option, you should use an if statement to ensure that if the string was empty that the default will be used. This may not be necessary for each element so use desecration when doing this, but it can be useful when you do not want a certain value to be left empty. Another important thing to note is that there are certain WordPress values that WordPress will use differently. For instance, $title has a special filter applied because it is the title of the widget which WordPress recognizes.
update()
/**
* Saves the widgets settings.
*
*/
function update($new_instance, $old_instance){
$instance = $old_instance;
$instance['title'] = strip_tags(stripslashes($new_instance['title']));
$instance['lineOne'] = strip_tags(stripslashes($new_instance['lineOne']));
$instance['lineTwo'] = strip_tags(stripslashes($new_instance['lineTwo']));
return $instance;
}
update() is by far the simplest of the three functions. All update() does is save the values of each of the configurable options for the widget.
The update() function takes two different parameters, $new_instance and $old_instance. These variables are rather self explanatory. The old instance($old_instance) is overwritten by the new instance($new_instance) which values are taken from the widget form.
Always be sure to include the proper PHP functions such as strip_tags() and stripslashes() to ensure that no matter what a user puts in the widget options, they will not break the page the widget appears on.
form()
/**
* Creates the edit form for the widget.
*
*/
function form($instance){
//Defaults
$instance = wp_parse_args( (array) $instance, array('title'=>'', 'lineOne'=>'Hello', 'lineTwo'=>'World') );
$title = htmlspecialchars($instance['title']);
$lineOne = htmlspecialchars($instance['lineOne']);
$lineTwo = htmlspecialchars($instance['lineTwo']);
# Output the options
echo '<p style="text-align:right;"><label for="' . $this->get_field_name('title') . '">' . __('Title:') . ' <input style="width: 250px;" id="' . $this->get_field_id('title') . '" name="' . $this->get_field_name('title') . '" type="text" value="' . $title . '" /></label></p>';
# Text line 1
echo '<p style="text-align:right;"><label for="' . $this->get_field_name('lineOne') . '">' . __('Line 1 text:') . ' <input style="width: 200px;" id="' . $this->get_field_id('lineOne') . '" name="' . $this->get_field_name('lineOne') . '" type="text" value="' . $lineOne . '" /></label></p>';
# Text line 2
echo '<p style="text-align:right;"><label for="' . $this->get_field_name('lineTwo') . '">' . __('Line 2 text:') . ' <input style="width: 200px;" id="' . $this->get_field_id('lineTwo') . '" name="' . $this->get_field_name('lineTwo') . '" type="text" value="' . $lineTwo . '" /></label></p>';
}
The final piece of the trifecta, form(), is used to display the form that is used on the WordPress admin interface when creating the widget. This form should include the proper input options for each configurable setting for the widget. It is important to note, WordPress now provides both the Save and Remove buttons natively, and it is not necessary to code in those buttons.
This function should also include an array of default values which will be used to populate the form the first time the widget is called in the WordPress admin interface.
WordPress 2.8 now has two different functions that are used in conjunction with the form. get_field_name() and get_field_id() will provide you will the correct field names and ids for each configurable option. This code is necessary in order to enable multiple instances of your widget.
If you are developing a plugin to be used in multiple languages, you must provide localization support by encapsulating your text with __( ). I don’t want to get into localization, so if you are planning on working with multiple languages you will need to look that up.
Piecing It All Together
So you have the three new functions and you are ready to make your widget a reality. Let’s take a look at the beginning of the Hello World example widget.
<?php
/*
* Plugin Name: Hello World Example
* Version: 1.0
* Plugin URI: http://jessealtman.com/2009/06/08/tutorial-wordpress-28-widget-api/
* Description: Hello World example widget using the the WordPress 2.8 widget API. This is meant strictly as a means of showing the new API using the <a href="http://jessealtman.com/2009/06/08/tutorial-wordpress-28-widget-api/">tutorial</a>.
* Author: Jesse Altman
* Author URI: http://jessealtman.com/
*/
class HelloWorldWidget extends WP_Widget
{
/**
* Declares the HelloWorldWidget class.
*
*/
function HelloWorldWidget(){
$widget_ops = array('classname' => 'widget_hello_world', 'description' => __( "Example widget demoing WordPress 2.8 widget API") );
$control_ops = array('width' => 300, 'height' => 300);
$this->WP_Widget('helloworld', __('Hello World Example'), $widget_ops, $control_ops);
}
In order to get WordPress to recognize this plugin, you need to give it the proper header. You should include a Plugin Name, Version, Plugin URI, Description, Author, and Author URI.
The next thing you need to do is declare your class. The class should be named something similar to what your widget is called. This class must extend the WP_Widget class in order to function properly. As with any class, you must give it a declaration.
In the class declaration, you need to have a few variables.$widget_ops contains the class name and the description of the widget. WordPress’ admin interface will use this to display the correct information for your widget. I opted to use $control_ops which is an optional parameter that can be passed to the WP_Widget function that will specify the width and height of the WordPress admin interface options menu for your widget. The final function in the class description is WP_Widget and must always be in the class declaration. This function creates your widget in the WordPress admin interface.
Following the class declaration you should provide the widget(), update(), and form() functions to your file. You can then create custom functions used throughout the class. You should place these functions after the form() function.
Wrapping It Up
In order to finish the widget, you need to register it. Let’s take a look at the end of the Hello World example widget.
}// END class
/**
* Register Hello World widget.
*
* Calls 'widgets_init' action after the Hello World widget has been registered.
*/
function HelloWorldInit() {
register_widget('HelloWorldWidget');
}
add_action('widgets_init', 'HelloWorldInit');
?>
First thing to notice is that this is outside of the HelloWorldWidget class. You must not include the final function in your class. The HelloWorldInit() function uses the register_widget() function provided by WordPress. This function will register the widget with WordPress and allow users to access it via the WordPress admin interface. The add_action() function is also WordPress specific. This function will add your HelloWorldInit() function to WordPress’ widget_init() function. This ensures your widget is run when WordPress initiates widgets.
Finished Product
<?php
/*
* Plugin Name: Hello World Example
* Version: 1.0
* Plugin URI: http://jessealtman.com/2009/06/08/tutorial-wordpress-28-widget-api/
* Description: Hello World example widget using the the WordPress 2.8 widget API. This is meant strictly as a means of showing the new API using the <a href="http://jessealtman.com/2009/06/08/tutorial-wordpress-28-widget-api/">tutorial</a>.
* Author: Jesse Altman
* Author URI: http://jessealtman.com/
*/
class HelloWorldWidget extends WP_Widget
{
/**
* Declares the HelloWorldWidget class.
*
*/
function HelloWorldWidget(){
$widget_ops = array('classname' => 'widget_hello_world', 'description' => __( "Example widget demoing WordPress 2.8 widget API") );
$control_ops = array('width' => 300, 'height' => 300);
$this->WP_Widget('helloworld', __('Hello World Example'), $widget_ops, $control_ops);
}
/**
* Displays the Widget
*
*/
function widget($args, $instance){
extract($args);
$title = apply_filters('widget_title', empty($instance['title']) ? ' ' : $instance['title']);
$lineOne = empty($instance['lineOne']) ? 'Hello' : $instance['lineOne'];
$lineTwo = empty($instance['lineTwo']) ? 'World' : $instance['lineTwo'];
# Before the widget
echo $before_widget;
# The title
if ( $title )
echo $before_title . $title . $after_title;
# Make the Hello World Example widget
echo '<div style="text-align:center;padding:10px;">' . $lineOne . '<br />' . $lineTwo . "</div>";
# After the widget
echo $after_widget;
}
/**
* Saves the widgets settings.
*
*/
function update($new_instance, $old_instance){
$instance = $old_instance;
$instance['title'] = strip_tags(stripslashes($new_instance['title']));
$instance['lineOne'] = strip_tags(stripslashes($new_instance['lineOne']));
$instance['lineTwo'] = strip_tags(stripslashes($new_instance['lineTwo']));
return $instance;
}
/**
* Creates the edit form for the widget.
*
*/
function form($instance){
//Defaults
$instance = wp_parse_args( (array) $instance, array('title'=>'', 'lineOne'=>'Hello', 'lineTwo'=>'World') );
$title = htmlspecialchars($instance['title']);
$lineOne = htmlspecialchars($instance['lineOne']);
$lineTwo = htmlspecialchars($instance['lineTwo']);
# Output the options
echo '<p style="text-align:right;"><label for="' . $this->get_field_name('title') . '">' . __('Title:') . ' <input style="width: 250px;" id="' . $this->get_field_id('title') . '" name="' . $this->get_field_name('title') . '" type="text" value="' . $title . '" /></label></p>';
# Text line 1
echo '<p style="text-align:right;"><label for="' . $this->get_field_name('lineOne') . '">' . __('Line 1 text:') . ' <input style="width: 200px;" id="' . $this->get_field_id('lineOne') . '" name="' . $this->get_field_name('lineOne') . '" type="text" value="' . $lineOne . '" /></label></p>';
# Text line 2
echo '<p style="text-align:right;"><label for="' . $this->get_field_name('lineTwo') . '">' . __('Line 2 text:') . ' <input style="width: 200px;" id="' . $this->get_field_id('lineTwo') . '" name="' . $this->get_field_name('lineTwo') . '" type="text" value="' . $lineTwo . '" /></label></p>';
}
}// END class
/**
* Register Hello World widget.
*
* Calls 'widgets_init' action after the Hello World widget has been registered.
*/
function HelloWorldInit() {
register_widget('HelloWorldWidget');
}
add_action('widgets_init', 'HelloWorldInit');
?>
If you combine all of these code snippets together, this is what your final PHP file should look like. Click the images for a larger view.
Single Widget – Front End
![]()
Single Widget – Back End
![]()
Double Widget – Front End
![]()
Double Widget – Back End
![]()
Plugin Interface
![]()
Download
Download the Hello World Example


Ronald Heft
June 9th, 2009
Great tutorial. The new WordPress 2.8 widget API is worlds better than the system they had before. The old API always seemed more like a hack that was brought it to WordPress (which, it indeed was) and never properly thought out.
Jesse Altman
June 9th, 2009
I’m just glad they added an official way to create widgets. I am also happy they made it so that widgets are built with the ability to have multiple instances. This new WordPress version is going to make a developer’s life much easier (in terms of widget creation).
Glenn Bennett
June 9th, 2009
Jesse,
Nice little tutorial here. One problem with the new Widget class is that if you don’t have 2.8 it obviously won’t work so maybe you need to have an old style version of your widget as well. With the new update system it might not be that big of a problem, but who knows how these things work out.
I created a WordPress widget maker over at Widgetifyr.com, and let users generate their widgets in either style. If you get a change take a look and let me know what you think.
Hey I use your podcast plug in and it seems to work great.
Thanks
Glenn
Jesse Altman
June 9th, 2009
I guess I should have added that little tidbit in the tutorial somewhere, but I thought it was implied (the WordPress 2.8 is the only version of WordPress that will run this widget).
I just took a quick glance over your site, and I must say it seems like a pretty neat tool. I have never been a fan of code generators however, since they tend to have the ability to add extra bloat that isn’t necessary. Overall though it seems like it could be an extremely useful tool for creating a new widget quicker than ever. I will have to look into it further the next time I need to build a widget! Good job!
Also, thanks for the kind words about Podcasting.
JamesD
June 11th, 2009
Thanks for the useful info. It’s so interesting
mk2
June 14th, 2009
Now that WP 2.8 is out, I’m really gonna try this. Thanks!
Dan
June 15th, 2009
What If I don’t want the widget to appear in the sidebar? I want my widget to be embedded in a post or page using short codes. I don’t see anywhere where we are explicitly telling wordpress to push this widget in to the sidebar.
Jesse Altman
June 15th, 2009
That technically wouldn’t be considered a WordPress widget in that case. This tutorial was made strictly for widgets that WordPress will see as a sidebar widget. We aren’t explicitly saying it is for the sidebar, but that is how WordPress registers widgets. Here is an article explaining WordPress widgets.
Line In
December 4th, 2009
If you do a search, there are plenty of tutorials on how to widgetise areas other than the sideabar.
I’m not sure about using short codes, though. That would probably require some work.
Eric Lightbody
June 23rd, 2009
Great tutorial, thanks a ton!
I just wanted to let you know that I think some code should be changed just a bit. In function form() you have get_field_name(’title’) . ‘”> It should be get_field_id(’title’) . ‘”> so that the for matches up with the id for the input field.
Thanks again!
Ronald Heft
June 24th, 2009
No, I believe Jesse is correct. The ‘for’ parameter of a <label> tag should match up with the ‘name’ parameter of an <input> tag.
Paul Novitski
February 23rd, 2010
No, Eric was correct, the
forattribute value is theidof the input field, not itsname.HTML 4.01 Specification
17.9.1 The LABEL element
for = idref [CS]
This attribute explicitly associates the label being defined with another control. When present, the value of this attribute must be the same as the value of the id attribute of some other control in the same document.
http://www.w3.org/TR/html4/interact/forms.html#h-17.9.1
Federico González Brizzio
June 30th, 2009
Excellent! I’m working to make two news groups (instances) for the same widget in sidebar. You can view it here http://www.cuencadelplata-granchaco.org/private/ “Novedades” & “Noticias de interés”.
Thanks from Ushuaia, Argentina
Umar
July 16th, 2009
Thanks for a wonderful tutorial
Louis Vuitton Handbags and Wallets
July 20th, 2009
Keep working, great job, I love it!
Jeff
July 21st, 2009
How do I use get_field_name() and get_field_id() with an array of options. For instance, a plugin I created allows setting an option per user role, and I save the option as an array as follows:
$show_link['subscriber'] = true;
$show_link['contributor'] = true;
etc. etc.
How can I still implement this?
Jesse Altman
July 21st, 2009
I am assuming you want each of these options customizable separately correct? If so, this should be rather simple. All you need to do is change the variable declarations to an array.
For instance, this sample plugin uses $lineOne and $lineTwo to indicate the separate lines of the output. I can easily change these options to an array, such as $line['one'] and $line['two']. You should be able to leave everything else the same way and the plugin will work fine.
In your case, all you need to do is define each index of $show_link as an index of $instance. This way it will all relate correctly.
I modified my Hello World example to better explain what I am doing. You can download it here.
Okey-Dokey
August 15th, 2009
I neeed to convert one ’single’ widget to multi. I really don’t know how it to do. This widget use other pinciples — register_sidebar_widget and register_widget_control functions…
craig
August 26th, 2009
Very good article, thank you for sharing. Great job
Simon Fairbairn
September 6th, 2009
Just wanted to join in with the general chorus of appreciation for providing this tutorial.
Thanks very much!
Si
Buyer Keywords Generator
September 12th, 2009
Excellent article this has been an brilliant read.
Home Based MLM
October 23rd, 2009
Awesome tutorial. Perfect for those of us who just upgraded to 2.8
Greg Morris
January 12th, 2010
Just wanted to say thank you.
I found other tutorials for this and they were no where near as clear as yours. They said things like “The code should be self explanatory”. If that were the case I would’ve just gone to the codex!
I made a plugin for DART for publishers ad tags and turned template tags into widgets with this guide.
Thanks!
Jenny
January 24th, 2010
This is super helpful! The first tutorial that I have found that doesn’t assume I’m a programming pro. Thanks a lot.
dandy
March 27th, 2010
How can i create a single instance widgets using this class?
I dont want multiple instance widget.
Thanks,
dralezero
April 24th, 2010
How do I make two different widgets in my plugin file? I tried duplicating the whole process with different names for the other widget but only one shows. I looked at another plugin that has multiple widgets with this class, I’m not sure what I should be doing.
Hetal Bhagat
April 28th, 2010
Thanks for the awesome tutorial. Following your example I was able to create my first ever Wordpress widget.
saleandiscount.appspot.com
June 3rd, 2010
Great post, Information about these Issues Always seem to make my day better!
Boyce Simmens
June 14th, 2010
Another Good wordpress post, I will be sure to bookmark this post in my Propeller account. Have a awesome day.
gunawan
June 14th, 2010
thanks for info,
good
Wordpress Developer
June 18th, 2010
I have widgets installed & customized in my own blog , it was not that easy .
But this article has helped me to get an idea on how easy to make use of widgets
I appreciate Jesse’s efforts on this article
Katherine Campbell
July 19th, 2010
Eminem is the best rapper, i have a collection of his live concerts and cds-~*