Thursday, March 13, 2025

Guide To Using The WordPress Theme Customization API

What is the theme customization API?

The WordPress theme customization API allows you to easily create custom theme configuration options that can be changed through the WordPress admin panel. It refers to the configuration options that can be found under the Appearance > Customize  page in the menu. This page is convenient and easy-to-use, both from the users’ and developers’ viewpoint. Developers can use pre-existing classes and functions to quickly make the theme more customizable, while users can have a single customization page with all the theme options that can be live previewed before saving them.

Creating custom configuration fields

The first step when working with the theme configuration API is to create a function that will be hooked to customize_register action. To do that, create a new file (called e.g. theme-settings.php) in your theme’s root directory and add the following code:

<?php
/**
 * @param WP_Customize_Manager $wp_customize
 */
function mys_customize_register($wp_customize)
{
    
}
add_action('customize_register', 'mys_customize_register'); 

$wp_customize is an instance of WP_Customize_Manager class, that contains built-in methods that handle the creation of custom settings and corresponding form fields. These methods are add_setting(), add_section() and add_control().

The Add_Setting() function is used to add a new theme setting. In this example, you will add four custom settings:

/**
 * @param WP_Customize_Manager $wp_customize
 */
function mys_customize_register($wp_customize)
{
    $wp_customize->add_setting('header_title');
    $wp_customize->add_setting('header_subtitle');
    $wp_customize->add_setting('intro_text');
    $wp_customize->add_setting('featured_post');
}

Each setting can have additional options, such as the default value, access control and input sanitization:

/**
 * @param WP_Customize_Manager $wp_customize
 */
function mys_customize_register($wp_customize)
{
    $wp_customize->add_setting('header_title', array(
    	// Set default value for this setting
    	'default' => 'Lorem ipsum',

    	// Edit theme option is the default capability
    	// You can change this if you want to customize access control to this setting
    	// Read more about roles and capabilities here: https://codex.wordpress.org/Roles_and_Capabilities
    	'capability' => 'edit_theme_options',

    	// This will call sanitize_header_title function instead and save its value
    	// In this example, it will capitalize the first letter of the title
    	'sanitize_callback' => 'sanitize_header_title'
    ));
    
    $wp_customize->add_setting('header_subtitle');
    $wp_customize->add_setting('intro_text');
    $wp_customize->add_setting('featured_post');
}
add_action('customize_register', 'mys_customize_register');

function sanitize_header_title($title) {
	return ucfirst($title);
}

All settings must belong to a certain section. A section is a group of settings that is added using the add_section() function:

$wp_customize->add_section('mys_general_section', [
    // Section name
    'title' => 'General settings',

    // Section ordering - setting this to 1 will make this section the first in the list
    'priority' => 1
]); 

There are a few predefined sections to which the settings can be added. These are:

  • title_tagline – Site Title & Tagline
  • colors – Colors
  • header_image – Header Image
  • background_image – Background Image
  • nav – Navigation
  • static_front_page – Static Front Page

However, the settings will still not appear on the theme customizer page. You have to create a control (i.e. form field element) for each setting and assign it to a desired section using add_control()  function:

$wp_customize->add_control('mys_header_title_ctrl', [
        'label' => 'Header Title',

        // Assign form field element to the desired section
        'section' => 'mys_general_section',

        // Connect form field element to the corresponding setting
        'settings' => 'header_title',
        'type' => 'text'
    ]); 

For the setting from above, form field type is set to text. However, other types are also available:

  • text
  • checkbox
  • radio
  • select
  • textarea
  • dropdown-pages
  • email
  • URL
  • number
  • hidden
  • date

Some of these types accept additional configuration arguments. For example, if form field type is selected, then you need to specify which options will appear in the dropdown:

$pages = get_posts([
        'nopaging' => true,
        'post_type' => 'page',
        'post_status' => 'publish'
]);

$page_ids = array_map(function($el) {
        return $el->ID;
}, $pages);

$page_names = array_map(function ($el) {
        return $el->post_title;
}, $pages);


$wp_customize->add_control('mys_featured_post_ctrl', [
        'label' => 'Featured Post',
        'section' => 'mys_general_section',
        'settings' => 'featured_post',
        'type' => 'select',
        'choices' => array('' => '') + array_combine($page_ids, $page_names)
]); 

Finally, don’t forget to include the theme settings file in functions.php:

require_once __DIR__ . '/theme-settings.php'; 

You can now show the values of these settings anywhere in the theme:

echo get_theme_mod('header_title'); 

Wrapping it up

Full code of the theme customization function would look like this:

/**
 * @param WP_Customize_Manager $wp_customize
 */
function mys_customize_register($wp_customize)
{
    $wp_customize->add_setting('header_title', array(
    	// Set default value for this setting
    	'default' => 'Lorem ipsum',

    	// Edit theme option is the default capability
    	// You can change this if you want to customize access control to these particular setting
    	// Read more about roles and capabilities here: https://codex.wordpress.org/Roles_and_Capabilities
    	'capability' => 'edit_theme_options',

    	// This will call sanitize_header_title function instead and save its value
    	// In this example, it will capitalize the first letter of the title
    	'sanitize_callback' => 'sanitize_header_title'
    ));

    $wp_customize->add_setting('header_subtitle');
    $wp_customize->add_setting('intro_text');
    $wp_customize->add_setting('featured_post');

    $wp_customize->add_section('mys_general_section', [
    	// Section name
        'title' => 'General settings',

        // Section ordering - setting this to 1 will make this section the first in the list
        'priority' => 1
    ]);

    $wp_customize->add_control('mys_header_title_ctrl', [
        'label' => 'Header Title',

        // Assign form field element to the desired section
        'section' => 'mys_general_section',

        // Connect form field element to the corresponding setting
        'settings' => 'header_title',
        'type' => 'text'
    ]);

    $wp_customize->add_control('mys_header_subtitle_ctrl', [
        'label' => 'Header Subtitle',
        'section' => 'mys_general_section',
        'settings' => 'header_subtitle',
        'type' => 'text'
    ]);

    $wp_customize->add_control('mys_intro_text_ctrl', [
        'label' => 'Intro Text',
        'section' => 'mys_general_section',
        'settings' => 'intro_text',
        'type' => 'textarea'
    ]);

    $pages = get_posts([
        'nopaging' => true,
        'post_type' => 'page',
        'post_status' => 'publish'
    ]);

    $page_ids = array_map(function($el) {
        return $el->ID;
    }, $pages);

    $page_names = array_map(function ($el) {
        return $el->post_title;
    }, $pages);


    $wp_customize->add_control('mys_featured_post_ctrl', [
        'label' => 'Featured Post',
        'section' => 'mys_general_section',
        'settings' => 'featured_post',
        'type' => 'select',
        'choices' => array('' => '') + array_combine($page_ids, $page_names)
    ]);

}
add_action('customize_register', 'mys_customize_register');

function sanitize_header_title($title) {
	return ucfirst($title);
}

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Popular Articles

Featured