How can you create a custom message in the theme customizer sidebar?

Preferably at the top, under where you see the active theme title and the button to change themes.

Why: For a project, all of the customizer sections have been hidden, for various reasons. A user may expect to see controls here, so I'd like to place a message explaining what to do if they want to change something on the site.


To do what you ask there are two solutions that would be optimal.

Solution #1

The simplest way would would be to use the WordPress customizer's notification API - as this API was specifically designed to add messages to the customizer in a location that users can expect to see notifications from their theme, uniformly.

A global notification would be the most logical choice here based on your description. First you'll need to create a JS file to enqueue in the customizer. It's a good practice to also make sure you have your message translation ready, which can be done using wp_localize_script(). This code shows how to achieve adding your translated message and script:

function wpse313731_custom_notification_enqueue_scripts() {
    $handle = 'wpse313731-custom-notification';

    // Register the script.
    wp_register_script( $handle, plugins_url( "$handle.js", __FILE__ ), array( 'customize-controls' ) );
    // Translate the message.
    $translated_msg = array(
        'msg' => esc_html( 'This is a custom message being added to the WordPress Customizer.', 'your-text-domain' ),

    // Localize script with translated data.
    wp_localize_script( $handle, 'wpse313731', $translated_msg );
    // Enqueue the script.
    wp_enqueue_script( $handle );

This method should be fired when the customize_controls_enqueue_scripts hook is called, so we can add this code to do so:

add_action( 'customize_controls_enqueue_scripts', 'wpse313731_custom_notification_enqueue_scripts' );

Now for the JS we want to ensure the customizer is ready, and then call the notification API to add our custom notice. In the PHP code above, we told WordPress our script will be called wpse313731-custom-notification.js, so this example shows what the JS code in wpse313731-custom-notification.js would look like:

( function( $ ) {

    'use strict';

    wp.customize.bind( 'ready', function () {
            new wp.customize.Notification(
                'wpse313731-custom-notification', {
                    dismissible: true,
                    message: wpse313731.msg,
                    type: 'error'
    } );

} )( jQuery );

The above example JS code creates a dismissable error notification. The notice can be non-dismissable (meaning the user can't just close the message) if you just change the dismissable key false. Error notifications display with red on the side, but you can change type to 'none', 'error', 'warning', 'info', or 'success'.

This how each of those types are displayed for reference:

Notification Types

I went ahead and put this code in a gist so you can install the .zip plugin and test it out yourself, making any changes you would like to fit your needs.

Solution #2

The second solution would be to append the message to the area with JS. First you would want to create the template that contains the content you want to render like this for example:

function wpse313731_print_templates() {
    <script type="text/html" id="tmpl-wpse313731-custom-message">
        <p class="wpse313731-custom-message"><?php esc_html_e( 'This is a custom message being added to the WordPress Customizer.', 'your-text-domain' ) ?></p>

Then we need to make sure we add the method containing the template we want to render to be fired in the customize_controls_print_footer_scripts hook:

add_action( 'customize_controls_print_footer_scripts', 'wpse313731_print_templates' );

In JS you would want to wait for the panel to be ready and loaded, and then render your template with wp.template (make sure to not include the tmpl- part from the script ID above). Once this is done, we just need to append your custom message to the themes panel, which is the part that you're talking about adding a message under. It would look something like this:

( function( $ ) {
    'use strict';
    wp.customize.bind( 'ready', function () {
        wp.customize.panel( 'themes', function( panel ) {
            panel.deferred.embedded.done( function() {
                var customMessage;
                customMessage = $( wp.template( 'wpse313731-custom-message' )() );
                panel.headContainer.append( customMessage );
            } );
        } );
    } );
} )( jQuery );

The JS file of course needs to be loaded in the customizer, and it should be loaded using wp_enqueue_script in the customize_controls_enqueue_scripts hook:

function wpse313731_enqueue_scripts() {
    $handle = 'wpse313731-custom-message';
    wp_enqueue_script( $handle, plugins_url( "$handle.js", __FILE__ ), array( 'customize-controls' ) );

add_action( 'customize_controls_enqueue_scripts', 'wpse313731_enqueue_scripts' );

You may wish to add some styles to make this look a little better, and CSS can be loaded in the customize_controls_enqueue_scripts hook just like the JS, but instead of using wp_enqueue_script(), you would use wp_enqueue_style(). It might also be helpful to add a class to the themes panel headContainer in JS as well, so you can more easily style this section if it is loaded.

I created this gist as well, so you can install the .zip plugin which styles the message to better fit this area and does all of the above things discussed in Solution #2 for you to further experiment with.

  • Many thanks for going above and beyond! Method one worked like a charm. I see it's a whole world of possibilities. I will add, my only trouble was registering the script. Using plugins_url() didn't work regardless of JS file location (theme root or sub dirs); could never get it to load. Instead I used get_template_directory_uri() which was already working for other scripts in the same functions file (Underscores starter theme). Sep 10 '18 at 3:51
  • Not a problem at all! Yes I used plugins_url since I was wrapping the examples up in a plugin, but get_template_directory_uri() is what you should use in themes for sure!
    – Tim Elsass
    Sep 10 '18 at 3:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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