Skip to main content
WordPress made easy with the drag & drop Total WordPress Theme!Learn More

How To Create A Widget Plugin For WordPress

November 5, 2012

WordPress is an amazing Content Management System with many great features such as widgets. In this tutorial, I’m going to explain you how to create your own widgets within a small plugin. This post will cover some extra points that you need to understand before creating the widget itself. Here we go!

Step 1: Create your Widget Plugin

I recently created a plugin called “Freelancer Widgets Bundle”, and some people asked me how to create such a plugin, so I decided to write this post. First step is the creation of the plugin. And as you’ll see, it’s the not the hardest part. A plugin is extra code added to WordPress once you activate it. WordPress creates a loop through a folder to retrieve all available plugins and list them in the back office. To create your plugin, you’ll need an editor such as Coda (Mac), or Dreamweaver (PC & Mac). I recommend you to create your plugin in a local install of WordPress, making it on a live server can cause some troubles if you make an error. So please, wait to test our plugin before placing on it your hosting.

Open now the folder wp-content/plugins. This where you are going to add your plugin. Create a new directory and call it “widget-plugin” (actually, this name can be whatever you want). Even if our plugin will only have one single file, it’s always better to use a folder for each plugin. In your directory, create a new file called “widget-plugin.php” (this name can be changed too), and open it. We are now about to add our first lines of code. The definition of a plugin under WordPress follows some rules that you can read here on the codex. Here is how WordPress defines a plugin:

Plugin Name: Name Of The Plugin
Plugin URI: http://URI_Of_Page_Describing_Plugin_and_Updates
Description: A brief description of the Plugin.
Version: The Plugin's Version Number, e.g.: 1.0
Author: Name Of The Plugin Author
Author URI: http://URI_Of_The_Plugin_Author
License: A "Slug" license name e.g. GPL2

So, we have to modify this code to make it fit our needs:

Plugin Name: My Widget Plugin
Plugin URI:
Description: This plugin adds a custom widget.
Version: 1.0
Author: AJ Clarke
Author URI:
License: GPL2

Save your file. By only adding code to our widget-plugin.php file we have created a plugin! Well, for now the plugin doesn’t do anything, but WordPress recognizes it. To make sure it’s the case, go your administration, and go under “Plugins” menu. If your plugin appears in the plugins list you’re good, otherwise make sure you followed my instructions and try again. You can now activate the plugin.

Step 2: Create the Widget

We are now going to create the widget itself. This widget will be a PHP class extending the core WordPress class WP_Widget. Basically, our widget will be defined this way:

// The widget class
class My_Custom_Widget extends WP_Widget {

	// Main constructor
	public function __construct() {
		/* ... */

	// The widget form (for the backend )
	public function form( $instance ) {	
		/* ... */

	// Update widget settings
	public function update( $new_instance, $old_instance ) {
		/* ... */

	// Display the widget
	public function widget( $args, $instance ) {
		/* ... */


// Register the widget
function my_register_custom_widget() {
	register_widget( 'My_Custom_Widget' );
add_action( 'widgets_init', 'my_register_custom_widget' );

This code gives WordPress all the information the system needs to be able to use the widget:

  1. The constructor, to initiate the widget
  2. The form() function to create the widget form in the administration
  3. The update() function, to save widget data during edition
  4. And the widget() function to display the widget content on the front-end

1 – The constructor

The constructor is the part of code that defines the widget name and main arguments, below is an example of what it may look like.

// Main constructor
public function __construct() {
		__( 'My Custom Widget', 'text_domain' ),
			'customize_selective_refresh' => true,

Please not the use of __() around the widget name, this function is use by WordPress for translation. I really recommend you to always use these functions, to make your theme fully translatable. And the use of the ‘customize_selective_refresh’ parameter allows the widget to be refreshed under Appearance > Customize when editing the widget so instead of refreshing the entire page only the widget is refreshed when making changes.

2 – The form() function

This function is the one that creates the widget form settings in the WordPress admin area (either under Appearance > Widgets or Appearance > Customize > Widgets). This is were you’ll enter your data to be displayed on the the website. So I’ll explain how you can add text fields, text areas, select boxes and checkboxes to your widget form settings.

// The widget form (for the backend )
public function form( $instance ) {

	// Set widget defaults
	$defaults = array(
		'title'    => '',
		'text'     => '',
		'textarea' => '',
		'checkbox' => '',
		'select'   => '',
	// Parse current settings with defaults
	extract( wp_parse_args( ( array ) $instance, $defaults ) ); ?>

	<?php // Widget Title ?>
		<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php _e( 'Widget Title', 'text_domain' ); ?></label>
		<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />

	<?php // Text Field ?>
		<label for="<?php echo esc_attr( $this->get_field_id( 'text' ) ); ?>"><?php _e( 'Text:', 'text_domain' ); ?></label>
		<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'text' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'text' ) ); ?>" type="text" value="<?php echo esc_attr( $text ); ?>" />

	<?php // Textarea Field ?>
		<label for="<?php echo esc_attr( $this->get_field_id( 'textarea' ) ); ?>"><?php _e( 'Textarea:', 'text_domain' ); ?></label>
		<textarea class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'textarea' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'textarea' ) ); ?>"><?php echo wp_kses_post( $textarea ); ?></textarea>

	<?php // Checkbox ?>
		<input id="<?php echo esc_attr( $this->get_field_id( 'checkbox' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'checkbox' ) ); ?>" type="checkbox" value="1" <?php checked( '1', $checkbox ); ?> />
		<label for="<?php echo esc_attr( $this->get_field_id( 'checkbox' ) ); ?>"><?php _e( 'Checkbox', 'text_domain' ); ?></label>

	<?php // Dropdown ?>
		<label for="<?php echo $this->get_field_id( 'select' ); ?>"><?php _e( 'Select', 'text_domain' ); ?></label>
		<select name="<?php echo $this->get_field_name( 'select' ); ?>" id="<?php echo $this->get_field_id( 'select' ); ?>" class="widefat">
		// Your options array
		$options = array(
			''        => __( 'Select', 'text_domain' ),
			'option_1' => __( 'Option 1', 'text_domain' ),
			'option_2' => __( 'Option 2', 'text_domain' ),
			'option_3' => __( 'Option 3', 'text_domain' ),

		// Loop through options and add each one to the select dropdown
		foreach ( $options as $key => $name ) {
			echo '<option value="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" '. selected( $select, $key, false ) . '>'. $name . '</option>';

		} ?>

<?php }

This code is simply adding 5 fields to the widget (Title, text, textarea, select and checkbox). So first you define the defaults for your widget, then the next function parses the current settings defined/saved for your widget with the defaults (so any settings that don’t exist would revert to the default, like when you first add a widget to your sidebar). And last is the html for each field. Notice the use of esc_attr() when adding the form fields, this is done for security reasons. Whenever you echo a user-defined variable on your site you should make sure it’s first sanitized.

3 –  The update() function

The update() function is really simple. As WordPress core developers added a really powerful widgets API, we only need to add this code to update each field:

// Update widget settings
public function update( $new_instance, $old_instance ) {
	$instance = $old_instance;
	$instance['title']    = isset( $new_instance['title'] ) ? wp_strip_all_tags( $new_instance['title'] ) : '';
	$instance['text']     = isset( $new_instance['text'] ) ? wp_strip_all_tags( $new_instance['text'] ) : '';
	$instance['textarea'] = isset( $new_instance['textarea'] ) ? wp_kses_post( $new_instance['textarea'] ) : '';
	$instance['checkbox'] = isset( $new_instance['checkbox'] ) ? 1 : false;
	$instance['select']   = isset( $new_instance['select'] ) ? wp_strip_all_tags( $new_instance['select'] ) : '';
	return $instance;

As you can see all we have to do is check for each setting and if it’s not empty save it into the database. Notice the use of the wp_strip_all_tags() and wp_kses_post() functions, these are used to sanitize the data before it’s added to the database. Whenever you are inserting ANY user submitted content into a database you need to make sure it doesn’t have any malicious code. The first function wp_strip_all_tags removes everything except basic text so you can use it for any fields where the end value is a string and the second function wp_kses_post() is the same function used for the post content and it removes all tags besides basic html like links, spans, divs, images, etc.

4 –  The widget() function

The widget() function is the one that will output the content on the website. It’s what your visitors will see. This function can be customized to include CSS classes, and specific tags to match perfectly your theme display. Here is the code (please not that this code can be modified easily to fit your needs):

// Display the widget
public function widget( $args, $instance ) {

	extract( $args );

	// Check the widget options
	$title    = isset( $instance['title'] ) ? apply_filters( 'widget_title', $instance['title'] ) : '';
	$text     = isset( $instance['text'] ) ? $instance['text'] : '';
	$textarea = isset( $instance['textarea'] ) ?$instance['textarea'] : '';
	$select   = isset( $instance['select'] ) ? $instance['select'] : '';
	$checkbox = ! empty( $instance['checkbox'] ) ? $instance['checkbox'] : false;

	// WordPress core before_widget hook (always include )
	echo $before_widget;

   // Display the widget
   echo '<div class="widget-text wp_widget_plugin_box">';

		// Display widget title if defined
		if ( $title ) {
			echo $before_title . $title . $after_title;

		// Display text field
		if ( $text ) {
			echo '<p>' . $text . '</p>';

		// Display textarea field
		if ( $textarea ) {
			echo '<p>' . $textarea . '</p>';

		// Display select field
		if ( $select ) {
			echo '<p>' . $select . '</p>';

		// Display something if checkbox is true
		if ( $checkbox ) {
			echo '<p>Something awesome</p>';

	echo '</div>';

	// WordPress core after_widget hook (always include )
	echo $after_widget;


This code isn’t complex, all you have to remember is to to check if a variable is set, if you don’t and if you want to print it, you’ll get an error message.

The Complete Widget Plugin Code

Now if you have been following correctly your plugin should now be fully functional and you can customize it to fit your needs. If you haven’t been following the guide or want to double check the code you can visit the Github page to view the full code.

View Full Code on Github


We saw that creating a widget inside a plugin is very interesting, now you must know how to create a simple plugin containing a widget with different field types and you learnt how to go a bit further using advanced techniques to customize the widget. Congratulations, you did an amazing job!

Subscribe to the Newsletter

Get our latest news, tutorials, guides, tips & deals delivered to your inbox.


  1. Gregg

    Great tutorial AJ. – Thanks!

    • AJ Clarke | WPExplorer

      You’ll have to thank our awesome new Contributor “Rémi Corson” 😉

  2. Dawson

    Very time article and I’m scratching my head how this plugin thing works. Thanks for writing a detailed article. Kudos.

    • Remi

      Hi, if you need some help let us know!

  3. behzad

    Hi Aj, Thanks for share this post

  4. Bucur

    very nice tutorial AJ congratulations

  5. Mike Keating

    Thanks so much AJ and Remi. This is awesome. Keep up the great work. Love what you are doing 🙂

    • Remi

      Thanks Mike!

  6. Tino

    very useful. tahnks…

  7. David - Closemarketing

    Nice Tutorial… I’m going to use it Soon!

  8. stacey

    You just simplified something that had my brain in knots. Thank you thank you thank you!

  9. Clarke Design

    Hi, nice and easy tutorial.

    All working fine for me except that carriage returns / line breaks in the textarea are not being passed through to the output on the public website.

    The widget stores them fine but doesn’t output them

    any ideas ?

    • Remi

      can you share a bit your code pastebin or github gist?

  10. Clarke Design
  11. romey

    Awesome….. tanx

  12. Joe

    Really good tutorial, very clear and easy to modify. Cheers

  13. Gaetano

    Fantastic Tutorial ! Easy to follow and breaks down all the main components. This is how people need to communicate. I find it hard when people try to write tutorials and expect that certain knowledge is assumed. This is for no experience and in experienced people to become experienced. Well done!

    • Remi

      Many thanks!

  14. DrV

    Really good, many thanks, I just made a widget for my plugin following your tutorial 😀 .
    Only if you could explain the part of “apply_filters” since many noobs like me find it misterious. Also the extract($args).
    Thanks for your effort sir!

    • Remi

      Thanks! The apply_filters section is not very complicated but i couldn’t cover everything. I think that Pippin Williamson did an amazing tuto on his site a few months ago about that.

  15. tommytx

    and in my next post I’ll show you how to add more complex field types
    Thanks for the great detailed post. did you ever get around to doing more as you promised… URL please. love your work.

  16. chris

    Anyway to use the $title variable as the widget name in the constructor? I plan on having many instances of the same widget in my sidebars. This would add a unique title to each.

    • AJ Clarke | WPExplorer

      If you need for this is for styling/javascript, then I would recommend just adding an ID to whatever wrapper you are using for the widget (div id=”social-widget-$title). I don’t see any point in using it in the “constructor”.

  17. Yanis Christodoulou

    Perfect tutorial, thank you very much Remi 🙂

  18. Cary Kelly

    Thanks Remi for the great tutorial. I’m having some problem with my widget though; after activating the plugin, none of my widgets (including the custom one) will stay open on the WordPress widget page. I can view the title box for each widget, but upon clicking the dropdown by each name, no information will display–for any widget! The problem disappears after I deactivate the custom plugin. I have my code up here:
    Maybe I’ve just made a small mistake? I am just a beginner in the world of PHP and WordPress.

  19. akexis


    Finally a tutorial that doesn’t assume you know to place your code in the plugins folder. It doesn’t assume you know what the functions are for. A great tut for getting off the ground and running. You kept it simple, gave great example code and explained what the different sections are doing.

    Awesome. Thanks.

  20. Remi

    Many thanks! 😉

  21. Kumaresh Cool

    Thanks for the tutorial ….

  22. Agent Bey

    Great tutorial! One simple question. I am unable to see the widget name and description under the Available Widgets. The widget name is blank. All else is working properly.

    How do I correct that?

  23. Agent Bey

    Disregard my last message. It was answered in part two. Very clear and concise. And I have already have my widgets running.

    • AJ Clarke | WPExplorer

      Great! I am glad to hear that 😉

  24. Ross Dallaire

    Nice tutorial! It worked on my first try.

  25. edna

    Nice and clean structure article. Thanks buddy,

    But in ‘function update’ its better to have a verification for empty field, so that we can avoid many things.

    Learnt from this article

  26. GratuiTous

    Great. Thank-you Remi 🙂 — Awesome start to someone learning PHP + developing simple plugins!

  27. Pawan Sharma

    Best article, read it first time and understood everything. Keep writing.

  28. An

    Hi, How to create input choose image, upload gallery?

    • AJ Clarke

      This is intended to be a simple guide for creating a widget, but if you want you can download my “More Widgets” plugin and see how I’ve done it. This plugin includes an image select field for the “About” widget (see the files at more-widgets/inc/widgets/about.php and more-widgets/assets/js/media-upload-btn.js)

Leave a Reply

Your email address will not be published. Required fields are marked *

Learn how your comment data is processed by viewing our privacy policy here.