I have a theme with an option for setting the excerpt length for generated excerpts. Is there a way in the Customizer of conditionally changing the transport mechanism, depending on whether the preview page is showing excerpts?

For example, I have another option that controls whether full content or excerpts are shown on archive pages, but the search page always shows excerpts. So I would prefer to not incur the whole page refresh if no excerpts are being previewed, but if it's the search page or the other option is set to show excerpts, I would need to use refresh when the excerpt length is changed.

Or is this even worth the trouble of extra code?

2 Answers 2


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.

  • This solution implies that 1. The PHP active callback is run once, (on preview page load ?) 2. The JS onChangeActive function is run when the active value changes, and this code replaces the function that is normally run. I tested this (although using return is_archive() || is_search() || is_home()), and it does not override the default behavior. My control is not shown on any page, even if I start the Customizer from the front end on a post page. Commented Feb 11, 2018 at 17:35
  • @user43242 I forgot to include is_admin() in the condition. I just updated the answer. The active_callback gets called each time the preview refreshes or you navigate to another page in the preview. Commented Feb 11, 2018 at 17:52
  • It's true that this answer depends on the initial state being one where the state is active. So that is why the is_admin check has to be there, so that when it runs on customize.php is is initially true. Commented Feb 11, 2018 at 17:54
  • That one change made it work on both back end and front end! I don't understand why is_admin() is true on the front end, though. Commented Feb 11, 2018 at 19:19
  • The is_admin() check is only there to set the state while waiting for the preview to load for the first time. It is true because customize.php also runs all of the active_callback functions when it initializes. Commented Feb 11, 2018 at 19:21

I didn't find any solution for this. But I would suggest you to use active_callback parameter such that if another option that controls full content or excerpts shows full content and the page previewed is other than search page, hide the control that controls the excerpt length.

I guess this would be the better approach as you do want to show the relevent controls as per the previewed page.

  • I specifically do NOT want to use active_callback to hide the control, because it is always valid to set it. It always applies to the search page, and you shouldn't have to be on the search page to set it. I just didn't want to do a full refresh if it isn't needed. Commented Feb 7, 2018 at 19:41

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.