How to Create a Settings Page for Your WordPress Theme

You’re developing a WordPress Theme and you want to have an options page. Maybe you want to give a client the ability to manipulate specific pieces of information, such as a phone number, which when updated in the backend goes through your theme and updates the phone number in various places. I’ve used it for this, for editing different blocks of content on a homepage that doesn’t conform to simply “the_content”, and for setting up an ad system, such as with DoubleClick for Publishers, so that my clients can login and update the code required for their <head> section and the individual ad blocks.

I’ll walk you through exactly how to do that here, and keep it as simple as possible, as this is one area where WordPress still gets a bit complicated even to us seasoned professionals.

Code for your Functions.php

The first thing we’ll do is review the specific code you’ll need to add to functions.php. You could also add this as a plugin if you wanted it to work across themes, but for today’s purposes we’ll assume this stuff is very theme-specific and therefore more appropriate for functions.php.

function build_options_page() { ?>
<div id="theme-options-wrap">
<div class="icon32" id="icon-tools"> <br /> </div>
<h2>Theme Settings</h2>
<p>Update various settings throughout your website.</p>
<form method="post" action="options.php" enctype="multipart/form-data">
<?php settings_fields('theme_options'); ?>
<?php do_settings_sections(__FILE__); ?>
<p class="submit">
<input name="Submit" type="submit" class="button-primary" value="<?php esc_attr_e('Save Changes'); ?>" />
</p>
</form>
</div>
<?php }
add_action('admin_init', 'register_and_build_fields');
function register_and_build_fields() {
register_setting('theme_options', 'theme_options', 'validate_setting');
add_settings_section('homepage_settings', 'Homepage Settings', 'section_homepage', __FILE__);
add_settings_section('footer_settings', 'Footer Settings', 'section_footer', __FILE__);
function section_homepage() {}
function section_footer() {}
add_settings_field('button1text', 'Button 1 Text', 'button1text_setting', __FILE__, 'homepage_settings');
add_settings_field('button1link', 'Button 1 URL', 'button1link_setting', __FILE__, 'homepage_settings');

add_settings_field('button2text', 'Button 2 Text', 'button2text_setting', __FILE__, 'homepage_settings');
add_settings_field('button2link', 'Button 2 URL', 'button2link_setting', __FILE__, 'homepage_settings');

add_settings_field('button3text', 'Button 3 Text', 'button3text_setting', __FILE__, 'homepage_settings');
add_settings_field('button3link', 'Button 3 URL', 'button3link_setting', __FILE__, 'homepage_settings');
add_settings_field('phonenumber', 'Phone Number', 'phonenumber', __FILE__, 'footer_settings');
add_settings_field('facebookurl', 'Facebook URL', 'facebookurl', __FILE__, 'footer_settings');
add_settings_field('googleurl', 'Google+ URL', 'googleurl', __FILE__, 'footer_settings');
add_settings_field('twitterurl', 'Twitter URL', 'twitterurl', __FILE__, 'footer_settings');
}
function validate_setting($theme_options) {
return $theme_options;
}
function button1text_setting() {
$options = get_option('theme_options'); echo "<input name='theme_options[button1text_setting]' type='text' value='{$options['button1text_setting']}' />";
}
function button1link_setting() {
$options = get_option('theme_options'); echo "<input name='theme_options[button1link_setting]' type='text' value='{$options['button1link_setting']}' />";
}
function button2text_setting() {
$options = get_option('theme_options'); echo "<input name='theme_options[button2text_setting]' type='text' value='{$options['button2text_setting']}' />";
}
function button2link_setting() {
$options = get_option('theme_options'); echo "<input name='theme_options[button2link_setting]' type='text' value='{$options['button2link_setting']}' />";
}
function button3text_setting() {
$options = get_option('theme_options'); echo "<input name='theme_options[button3text_setting]' type='text' value='{$options['button3text_setting']}' />";
}
function button3link_setting() {
$options = get_option('theme_options'); echo "<input name='theme_options[button3link_setting]' type='text' value='{$options['button3link_setting']}' />";
}
function phonenumber() {
$options = get_option('theme_options'); echo "<input name='theme_options[phonenumber]' type='text' value='{$options['phonenumber']}' />";
}
function facebookurl() {
$options = get_option('theme_options'); echo "<input name='theme_options[facebookurl]' type='text' value='{$options['facebookurl']}' />";
}
function googleurl() {
$options = get_option('theme_options'); echo "<input name='theme_options[googleurl]' type='text' value='{$options['googleurl']}' />";
}
function twitterurl() {
$options = get_option('theme_options'); echo "<input name='theme_options[twitterurl]' type='text' value='{$options['twitterurl']}' />";
}
add_action('admin_menu', 'theme_options_page');
function theme_options_page() { add_options_page('Theme Settings', 'Theme Settings', 'administrator', __FILE__, 'build_options_page');}

Whoa, pretty big chunk of code there doing various things. You could simply add that to your functions.php and be done with it. You’d get the following under Settings > Theme Options:

screen shot of the results of our code thus far
Our new Theme Options Page

Let’s dissect the code above though so you can see what we’re doing and how you can modify things to your liking.

First we start by creating the function that will house all of this.

function build_options_page() {

Then we add to that function the stuff that makes up a typical WordPress page.

<div id="theme-options-wrap">
<div class="icon32" id="icon-tools"> <br /> </div>
<h2>Theme Settings</h2>
<p>Update various settings throughout your website.</p>
<form method="post" action="options.php" enctype="multipart/form-data">
<?php settings_fields('theme_options'); ?>
<?php do_settings_sections(__FILE__); ?>
<p class="submit">
<input name="Submit" type="submit" class="button-primary" value="<?php esc_attr_e('Save Changes'); ?>" />
</p>
</form>
</div>
<?php }

The icon-tools class just adds WordPress’ Hammer & Screwdriver icon, a fitting one for a settings page I suppose. You can change the contents of the <h2> section to suit your needs, as well as the following <p> tag. In fact, you could add just about anything wanted above the opening form.

Within that form, we then have <?php settings_fields('theme_options'); ?>, which, along with the do_settings_sections line below it, pulls in the values and sets up the framework to start showing off our fields.

The next two lines ensure our code will be run everytime a user loads up WP-Admin.

add_action('admin_init', 'register_and_build_fields');
function register_and_build_fields() {

admin_init basically fires off some code before any other hooks are triggered, and must be tied to a specific function. In our case, the register_and_build_fields function. Let’s look at the various lines inside of that function.

register_setting('theme_options', 'theme_options', 'validate_setting');

This tells WordPress to, you guessed it, register the settings we’re about to setup. It doesn’t do much on it’s own though, we need a bit more code:

add_settings_section('homepage_settings', 'Homepage Settings', 'section_homepage', __FILE__);

Here we create an entire section for our settings. In the full code above, I’ve created two sections, one for “Homepage Settings” and another for “Footer Settings”. These are displayed on the same page, just in two different visual sections on the page.

The initial homepage_settings will be used later, when we create fields, to tell those fields which section to hang out in. The next parameter is the displayed text for that section. The third parameter is the “callback”, essentially, the name of the associated function which will fire this off. Finally, we use the __FILE__ to simply tell WP that we want this to happen on the page we’re working with.

Next up we just make the function to trigger the callback mentioned above.

function section_homepage() {}

Now that we’ve got the page setup and a section created, we’re ready to start creating our various fields. There are two steps to this, the first being to use add_settings_field to define our various fields. Below I’ve defined a button1text field and a button1link field, which could allow an admin to enter some text and a URL, to then be used on the front end to display a button. More on displaying these options later.

add_settings_field('button1text', 'Button 1 Text', 'button1text_setting', __FILE__, 'homepage_settings');
add_settings_field('button1link', 'Button 1 URL', 'button1link_setting', __FILE__, 'homepage_settings');

The first parameter of add_settings_field is the ID of the field itself. The next parameter defines the fields’ label. The third parameter is the callback which we’ll use in the next step. Again, we then tell it to use __FILE__ to say “we’re talking about the page in question”, and finally, we tell WordPress which section, homepage_settings, of this page to add the field to.

Next up, we start creating the actual inputs and textareas to be displayed on the settings page. The following creates a text input with the value being set to whatever button1text was previously saved as. Initially it will be blank, but once an admin saves some content, it’ll be prepopulated from their on out.

function button1text_setting() {
$options = get_option('theme_options'); echo "<input name='theme_options[button1text_setting]' type='text' value='{$options['button1text_setting']}' />";
}

See our button1text_setting callback in there? We set that with add_settings_field above.

If you’d prefer to instead have a textarea, give this a go:

function button1text_setting() {
$options = get_option('theme_options');
echo "<textarea rows='10' columns='25' name='theme_options[button1text_setting]'>{$options['button1text_setting']}</textarea>";
}

You can create as many of those as you’d like, of course, but remember that to create any one individual setting, you need both the add_settings_field to define everything, and then a function with that settings callback to create the output that admins will see.

One final step gets us all up and running here:

add_action('admin_menu', 'create_theme_options_page');
function create_theme_options_page() { add_options_page('Theme Settings', 'Theme Settings', 'administrator', __FILE__, 'build_options_page');}

Essentially, we just tell WordPress, do us a solid and add this page to the Admin area.

Code to Display it all on the Front End

Now that we’ve got a settings page up and running that actually works, let’s look at how to display settings on the front end of the site, which is considerably simpler now that we’ve prepped everything in the backend correctly.

First we create a variable that gets jam packed with all of our settings information:

<?php $options = get_option('theme_options'); ?>

Then we can use it in real world scenarios. Remember how we were setting button1link_setting and button1text_setting above? Now we can spit those out into an anchor tag and create a custom link that admins can define.

<a href="<?php echo $options['button1link_setting']; ?>"><?php echo $options['button1text_setting']; ?></a>

Creating settings pages is, maybe after plugin creation, one of the trickier aspects of working with WordPress, but stick to the game plan above and you’ll be thanking yourself later when your clients need to be able to globally change phone numbers or want to have a bunch of different content sections on the homepage.

Up Next: Numbered Tabs with Liquid Slider