I'm using the JS & PHP code displayed below to add a customizer setting dynamically. I know that saving the setting works because when I echo get_theme_mod('mySetting') within a theme template file, the saved value is returned. However, after a browser refresh within the customizer, the input does not display the saved value but rather the value used when the setting is instantiated (JS Default Value?). What am I doing wrong?

Note: Please read first comment as well.

// JS enqueued via action hook: customize_controls_enqueue_scripts
(function( $, api ) {
api.bind( 'ready', function() {

    var section = new api.Section( 'my-section', {
        title           : 'Dynamic Setting Section',
        priority        : 1,
        customizeAction : 'Customizing'

    var setting = new api.Setting( 'mySetting', 'JS Default Value?' );

    var control = new api.Control( 'my-control', {
        type    : 'text',
        section : 'my-section',
        setting : setting

    api.section.add( section );

    api.add( setting );

    api.control.add( control );

})( jQuery, wp.customize );

As explained by Weston Ruter in more detail here and here, dynamically created settings must also be registered in PHP because:

In order for a setting to be safely stored it must be sanitized and validated by the server. Relying on client-side sanitization and validation is dangerous.

add_filter( 'customize_dynamic_setting_args',function( $setting_args, $setting_id )
    if ( 'mySetting' == $setting_id ) {
        $setting_args = array(
            'transport'         => 'postMessage',
            'default'           => 'PHP Default Value!',
            'sanitize_callback' => 'wp_strip_all_tags',

    return $setting_args;
  • It appears that the 2nd parameter within api.Setting() needs to be the current value retrieved via get_theme_mod and send to JS via wp_localize_script. I just assumed that the functionality for getting values from the DB was baked-in. Thoughts?
    – Marc Wiest
    Commented Jun 13, 2018 at 0:01

1 Answer 1


When you register the setting in JS, you need to supply the current value saved in the DB as the value, not some default value. So instead of:

var setting = new api.Setting( 'mySetting', 'JS Default Value?' );

You would need to obtain the value via some means like the REST API and then use it when instantiating. You also need to provide the transport. So it would look like this:

var setting = new api.Setting( 'mySetting', someResponse.value, { transport: 'postMessage' } );

Here are some examples of doing this:

Your Answer

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

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