Build a Better WordPress Theme with the Settings API

August 20, 2015

Often when we create our WordPress themes, they come with a small theme options page built using the Settings API. This page could have inputs for everything from social media handles to uploading a new logo or picking a homepage layout. Having these options makes it easier for non-developers to make important changes to their websites, or give it minor refreshment.

Here’s a pretty straightforward example of how we use it on Chasing the Dream. Administrators can update the links for social media icons, enter the unique Google Custom Search Key, pick a homepage grid, and even update the footer text.


Having a theme options page is a good way to set global options, such as a font or accent color. Instead of having to find all of the places within the CSS every time a client wants to try a different shade of blue, instead they can have the power to update it themselves.

Where to Start

We always start with a boiler plate options page that includes the following:

  • Homepage Layout
  • Social Media Icon URLs (Facebook, Twitter, and Instagram)
  • API Keys
  • Footer Text

Other common options include a color picker for the accent color and links, choice of overall theme colors, a banner image uploader, and post layout choices. For the most part, these are purely aesthetic, but they do have to be considered in the overall development of a theme. For example, if you want to users to upload a logo, that logo will live within certain parameters. As much flexibility as can be had for administrators is great, but it’s also ok to give parameters (such as the best ratio for the image size) that will lead to less development.

What is the Settings API?

In brief, the Settings API allows admin pages to have fields for customizing the way your WordPress theme works, both on the front-facing website and within the admin itself. Settings pages have fairly strict requirements to protect your theme; users need to be administrators (or in a WordPress Network setup, Super Admin) to submit changes.

Create the Settings Page Menu Item

At the moment, you would not be able to access the theme settings. You can choose to have the page appear as a subpage within Settings or as it’s own menu item. It should be easy for admins to access the settings page and make changes, so we’re going to go with a separate, top-level menu item. Here’s the code:

function add_theme_menu_item() {
    add_menu_page("Theme Customization", "Theme Customization", "manage_options", "theme-customizer", "theme_customizer_page", null, 99);
add_action("admin_menu", "add_theme_menu_item");

theme-customizer is the unique ID representing our menu item. theme_customizer_page is the callback for displaying the content of the page created by the Menu API. manage_options tells WordPress to save the results in the Options table of your database. This way, the information you save on your settings page can be accessed throughout the theme.

Register Settings

It’s important to remember that all of the options created could affect the overall performance of the site. Be sure that nothing will break if these options are never touched or changed with fallbacks in the PHP.

There are two parts to adding new settings to a settings page: adding the option and registering those settings. You can declare the settings you intend to use as well as any default information in the case that the administrator doesn’t have time or doesn’t want to customize the theme. It is important to be aware of these settings when building your theme, and that not every administrator will visit this settings page. Be careful that if your theme does rely on particular information from the settings page, there must be a default so that the theme doesn’t break out of the box.

function awtheme_register_settings() { 
 //Declare all options and if applicable, the default information
 add_option( 'aw_social_facebook', '');

 //Register these settings with the theme page
 register_setting( 'awthemesettings', 'aw_social_facebook'); 
add_action( 'admin_init', 'awtheme_register_settings' );

In this code, I’ve declared an input for the URL to a Facebook page. After the admin panel is initialized, we’re registering the sections and fields display callbacks. Here we’re using two important functions:

  • add_option is used to declare the settings as well as any inherant values.
  • register_setting is called to automate saving the values of the fields.

To add more settings to your page, you simply duplicate those lines of code along with different option names. Instead of aw_social_facebook use aw_social_twitter to add an option and register and input for a Twitter URL or username. awthemesettings connects the various settings fields to each other. For peace of mind, I suggest you register all of your settings with the same settings name so you just have to declare the settings once.

Some developers prefer to use setting sections, but this way, we have better customization of what those options look like within the form.

Speaking of which…

The Settings Form

At the most basic level, this is a theme customizer page:

function theme_customizer_page() {
        <div class="wrap">
        <h1>Theme Options</h1>
        <form method="post" action="options.php">

We’ve registered the settings_fields with the ID awthemesettings. The submit_button() function echoes the submit button, allowing the theme options we create to be saved. As you may have noticed, I prefaced the settings_field label (as well as the options, and various other parts of the code) with my initials to identify who built the page as well as to lessen the likelihood that it will interfere with other plugins or functions.

If that was the only code called for, there wouldn’t actually be a way to update the settings! It’s important to think about how you want the settings to be input and used within the theme. Does it make sense to input custom text? Is the setting a choice for how a certain layout will look?

It’s now time to create the input for the Facebook page option we registered earlier. It makes the most sense to create a simple text input, as we plan on using the full page URL to link out a Facebook icon from the homepage to our fan page.

<!-- social media -->
  <div class="postbox" >
   <h3>Social Media</h3>
    <label for="aw_social_facebook">Facebook URL:</label><br>
    <input type="text" id="aw_social_facebook" name="aw_social_facebook" value="<?php echo get_option('aw_social_facebook'); ?>" /><br><br>

  <!-- end social -->

I’ve wrapped the option in a div so that social media can be separate from homepage options, footer options, etc.

By declaring get_option() in the input’s value, once the option has been saved, you’ll be able to see and edit it directly within the input. Though while text inputs are generally the simplest, you can use the entire array of form inputs to save your data.

For one project, Chasing the Dream, the site administrators wanted two different homepage options: one with heavy customization and one that would simply auto-populate. For this choice, it was important to build the options into the theme and use a simple select.

<!-- homepage layout -->
  <div class="postbox" >
   <h3>Homepage Layout</h3>
    <label for="aw_homepage_format">Layout:</label><br>

    <?php $selected = ' selected'; ?>
    <?php $hp_type = get_option('aw_homepage_format'); ?>
    <select name="aw_homepage_format">
     <option value="1"<?php if ( $hp_type == '1') echo $selected; ?>>Standard Grid</option>
     <option value="2"<?php if ( $hp_type == '2') echo $selected; ?>>Dynamic Grid</option>

  <!-- end homepage layout -->

In this select there are two options of grids. The values saved are “1” and “2”, instead of “standard” and “dynamic”. When using those theme options, refer to the value of the option to get the result you’re looking for.

Using Theme Options

Now that you have all of these special theme options saved, it’s time to put them to work. Getting that data and putting it to work is simple. Here’s what your index.php could look like:

  $hpformat = get_option('wnet_homepage_format'); //get the option saved in the theme
  if ($hpformat == 1) {
     get_template_part( 'home/home-standard', 'view' ); } //if option one, show this page
  else if ($hpformat == 2) {
     get_template_part( 'home/home-dynamic-grid', 'view' ); } //if option two, show this page
  else {
     get_template_part( 'views/homepage/homepage', 'view' );} //just in case something is broken, default

First, get the option from the options table using get_option(), the same function which is used to display the results within the settings page itself. Depending on which option is surfaced, get the corresponding homepage template.


For those of you just looking for the full code block to build a theme options page without having to go through step-by-step (plus some additional styling information), here you go:

Resources and Thanks

Hat tip to New Relic, who helped me create my first theme options page.

Digital at The WNET Group is not responsible for your or any third party’s use of code from this tutorial. All the information on this website is published in good faith “as is” and for general information purposes only; WNET and IEG make no representation or warranty regarding reliability, accuracy, or completeness of the content on this website, and any use you make of this code is strictly at your own risk.