Extending WordPress – Customizing the Customizer

Introduction

There has long been a practice in themes including a theme settings page within the administrative dashboard. The customizer, which first appeared in [which??] has been intended as a place to centralize appearance-related settings. WordPress has since been encouraging use of the customizer over theme options pages.

The Customizer

Whither options pages?

WordPress for some time has been pushing theme-related settings into the customizer. In a recent release, a menus section was added to the customizer and it was announced that the separate menu management page would eventually go away, which caused a furor in the WordPress community. The WordPress team have been for some time encouraging uptake of the customizer as the place to handle theme settings.

The following screenshot shows what the customizer looks like out of the box with a freshly created theme (courtesy of Underscores).

Customizer out of the box

Building options pages is a manual process involving multiple steps, including writing out the needed markup manually and handling the save event to save out settings. The customizer offers an API which allows defining sections, settings, and controls (more on these later) and handles all the markup generation, saving of settings etc.

Now it’s time to look at an example of how to add sections and settings to the customizer.

Customizer Customization Implementation

Here’s a simple scenario: suppose that there is a need for a site owner to upload and select an image to use for the site header, with the option for an alternate version in the footer. In a one-off situation it might be acceptable to include these files in the theme and hardcode the references within the header and footer templates; however, this makes updates more involved than need be, requires code changes, and is not suitable for themes that might be distributed, so it makes sense to leverage the customizer.

It’s just a matter of leveraging the customizer API to add additional customizer sections and settings within. Fortunately, an Underscores-produced theme includes a stub function for leveraging the customizer, located in inc/customizer.php. This is where the example custom settings will go.

In inc/customizer.php:

function wordpress_customizer_example_customize_register( $wp_customize ) {
    // Create a new settings section.
    $wp_customize->add_section(
        'custom_customizer_logos',
        array(
            'title' => __( 'Logos', 'wordpress-customizer-example' ),
            'priority' => 30,
        )
    );

    // Add the header logo setting.
    $wp_customize->add_setting(
        'header_logo',
        array(
            'default' => '',
            'transport' => 'postMessage',
        )
    );

    // Add the header logo control.
    $wp_customize->add_control(
        new WP_Customize_Image_Control(
            $wp_customize,
            'custom_customizer_logos_header',
            array(
                'label' => __( 'Header Logo (replaces text)', 'wordpress-customizer-example' ),
                'section' => 'custom_customizer_logos',
                'settings' => 'header_logo', // Must match the setting name.
                'priority' => 1,
            )
        )
    );

    // Add the footer logo setting.
    $wp_customize->add_setting(
        'footer_logo',
        array(
            'default' => '',
            'transport' => 'postMessage',
        )
    );

    // Add the footer logo control.
    $wp_customize->add_control(
        new WP_Customize_Image_Control(
            $wp_customize,
            'custom_customizer_logos_footer',
            array(
                'label' => __( 'Footer Logo', 'wordpress-customizer-example' ),
                'section' => 'custom_customizer_logos',
                'settings' => 'footer_logo', // Must match the setting name.
                'priority' => 2,
            )
        )
    );
}
add_action( 'customize_register', 'wordpress_customizer_example_customize_register' );

The code is collected within a single function executed via the customize_register hook. The flow within the function is:

  • create a new settings section
  • create the header logo setting
  • create the header logo control, associate with the setting
  • create the footer logo setting
  • create the footer logo control, associate with the setting

Each setting has a two-step process: defining the setting, then defining the UI control to provide control over the setting. Note that in the latter case, the settings field must match the first parameter of the add_setting() function call in order for them to sync up, and the section field must match the name of the section, the first parameter of the create_section() call.

Checking the customizer again in a browser shows a new section titled Logos. Clicking into that reveals the following:

Customizer, updated

The above code snippet generated that interface. WordPress (via the customizer API) just uses the controls that have been specified, generates the markup, and handles the saving of settings. So it’s just up to the developer to add sections, settings, and controls.

The settings are saved as theme mods, so can be retrieved by name using the get_theme_mod() function. The name passed must match the setting name, ie. the first parameter of the add_setting() function call as shown above. As already outlined, the intent is to output the logos separately, typically in the header and footer templates, though this may differ based on the how the theme is set up.

In header.php:

<h1><?php if ( get_theme_mod( 'header_logo' ) ) : ?>
    <img src="<?php echo esc_url( get_theme_mod( 'header_logo' ) ); ?>" alt="<?php echo esc_attr( get_bloginfo( 'name' ) ); ?>">
<?php endif; ?></h1>

In footer.php:

<?php if ( get_theme_mod( 'footer_logo' ) ) : ?>
    <img src='<?php echo esc_url( get_theme_mod( 'footer_logo' ) ); ?>' alt='<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>'>
<?php endif; ?>

The markup snippets can of course be tailored to mesh with any existing. Perhaps to wrap the header link around that, and/or do text replacement, for example.

And the result:

The result

Pardon the logo usage, but I needed two different images for demonstration. These came from the WordPress logos page.

Here’s the source code for the example theme. All items of interest are in footer.php, header.php, and inc/customizer.php.

Conclusion

The WordPress team have been pressing theme developers to move their theme settings from custom settings pages into the customizer. This hasn’t been without controversy, but it does gather theme settings into a consistent location and with a consistent UI. As demonstrated, making use of the customizer is straightforward, involving a mild effort with adding code to leverage the customizer and updating templates accordingly. It also keeps the site management experience consistent and responsive with live refresh.

Further Reading