I have been attempting to create a theme reset button for the theme customizer that automatically removes all of the theme_mod settings. I have tried multiple ways to do this and have never been able to get it to work. As seen here.

After multiple failed attempts using the remove_theme_mods approach I begin to wonder if that is my problem other than the ajax and javascript being faulty and not properly binding the button.

Since I save all defaults into one big array so when my theme is installed it automatically has values populated on the theme customizer page, and the theme has a specific look... I was thinking I could try a different approach to instead remove the theme settings I just over ride them, maybe with a custom control? Possibly by somehow assigning these default values to all settings? I really hope someone can help me get this going. If you have any ideas I would appreciate it very very much.

Here is an example of how I assign the default values for the theme:

function newtheme_get_theme_mods() {

$defaults = array(

        'newtheme_responsive'                 => true,

        'newtheme_hero_title'                 => 'Beautiful and Elegant',

        'newtheme_hero_description'           => 'The best theme in the world',

                'newtheme_header_logo'                => '/wp-content/themes/newtheme/img/logo.png',

                'newtheme_header_background_color'    => 'rgba(35,35,35, 0.9)'

    return $defaults;


4 Answers 4


There is a function called remove_theme_mods that will kill all theme mods. Beware, however, that this will not only remove the mods that you have defined in your theme using the customizer API. It will also target other mods, such as the menu locations. Widget positions are currently defined as options, not as mods, but this may change in the future. WordPress is likely to move more stuff from options to mods, making remove_theme_mods all the more dangerous to use.

The best approach is to arrange all mods that belong to the theme proper in an array. You can then loop through that array and remove the individual mods with remove_theme_mod.


The problem with using remove_theme_mods for showing defaults in the Customizer is

  • the Customizer is a preview which you can exit without saving,
  • the individual theme_mods are filtered, but not the entire theme_mod array,
  • theme_mods includes menus and widgets.

I also wanted a reset button, but I chose instead to create a Preset control, and one of the presets is "defaults". This way uses a select, so there is no problem with the button not working (because bind is for value changes and buttons don't change their values).

The trick is to use ajax to retrieve the chosen preset, and then loop over the values in javascript, assigning them to the settings so that those changes will trigger the refresh of the preview. My code includes filters so that child themes can add in more options and presets. And the presets can be subsets of the options available.

Here is PHP for the Preset control (just a normal select, but a settingless control):

$wp_customize->add_control( 'option_presets', array(
    'label'    => __( 'Use preset theme options', 'mytheme' ),
    'description' => __( 'Theme options will be set to the preset values.', 'mytheme' ),
    'section'  => 'mytheme_section',
    'settings' => array(),
    'type'     => 'select',
    'capability' => 'edit_theme_options',
    'choices'  => mytheme_option_presets_choices(),
) );

Here is the rest of the PHP functions.

 * Supply list of choices for option presets.
function mytheme_option_presets_choices() {
    return apply_filters( 'mytheme_option_presets_choices', array(
        'none' => __( 'Select preset', 'mytheme' ),
        'defaults' => __( 'Defaults', 'mytheme' ),
        'dark' => __( 'Dark', 'mytheme' ),
    ) );

 * Sanitize an option preset choice.
function mytheme_sanitize_option_presets_choice( $input ) {
    $valid = mytheme_option_presets_choices();
    return array_key_exists( $input, $valid ) ? $input : 'none';

 * Get the preset values for the chosen option preset.
function mytheme_option_preset( $which ) {
    $values = array();
    if ( 'defaults' === $which ) {
        $values = mytheme_default_values();
    if ( 'dark' === $which ) {
        $values = array(
            'body_textcolor' => '#f9f7f7',
            'background_color' => '#444244',
            'header_textcolor' => '#bf9a07',
            'area_classes' => array(
                'sidebar' => 'semi-black',
                'widgets' => 'box',
    return apply_filters( 'mytheme_option_preset', $values, $which );

 * Add a nonce for Customizer for option presets.
function mytheme_refresh_nonces( $nonces ) {
    $nonces['mytheme-customize-presets'] = wp_create_nonce( 'mytheme-customize-presets' );
    return $nonces;
add_filter( 'customize_refresh_nonces', 'mytheme_refresh_nonces' );

 * Ajax handler for supplying option preset values.
function mytheme_ajax_option_preset_values() {
    check_ajax_referer( 'mytheme-customize-presets', 'option_presets_nonce' );
    if ( ! current_user_can( 'edit_theme_options' ) ) {
        wp_die( -1 );

    if ( empty( $_POST['option_preset'] ) ) {
        wp_send_json_error( 'mytheme_missing_preset_parameter' );
    $preset = sanitize_text_field( wp_unslash( $_POST['option_preset'] ) );
    $values = mytheme_option_preset( $preset );
    if ( empty( $values ) ) {
        wp_send_json_error( array( 'message' => __( 'No preset found.', 'mytheme' ) ) );
    else {   // Flatten the array.
        foreach ($values as $key => $avalue) {
            if ( is_array( $avalue ) ) {
                unset( $values[$key] );
                foreach ($avalue as $subkey => $subvalue) {
                    $values[$key . '[' . $subkey . ']'] = $subvalue;
        wp_send_json_success( array( 'values' => $values ) );
add_action( 'wp_ajax_mytheme_option_preset', 'mytheme_ajax_option_preset_values' );

And then just a little bit of Javascript to make the ajax request. This is queued on the 'customize_controls_enqueue_scripts' action. (I left out the display of the error message.)

wp.customize.control( 'option_presets', function( control ) {
    control.element = new wp.customize.Element( control.container.find( 'select' ) );
    control.element.bind( function( preset ) {
        var request = wp.ajax.post( 'mytheme_option_preset', {
            option_presets_nonce: wp.customize.settings.nonce['mytheme-customize-presets'],
            wp_customize: 'on',
            customize_theme: wp.customize.settings.theme.stylesheet,
            option_preset: preset
        } );
        request.done( function( response ) {
            _.each( response.values, function( value, id ) {
                var setting = wp.customize( id );
                if ( setting ) {
                    setting.set( value );
            } );
        } );
    } );
} );

So in your theme setting page do something like this:

if( isset( $_REQUEST['resetl_all'] ) ){
    call_reset_function(); // or newtheme_get_theme_mods function (I guess)                      
  • Thank you for the suggestion. I attempted to change the remove theme mods to your suggestion of the function that returns the defaults, and I still am having the same issue. So I am starting to think that maybe the issue really is that the button isn't binding to the function properly. I still can not get it to bind properly so I think I am just going to give up on this feature all together. May 16, 2013 at 20:45
  • try to print something when button pressed lilke if(isset($_REQUEST['button_name'])){echo 'button clicked';}
    – Core
    May 17, 2013 at 9:48
  • If you are using bind, it won't get triggered, since that is only for value change and there is no value changing when a button is clicked. Mar 18, 2018 at 0:24

this will removes all of the theme_mod settings

function reset_newtheme_options() { 
  • 2
    Some explanation would be great. Jun 23, 2015 at 11:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.