Thursday, April 10, 2025

4 min read

How to Create a Custom Sidebar Widget Without a Plugin in WordPress

Custom sidebar widgets are still a solid way to add small, reusable bits of functionality to your WordPress site. You do not need a plugin for this - just a simple class that extends WP_Widget and a registration hook. Let’s wire one up step by step.

Step 1: Define the Widget Class

Open your active theme’s `functions.php` file (or better: a small custom plugin) and start by defining a widget class that extends `WP_Widget`. This sets up the structure WordPress expects:

php
1class My_Sidebar_Widget extends WP_Widget {
2  
3      public function __construct() {
4          // Widget setup
5      }
6  
7      public function widget( $args, $instance ) {
8          // Frontend output
9      }
10  
11      public function form( $instance ) {
12          // Backend form fields
13      }
14  
15      public function update( $new_instance, $old_instance ) {
16          // Save settings
17      }
18  }

This by itself does nothing yet, but it gives you the four main methods every widget should implement.

Step 2: Fill Out the Widget Class

Constructor: Name and Description

php
1public function __construct() {
2      $widget_details = array(
3          'classname'   => 'my_sidebar_widget',
4          'description' => 'A simple custom sidebar widget example.',
5      );
6  
7      parent::__construct(
8          'my_sidebar_widget',      // Base ID
9          'My Sidebar Widget',      // Name in the admin UI
10          $widget_details
11      );
12  }

Frontend Output: widget()

The `widget()` method controls what shows up in the sidebar on the frontend. We will use the instance title if set, and print a simple message as the widget content:

php
1public function widget( $args, $instance ) {
2      $title = ! empty( $instance['title'] ) ? $instance['title'] : '';
3  
4      echo $args['before_widget'];
5  
6      if ( ! empty( $title ) ) {
7          echo $args['before_title'] . esc_html( $title ) . $args['after_title'];
8      }
9  
10      echo '<p>Hello, World!</p>';
11  
12      echo $args['after_widget'];
13  }

Admin Form: form()

The `form()` method builds the settings form in the Widgets screen. Here we add a single text field for the title and handle empty values safely:

php
1public function form( $instance ) {
2      $title = isset( $instance['title'] ) ? $instance['title'] : '';
3      ?>
4      <p>
5          <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
6              Title:
7          </label>
8          <input
9              class="widefat"
10              type="text"
11              id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
12              name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
13              value="<?php echo esc_attr( $title ); ?>"
14          />
15      </p>
16      <?php
17  }

Save Settings: update()

php
1public function update( $new_instance, $old_instance ) {
2      $instance = array();
3      $instance['title'] = isset( $new_instance['title'] )
4          ? sanitize_text_field( $new_instance['title'] )
5          : '';
6  
7      return $instance;
8  }

Step 3: Register the Widget

Now you need to tell WordPress about the widget class using `register_widget()`. Add this below the class definition:

php
function register_my_sidebar_widget() {
      register_widget( 'My_Sidebar_Widget' );
  }
  add_action( 'widgets_init', 'register_my_sidebar_widget' );

After this, your widget will appear under Appearance -> Widgets. In newer WordPress versions with the block based widget editor, you will see it as a legacy widget and can still add it to any widget area.

Full Working Example

php
1<?php
2  // Custom sidebar widget class
3  class My_Sidebar_Widget extends WP_Widget {
4  
5      public function __construct() {
6          $widget_details = array(
7              'classname'   => 'my_sidebar_widget',
8              'description' => 'A simple custom sidebar widget example.',
9          );
10  
11          parent::__construct(
12              'my_sidebar_widget',
13              'My Sidebar Widget',
14              $widget_details
15          );
16      }
17  
18      public function widget( $args, $instance ) {
19          $title = ! empty( $instance['title'] ) ? $instance['title'] : '';
20  
21          echo $args['before_widget'];
22  
23          if ( ! empty( $title ) ) {
24              echo $args['before_title'] . esc_html( $title ) . $args['after_title'];
25          }
26  
27          echo '<p>Hello, World!</p>';
28  
29          echo $args['after_widget'];
30      }
31  
32      public function form( $instance ) {
33          $title = isset( $instance['title'] ) ? $instance['title'] : '';
34          ?>
35          <p>
36              <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
37                  Title:
38              </label>
39              <input
40                  class="widefat"
41                  type="text"
42                  id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
43                  name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
44                  value="<?php echo esc_attr( $title ); ?>"
45              />
46          </p>
47          <?php
48      }
49  
50      public function update( $new_instance, $old_instance ) {
51          $instance = array();
52          $instance['title'] = isset( $new_instance['title'] )
53              ? sanitize_text_field( $new_instance['title'] )
54              : '';
55          return $instance;
56      }
57  }
58  
59  // Register the widget
60  function register_my_sidebar_widget() {
61      register_widget( 'My_Sidebar_Widget' );
62  }
63  add_action( 'widgets_init', 'register_my_sidebar_widget' );

WordPress Developer Reference for WP_Widget:

Theme Handbook: Widgets API overview:

That is the basic pattern for a custom sidebar widget. From here you can swap out the static Hello World text with anything you need: recent items from an API, custom post queries, small forms, or anything else you can render with PHP and HTML.

About the Author
Jonas Lindemann

I’m an experienced SEO professional with over a decade of helping over 100 businesses rank higher online, especially local businesses, e-commerce stores and SaaS. As the co-founder of LPagery, I specialize in practical, proven strategies for regular SEO and Local SEO success.