How to save custom settings for your WordPress plugin

I used to build WordPress plugins and front-end apps for my freelance clients. Many times I had to make the WordPress plugin configurable through the WordPress dashboard. There are several ways to do this, but the recommended approach is to use the WordPress Settings API.

In this post I’ll guide you through on how to create a basic settings page for your WordPress plugin using the WP Settings API.

Complete Source Code

Disclaimer: This guide assumes you already have basic knowledge of WordPress plugin development such as Hooks and Filters and how to register and use shortcodes.

Since versions 2.7, WordPress has included a standardized Settings API to let plugin and theme developers to save settings and options using the WordPress dashboard. Using this API grants several advantages over other solutions.

Basically, adding settings for a plugin in WordPress roughly follow the given steps:

  1. Register the menu page and/or a sub-menu page in the WP Dashboard
  2. Add a settings section under the sub-menu page
  3. Register settings and settings fields under the settings section
  4. Add settings fields for each registered setting and provide a callback that renders the html for each field

Let’s go through each of these steps one-by-one.

Basic Setup

For this tutorial I’ll be building a basic wordpress plugin to go along with the explanation. It is always better to write code by hand to get a feel for it.

Here is the starter code. It registers a single shortcode and displays “Hello world!” where ever the short code is called. Let’s try it.

<?php
/*
Plugin Name: Tutorial WordPress Plugin
*/

function render_text()
{
    echo '<h1>Hello world!</h1>';
}
add_shortcode('my-settings', 'render_text');

 

If you’ll add the shortcode [my-settings] to any page on your WP site, it should render Hello world!

Registering the menu and sub-menu page

Menu pages in the dashboard are top level pages that contain one or more sub-pages. Examples of menu pages include Posts, Media, Pages and Appearance etc. Each of these are default menu pages in WordPress and contain several sub-pages.

Menu and sub menu items

It is completely upto you whether you want to register a top level menu page for your plugin or not. Most plugins have sub-menu pages under one of the default top level menus such as Tools or Settings. I’m going to register my plugin under the default Settings menu page. For that we’ll be using the add_submenu_page function. Add the following code in your plugin.

<?php
function my_settings_page()
{
    add_submenu_page(
        'options-general.php', // top level menu page
        'My Settings Page', // title of the settings page
        'My Settings', // title of the submenu
        'manage_options', // capability of the user to see this page
        'my-settings-page', // slug of the settings page
        'my_settings_page_html' // callback function when rendering the page
    );
}
add_action('admin_menu', 'my_settings_page');

function my_settings_page_html() {

}

What this code does is it calls the my_settings_page() function on the admin_menu hook, In which the add_submenu_page() function is used to add the menu page under the Settings tab. You’ll notice that I have defined a function my_settings_page_html() and left it empty, We will use this later on. Now if you’ll open up your WP Dashboard, you should see a My Settings submenu under the Settings menu.

My Settings under Settings

So far so good. Onto the next step!

Adding a settings section under the sub-menu page

Next we are going to register a settings section under our menu page. A settings section in WordPress groups together relevant settings so that they can be shown on a single section under a settings page. You can add multiple sections under the same page. We are going to use only 1 section for now. To add a settings section we are going add another hook and callback combo in our code. We are going to add a function to register our settings at the admin_init hook. So our code becomes:

function my_settings_page() {
    add_submenu_page(
        'options-general.php', // top level menu page
        'My Settings Page', // title of the settings page
        'My Settings', // title of the submenu
        'manage_options', // capability of the user to see this page
        'my-settings-page', // slug of the settings page
        'my_settings_page_html' // callback function when rendering the page
    );
    add_action('admin_init', 'my_settings_init');
}
add_action('admin_menu', 'my_settings_page');

function my_settings_init() {
    add_settings_section(
        'my-settings-section', // id of the section
        'My Settings', // title to be displayed
        '', // callback function to be called when opening section, currently empty
        'my-settings-page' // page on which to display the section
    );
}

function my_settings_page_html() {

}

As you can see, we’ve added a new function my_settings_init() that gets called on the admin_init hook. We call this hook inside the admin_menu hook so that when the admin panel is loaded our my_settings_init() function gets called. We will now register and add our settings in the my_settings_init() function. Let’s do that right now.

Registering settings and adding settings fields and callbacks

There are two functions used to add custom settings to a settings section in WordPress, register_setting() and add_settings_field. register_settings() registers a setting to our WordPress with a unique ID, while add_settings_field() defines the actual markup and metatdata for each setting that will be diplayed in the section. We will add a single setting to our plugin called my_first_setting using these functions. These will be added in the my_settings_init() function, so the code becomes:

function my_settings_init() {
    add_settings_section(
        'my-settings-section', // id of the section
        'My Settings', // title to be displayed
        '', // callback function to be called when opening section
        'my-settings-page' // page on which to display the section, this should be the same as the slug used in add_submenu_page()
    );

    // register the setting
    register_setting(
        'my-settings-page', // option group
        'my_first_text'
    );

    add_settings_field(
        'my-first-text', // id of the settings field
        'My First Text', // title
        'my_settings_cb', // callback function
        'my-settings-page', // page on which settings display
        'my-settings-section' // section on which to show settings
    );
}

function my_settings_cb() {
    $first_text = esc_attr(get_option('my_first_text', ''));
    ?>
    <?php echo $first_text; ?>

    <?php
}

 

You will see that I have added another callback function my_settings_cb() which is called after the add_settings_field() function. This function contains the actual markup that will be displayed on the settings page for the specific setting.

You might remember we had a function called my_settings_page_html() that we left empty. Now we are going to use that function and include our settings code in it. That code will display our settings on the Admin dashboard and provide an interface to save them.

function my_settings_page_html() {
    // check user capabilities
    if (!current_user_can('manage_options')) {
        return;
    }
?>

<div class="wrap">
    <?php settings_errors();?>
    <form method="POST" action="options.php">
        <?php settings_fields('my-settings-page');?>
        <?php do_settings_sections('my-settings-page')?>
        <?php submit_button();?>
    </form>
</div>
<?php
}

 

Now if you open up your browser and navigate to My Settings you should see a single text field with a save button. You can save any text in this field.

Now we will modify the shortcode function to display my_first_text on the front-end.

function my_render_text() {
    $first_text = esc_attr(get_option('my_first_text', ''));

    echo '<h1>' . $first_text . '</h1>';
}
add_shortcode('my-settings', 'my_render_text');

 

Now if you refresh the homepage of your site it should display whatever text you stored in the field.

You can find all the finished code for the plugin here. I hope this helps you get you started with the WordPress Settings API and WordPress plugin development. I know this API is a little hard to work with but once you get the feel for it it seems slightly less bad than it is. Happy coding!