Can I change a control’s transport in Customizer depending on the previewed page?

Yes, you can change the transport of a registered setting dynamically after the page loads. And actually the active_callback can be used in conjunction with JS to change the transport instead of causing the control to be hidden.

Assuming you have registered a control with the ID of excerpt_length, and you have registered a setting and control as follows:

$wp_customize->add_setting( 'excerpt_length', array(
    'transport'         => 'refresh',
    'sanitize_callback' => function( $value ) {
        return intval( $value );
    },
) );

$wp_customize->add_control( 'excerpt_length', array(
    'label'           => __( 'Excerpt length', 'example' ),
    'section'         => 'something',
    'type'            => 'number',
    'active_callback' => function() {
        // Admin check is for initial state in customize.php.
        return is_admin() || is_archive() || ( is_home() && ! is_front_page() );
    },
) );

Then you can enqueue some JS for the Customizer controls app (at customize_controls_enqueue_scripts) which overrides the behavior for when the active state changes, like so to toggle the setting’s transport when active state changes instead of toggling the visibility of control:

wp.customize.control( 'excerpt_length', function( control ) {
    control.onChangeActive = function( active ) {
        control.setting.transport = active ? 'refresh' : 'postMessage';
    };
} );

There’s other ways to do it, but this is probably the least amount of code.

Leave a Comment