Create a WordPress Theme Settings Page with the Settings API

By Narayan Prusty

Most WordPress themes have a Theme settings page to customize its features, behaviour and styles. Providing a theme settings page with your theme makes it easy for your users to customize your theme instead of directly editing the PHP or CSS files. This makes updating your theme easier, as users will not lose the changes they’ve made.

In this tutorial we’ll learn the ‘WordPress’ recommended way of creating a theme settings page, that is, using the WordPress Settings API. The WordPress Settings API was added in WordPress 2.7 and since then it has become one of the most popular WordPress APIs. This tutorial will also be useful if you’re planning to add a settings page to your WordPress plugin. Let’s get started.

What Shall We Include in a Theme Settings Page?

Options in your theme settings page depend on what features and customization your theme supports. That said, there are some common things which are included in every theme settings page. Some of the common options are: social URLs, static or responsive layout and header logo to name a few. In this tutorial I’ll show you how to include these four options in our theme settings page.

Creating a Theme Settings Page Menu Item

First we have to create a menu item on the admin panel that will access our theme settings page.

We can create a menu item using the WordPress Menu API. Here’s the code to create a menu item.

function theme_settings_page(){}

function add_theme_menu_item()
{
	add_menu_page("Theme Panel", "Theme Panel", "manage_options", "theme-panel", "theme_settings_page", null, 99);
}

add_action("admin_menu", "add_theme_menu_item");

Here, theme-panel is the unique ID representing our menu item. theme_settings_page is the callback for displaying the content of the page created by the Menu API. We’ll be coding this function next.

Here’s how it looks.

Theme Settings API

Overview of the Settings API

The Settings API is used to populate the page created by the menu item API. A settings page is divided into sections and fields.

For the sake of this tutorial, we’ll just be creating a single section and will put all the fields inside that section.

Here is the code for the theme_settings_page function to create a section and add the submit button.

function theme_settings_page()
{
    ?>
	    <div class="wrap">
	    <h1>Theme Panel</h1>
	    <form method="post" action="options.php">
	        <?php
	            settings_fields("section");
	            do_settings_sections("theme-options");      
	            submit_button(); 
	        ?>          
	    </form>
		</div>
	<?php
}

Here we’re registering a section using settings_field with an ID section. theme-options is a group ID to all of the fields belonging to a section. Finally, the submit_button() function echoes the submit button for our theme settings page.

Here’s how that should look.

Theme Settings API Example

Adding Social Profile URLs

Now, let’s add fields in our settings page to store our Facebook and Twitter profile URLs. Almost every WordPress theme has social profile options, therefore it’s a handy, practical example.

Here’s the code to add input text fields using the Settings API.

function display_twitter_element()
{
	?>
    	<input type="text" name="twitter_url" id="twitter_url" value="<?php echo get_option('twitter_url'); ?>" />
    <?php
}

function display_facebook_element()
{
	?>
    	<input type="text" name="facebook_url" id="facebook_url" value="<?php echo get_option('facebook_url'); ?>" />
    <?php
}

function display_theme_panel_fields()
{
	add_settings_section("section", "All Settings", null, "theme-options");
	
	add_settings_field("twitter_url", "Twitter Profile Url", "display_twitter_element", "theme-options", "section");
    add_settings_field("facebook_url", "Facebook Profile Url", "display_facebook_element", "theme-options", "section");

    register_setting("section", "twitter_url");
    register_setting("section", "facebook_url");
}

add_action("admin_init", "display_theme_panel_fields");

After the admin panel is initialized, we’re registering the sections and fields display callbacks. Here we’re using three important functions:

  1. add_settings_section is used to display the section heading and description.
  2. add_settings_field is used to display the HTML code of the fields.
  3. register_setting is called to automate saving the values of the fields.

Here’s what our settings page should now look like.

Theme Settings API Social Profiles

We’ve now seen how to add input text fields using our settings page. Let’s see how to add a checkbox by providing an option to choose between static or responsive layouts.

Adding Option to Choose Between Layouts

Let’s see how to expand out the display_theme_panel_fields function to display a checkbox to choose between layouts.

Here’s the code to achieve this.

function display_twitter_element()
{
	?>
    	<input type="text" name="twitter_url" id="twitter_url" value="<?php echo get_option('twitter_url'); ?>" />
    <?php
}

function display_facebook_element()
{
	?>
    	<input type="text" name="facebook_url" id="facebook_url" value="<?php echo get_option('facebook_url'); ?>" />
    <?php
}

function display_layout_element()
{
	?>
		<input type="checkbox" name="theme_layout" value="1" <?php checked(1, get_option('theme_layout'), true); ?> /> 
	<?php
}

function display_theme_panel_fields()
{
	add_settings_section("section", "All Settings", null, "theme-options");
	
	add_settings_field("twitter_url", "Twitter Profile Url", "display_twitter_element", "theme-options", "section");
    add_settings_field("facebook_url", "Facebook Profile Url", "display_facebook_element", "theme-options", "section");
    add_settings_field("theme_layout", "Do you want the layout to be responsive?", "display_layout_element", "theme-options", "section");

    register_setting("section", "twitter_url");
    register_setting("section", "facebook_url");
    register_setting("section", "theme_layout");
}

add_action("admin_init", "display_theme_panel_fields");

We added a new settings field using add_settings_field and registered it using register_settings as usual. One thing to note, if we want to tell whether a user has checked the checkbox or not, we’re using the checked() function.

The checked() function compares a value with an another value, if they’re equal then it echoes a checked attribute, otherwise nothing.

Here’s how our settings page looks now.

Settings API Checkbox Example

Uploading a Logo

The register_setting function takes a third argument which is a callback, this callback is fired before it saves the settings into the database. We can utilise this callback to handle uploads.

Here is code to upload a logo in our settings page.

function logo_display()
{
	?>
        <input type="file" name="logo" /> 
        <?php echo get_option('logo'); ?>
   <?php
}

function handle_logo_upload()
{
	if(!empty($_FILES["demo-file"]["tmp_name"]))
	{
		$urls = wp_handle_upload($_FILES["logo"], array('test_form' => FALSE));
	    $temp = $urls["url"];
	    return $temp;   
	}
	  
	return $option;
}

function display_theme_panel_fields()
{
	add_settings_section("section", "All Settings", null, "theme-options");
	
    add_settings_field("logo", "Logo", "logo_display", "theme-options", "section");  

    register_setting("section", "logo", "handle_logo_upload");
}

add_action("admin_init", "display_theme_panel_fields");

Here, we’re using wp_handle_upload to store the image file and retrieve its URL and store it as a option.

Here’s how our settings page looks now, it’s shaping up nicely!

Settings API Logo Example

Retrieving Settings

A theme needs to retrieve the setting values on the front end. The Settings API internally stores the values using the Options API. Therefore, you can retrieve the values using get_option() function.

It’s quite simple, here’s the code.

<?php

$layout = get_option('theme_layout');
$facebook_url = get_option('facebook_url');
$twitter_url = get_option('twitter_url');

Conclusion

In this article we saw how we can easily create a theme settings page using the Settings API. We created a text, file and checkbox input fields to take input in various data formats. Go ahead and try to expand the page and add more form controls yourself.

  • A rather useless tutorial for theme developers now given the news in the link pethaps a current article on the customizer would be a good follow up? – http://wptavern.com/wordpress-org-now-requires-theme-authors-to-use-the-customizer-to-build-theme-options

  • mt

    This article is useless, as WordPress now requires themes to use the Customizer for implementing theme options:
    https://make.wordpress.org/themes/handbook/review/required/#options-and-settings

    • Colin

      I must agree, this is a poorly written tutorial. The example code does not function as described. The logo doesn’t save, and the some of the code snippets are mutually exclusive. Very disappointing…

  • Yes the post will useless according to wp theme reviewer decision, still this post gives basic idea , how to work with setting api.

  • In the 1st paragraph I have clearly mentioned that the same steps applies for creating a settings page for a plugin.

    Other marketplaces haven’t yet forced the use of Customizer therefore a lot of new themes of Themeforest, Creative Market etc are still using the settings api to implement settings page.

    For example: A drag and drop theme cannot implement its settings using Customizer it has to create settings page.

    Hope you understood the use of this tutorial. Thanks.

    • bader

      narayan can you help us with how to create theme option to create different layouts i.e one column , two columns or tree columns layouts ?

  • Please read my above comment. Anyways I will soon come up with an tutorial on implementing theme settings using customizer api.

  • bader

    please can you help us how to create theme option to create different layouts i.e one column , two columns or tree columns layouts ?

    • Add select box in options page with your layout options, Create grid based layout in your front end, you can also use bootstrap. According to select box value you can set layout in your frontend.

  • Great stuff. Thanks.

    Wouldn’t it be nice if WP had a standard / universal way for generating form elements (e.g., text, textarea, checkbox, etc? I mean, each element is really a collection of args that just so happen to get rendered as a string. Doing such things with code (e.g.):

    <input type="text" name="twitter_url" id="twitter_url" value="” />

    feels dated at best.

    I’m not talking about something like CMB2 (which is a great tool), but simply a standard form element generator. Given the ends is always the same (i.e., a checkbox is a checkbox is a checkbox) the means shouldn’t be in the hands of each dev (more or less reinventing the wheel).

  • simon codrington

    Good article @pnarayanprusty:disqus. Don’t listen to the various complains that ‘this is useless because of X’

    Creating settings pages / administration sections like this is still mainstream and will be for some time (until absolutely all of the markets and sites that sell theme move to the customiser implementation)

    Having a good grasp on how to add these sections and work with them is still important to theme development.

  • JoaoReynolds

    Based on the author’s comments here, the title of this article should be changed to “How to create a settings page for a plugin”. It is the wrong way (and quite outdated now) to implement a theme settings page as mentioned in the comments here. Also, the tutorial is incomplete – it doesn’t explain the options.php file (so if you follow the tutorial, you’ll get a php error since the options.php file is missing).

    For others: WordPress has GREAT instructions on how to setup custom theme settings using the customizer: https://codex.wordpress.org/Theme_Customization_API

    VERY easy to follow, much easier and less code than the tutorial here.

  • Prav

    Hey this article was good one. But I did all correctly. but only checkboxes are not getting saved any idea why it is not getting updated

  • गणेश ठाकुर

    logo image is not being uploaded…please tell what’s wrong in logo upload?

  • lovish bishnoi

    Not able to get image url using wp_handle_upload please help !!!!!

  • Sam

    Thanks Narayan this helped me a lot with my basic understanding of settings pages. Although I will be doing further research into the use of Customizer as mt, @epakrat:disqus and @disqus_bKlou3Zxjp:disqus have suggested.

  • wow, thanks you make creating a options page for a theme a very easy.

  • Himanshu

    can we have reset button here to remove all the settings values which we have filled in

  • brodster

    how do you display setings_fields on the front page

    settings_fields(“section”);
    do_settings_sections(“theme-options”);
    submit_button();

  • Geez, this tutorial could have been written much better. The sections of code that are laid out for us might be solid, but we don’t exactly know where each code block belongs.

  • You have this on github?

  • How comes am not able to save the logo, Is there any mistake in the code?

  • As others have said, this tutorial doesn’t exactly work as one would expect. For example, with the file uploader the given form would never work as intended. The form code needs to be

    Where enctype=”multipart/form-data” is an essential to getting file uploads to work.

  • asd

    Very good tutorial..But please help in logo uplode..It is not working in my..

  • is not working…

  • Mike D

    This was very helpful to create a basic options page for my plugin. Thanks for posting!

  • Γιάννος Κάλφα

    Food for thought article. I believe there is a disadvantage. It is better for the user to be able to choose a media file from wordpress media manager than just upload a file from its desktop.

  • Matt
  • Allef Decharts Braga

    Like leaving functional for all users ?

  • Jeyaseelan

    It is very useful and i have created custom menu as per above
    Thank You

  • Hossein Marzban

    for logo issue and fix it, change the code like below:

    function handle_logo_upload()
    {
    global $option;
    if($_FILES[“logo”][“tmp_name”])
    {
    $urls = wp_handle_upload($_FILES[“logo”], array(‘test_form’ => FALSE));
    $temp = $urls[“url”];
    return $temp;
    }

    return $option;
    }

    this code, get back url of the logo, then you can put it in img tag “src” to display.

  • Muhammed Athimannil

    How can I upload svg file ?

  • Helpful tutorial. Have a Creating Section, Setting, Control but not Output Settings Values (). Please explain write tutorial.

  • suraj sudhera

    I am fairly new to wordpress can help someone help me figure out what should i use to make a themes options panel. Customizer Api or Setting Api ?

    • maniix

      Don’t bother with WordPress. WordPress is fucking shit and it’s a complete waste of time to learn, trust me.

  • maniix

    This is outdated shit, please remove this.

    • Great idea lets remove everything from the web that is outdated. How about you press the bloody button to make that happen and may you rest in piece when you are hunted for your crimes against humanity.

      Seriously people, we need good tutorials for old ways so that we can understand not just what has been done in thousands of existing plugins but why it has been done the way it has. As in, it was and for many, still is the way.

  • Daniel Bier

    Thanks, works perfectly, I don’t need an image.

  • Dilantha Prasanjith

    Well this is a good article. I saw arguments are a bit old. But if some one wants to stick with customizer API they are quite free to use it.But I found settings API quite handy yet in some cases. Thanks for the nice article.

    • Gaëlle Rauffet

      I agree. When you develop your own theme it can be usefull to use Settings API. What is interesting with the development is to have several choices

  • This article is sooooo not useless. Usage of the customizer isn’t a strict requirement because it may not be the best choice. What if I wanted to make a plugin that uses it’s own menu item and page with a set of non-standard elements we wouldn’t find in the customizer? An image gallery comes to mind. I can still use the settings api to store data, and retrieve it using the functionality introduced in this article. The point here is that WordPress is not as restrictive as some people would like to believe.

Recommended
Sponsors
Get the latest in WordPress, once a week, for free.