How to Add Theme Options with the WordPress Customizer API

The WordPress Customizer (introduced in version 3.4) lets users preview theme changes in real time before saving. Adding your own options — colour pickers, text inputs, dropdowns — integrates them into this same live-preview workflow using the Customizer API.

Problem: How do you add custom theme options to the WordPress Customizer — for example, a colour picker or a text field — so they appear in the live preview panel?

Solution: Hook into customize_register and use $wp_customize->add_section(), add_setting(), and add_control() to register your options, then output them in the theme using get_theme_mod().

Register a section, a setting, and a control in the customize_register action:

add_action( 'customize_register', 'mytheme_customizer_settings' );

function mytheme_customizer_settings( WP_Customize_Manager $wp_customize ) {

    // Section
    $wp_customize->add_section( 'mytheme_colors', [
        'title'    => __( 'Theme Colors', 'textdomain' ),
        'priority' => 30,
    ] );

    // Setting + Control: accent colour
    $wp_customize->add_setting( 'accent_color', [
        'default'           => '#e74c3c',
        'sanitize_callback' => 'sanitize_hex_color',
        'transport'         => 'postMessage', // live preview without full refresh
    ] );

    $wp_customize->add_control(
        new WP_Customize_Color_Control( $wp_customize, 'accent_color', [
            'label'   => __( 'Accent Color', 'textdomain' ),
            'section' => 'mytheme_colors',
        ] )
    );

    // Setting + Control: footer text
    $wp_customize->add_setting( 'footer_text', [
        'default'           => '',
        'sanitize_callback' => 'sanitize_text_field',
    ] );

    $wp_customize->add_control( 'footer_text', [
        'label'   => __( 'Footer Text', 'textdomain' ),
        'section' => 'mytheme_colors',
        'type'    => 'text',
    ] );
}

Output the value in your template:

$accent = get_theme_mod( 'accent_color', '#e74c3c' );

// Inline CSS for live preview with postMessage transport
add_action( 'wp_head', function() use ( $accent ) {
    echo '<style>a { color: ' . sanitize_hex_color( $accent ) . '; }</style>';
} );

NOTE: Set transport => 'postMessage' only for settings that you handle with a JavaScript preview script — otherwise the preview panel won't update until the user saves. Use sanitize_hex_color for colour settings; WordPress provides it out of the box.