How do I create a widget that only allows a single instance of a widget to be added through the Wordpress interface?

The default behaviour of widgets allows multiple instances to be added.

I am using the Example code from http://codex.wordpress.org/Widgets_API

I have seen a similar question where the answer was to use the old widget code, but I would like to continue to use that more modern code if possible.

I have seen plugins such as Twitter for Wordpress that give exact control over the number of instances allowed.


5 Answers 5


I know this is a super old question, but searching for solutions 8 years later didn't yield many results aside from this unresolved question (and a few other vague answers). Nothing I found on this site worked for me so if others arrive on this page looking for a way to limit a widget-area to single-use from a specific widget, I've provided the code that worked for me below. This solution is based on an article posted by Tom McFarlin. It makes use of jQuery's sortable function to check the widgets according against criteria every time it tries to update. I made some of my own tweaks to better suit my needs.

Please note: You'll need to replace widget_area_id with your own ID for the specific WIDGET AREA as well as widget_id with your own ID for the actual WIDGET. Place this code in an admin.js file and enqueue it on the backend.



        update: function( evt, ui ) {

            // Check each widget in the widget area to verify that it matches the ID of the widget we want there 
                var value = $(this).find('.widget-inside').children('form').children('.id_base').val();
                if( value !== 'widget_id' ){

            // And if there are more than one widget, remove all but one
            if ( 2 !== $(this).children().length ) {




Switch after the 1st instance and abort

In the following example you can find a static variable that's not set on the first instance. If the widget gets called the 1st time, we set it to true. On the 2nd run, we abort and just return without actually serving anything to the user.

class My_Widget extends WP_Widget {
    // You static instance switch
    static $instance;

    function My_Widget() {
            // We set the static class var to true on the first run
            if ( ! $this->instance ) {
                    $this->instance = true;
            // abort silently for the second instance of the widget
            else {
        // widget actual processes
    function form($instance) {
        // outputs the options form on admin
    function update($new_instance, $old_instance) {
        // processes widget options to be saved
    function widget($args, $instance) {
        // outputs the content of the widget

Code taken from the related Widgets API Codex article

Handling the global widgets array

Another option might be to check the global array containing all registered widgets:

function wpse32103_show_widgets()
    $dump  = '<pre>';
    $dump .= var_export( $GLOBALS['wp_registered_widgets'], false );
    $dump .= '</pre>';

    return print $dump;
add_action( 'shutdown', 'wpse32103_show_widgets' );

The output of the associative array contains the name as key, appended by -2 (nr. is incremented). You could search through the array on the init or admin_init hook and simply unset if you have found a second instance. Maybe something like the following:

function wpse32103_show_widgets()
        global $wp_registered_widgets;

        // Go and search for your widgets name with the above written function
        $target = 'FILL IN YOUR FOUND ARRAY KEY HERE. Without -2 (or any other appending number)';

        // Container for your targeted widget(s)
        $unsets = array();
        foreach ( array_keys( $wp_registered_widgets ) as $widget )
            // remove dashes
            $widget_check = str_replace( '-', '', $widget );
            // remove numbers
            $widget_check = preg_replace( '/[^0-9]/', '', $widget );

            // if we match, do it in our container
            if ( $widget_check === $target )
                $unsets[] = $widget;

        // less than one element in the container: abort
        if ( ! count ( $unsets ) > 1 )

        // preserve first element
        array_shift( array_values( $unsets ) );

        // unset all left instances from the global array
        foreach ( $unsets as $unset )
            unset ( $wp_registered_widgets[ $unset ] );

add_action( 'init', 'wpse32103_show_widgets' );
  • 1
    The first approach is more to my liking, but I tried it and it didn't work. Did you try it yourself out of interest? Oct 26, 2011 at 19:42
  • It should work. Could you do a var_dump( $instance );? I guess there's some typo or similiar.
    – kaiser
    Oct 27, 2011 at 1:00
  • Hi, it's showing null above each widget on the front end. But really, I want to prevent adding more than one widget in the Wordpress back end. Doing var_dump( $this->instance ); in the constructor for the widget also shows null for any/all instances. I've edited the question to clarify. Oct 27, 2011 at 11:38
  • how would one make sure that the options array only contains one set of options for the one array instance? see the related question here wordpress.stackexchange.com/questions/125971/…
    – user9
    Dec 10, 2013 at 21:05

Edit: Doh, just saw that you didn't want to use to the old code. Oh well, I'll leave it just in case it helps someone.

WP added multi widgets in 2.8. So, I tracked down a tutorial that covered how to make a widget in WP 2.7. Here's the code:

add_action("widgets_init", array('Widget_name', 'register'));
register_activation_hook( __FILE__, array('Widget_name', 'activate'));
register_deactivation_hook( __FILE__, array('Widget_name', 'deactivate'));
class Widget_name {
  function activate(){
    $data = array( 'option1' => 'Default value' ,'option2' => 55);
    if ( ! get_option('widget_name')){
      add_option('widget_name' , $data);
    } else {
      update_option('widget_name' , $data);
  function deactivate(){
    function control(){
        $data = get_option('widget_name');
        <p><label>Option 1<input name="widget_name_option1"
    type="text" value="<?php echo $data['option1']; ?>" /></label></p>
        <p><label>Option 2<input name="widget_name_option2"
    type="text" value="<?php echo $data['option2']; ?>" /></label></p>
         if (isset($_POST['widget_name_option1'])){
            $data['option1'] = attribute_escape($_POST['widget_name_option1']);
            $data['option2'] = attribute_escape($_POST['widget_name_option2']);
            update_option('widget_name', $data);
  function widget($args){
    echo $args['before_widget'];
    echo $args['before_title'] . 'Your widget title' . $args['after_title'];
    echo 'I am your widget';
    echo $args['after_widget'];
  function register(){
        wp_register_sidebar_widget( 'my_widget_id', 'Widget name', array('Widget_name', 'widget'));
    wp_register_widget_control( 'my_widget_id', 'Widget name', array('Widget_name', 'control'));

I replaced the calls to register_sidebar_widget and register_widget_control with wp_register_sidebar_widget and wp_register_widget_control respectively, to fix warnings about using deprecated functions. Otherwise, this is a straight copy/paste from the tutorial I linked to.


Here’s a proof of concept for a single-use widget derived from this answer:


Limitation: Only works in the Customizer, not on Widget admin page.

  • 2
    Could you please edit this answer with the included code? Link only answers are discouraged as they could go down or be removed. Links should be used as references or additional resources.
    – Howdy_McGee
    Dec 1, 2017 at 15:40

You don't. It's too difficult to be worth it. It's how the JS editor thing works.

BUT: Create a Widget with no settings and allow setting it up on a different page. Like this:

// In your Widget use this form() method
public function form($instance){
    $settings_url = admin_url('options-general.php?page=SettingsPage');
    echo '<p>';
        echo 'To setup this <strong>Widget</strong> go to:<br />';
        echo '<a href="', $settings_url, '" target="_blank">';
            echo '<strong>Settings &raquo; Settings Page</strong>';
        echo '</a>';
    echo '</p>';
    return 'noform';

Use add_options_page to create the SettingsPage page for Widget management. And use get_option() to retrieve the settings for Widget Output.


PS: If you need a full example, let me know.

  • Keep the rate hate flowing. I'd love hate comments too. Thanks ;) Oct 27, 2011 at 1:34
  • It's not hate, it's simply that you categorically affirm something that is not true. if(true) then {false} :o)
    – brasofilo
    May 3, 2012 at 20:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.