# Different Logo on Selected Pages

> Adds a Page Logo box to the page editor so you can pick a different logo from the Media Library for that page. It replaces the site logo wherever the theme shows it, including the Site Logo block.

- Type: PHP
- Runs: Run everywhere
- Category: [Frontend & Design](https://wpide.com/library/category/frontend/)
- Tags: frontend, logo, branding, pages
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/custom-logo-per-page/

## Code

```php
// Post types that get the "Page Logo" box.
$wpide_page_logo_post_types = array( 'page' );

// Where the chosen image ID is stored.
$wpide_page_logo_meta_key = '_wpide_page_logo_id';

// Registered for the REST API so the block editor saves it with the page.
add_action( 'init', function () use ( $wpide_page_logo_post_types, $wpide_page_logo_meta_key ) {
    foreach ( $wpide_page_logo_post_types as $post_type ) {
        register_post_meta( $post_type, $wpide_page_logo_meta_key, array(
            'type'              => 'integer',
            'single'            => true,
            'default'           => 0,
            'show_in_rest'      => true,
            'sanitize_callback' => 'absint',
            'auth_callback'     => function ( $allowed, $meta_key, $post_id ) {
                return current_user_can( 'edit_post', $post_id );
            },
        ) );
    }
} );

add_action( 'add_meta_boxes', function () use ( $wpide_page_logo_post_types, $wpide_page_logo_meta_key ) {
    add_meta_box( 'wpide-page-logo', 'Page Logo', function ( $post ) use ( $wpide_page_logo_meta_key ) {
        $logo_id = (int) get_post_meta( $post->ID, $wpide_page_logo_meta_key, true );
        $preview = $logo_id ? wp_get_attachment_image( $logo_id, 'medium', false, array( 'style' => 'max-width:100%;height:auto;' ) ) : '';

        wp_nonce_field( 'wpide_page_logo_save', 'wpide_page_logo_nonce' );
        ?>
        <div class="wpide-page-logo" data-meta-key="<?php echo esc_attr( $wpide_page_logo_meta_key ); ?>">
            <div class="wpide-page-logo__preview"><?php echo wp_kses_post( $preview ); ?></div>
            <input type="hidden" name="wpide_page_logo_id" value="<?php echo esc_attr( $logo_id ? (string) $logo_id : '' ); ?>">
            <p>
                <button type="button" class="button wpide-page-logo__choose">Choose logo</button>
                <button type="button" class="button-link button-link-delete wpide-page-logo__remove"<?php echo $logo_id ? '' : ' hidden'; ?>>Remove</button>
            </p>
            <p class="description">Shown instead of the site logo on this page only.</p>
        </div>
        <?php
    }, $wpide_page_logo_post_types, 'side', 'low' );
} );

add_action( 'admin_enqueue_scripts', function ( $hook ) use ( $wpide_page_logo_post_types ) {
    $screen = get_current_screen();

    if ( in_array( $hook, array( 'post.php', 'post-new.php' ), true ) && $screen && in_array( $screen->post_type, $wpide_page_logo_post_types, true ) ) {
        wp_enqueue_media();
    }
} );

$wpide_page_logo_script = function () use ( $wpide_page_logo_post_types ) {
    $screen = get_current_screen();

    if ( ! $screen || ! in_array( $screen->post_type, $wpide_page_logo_post_types, true ) ) {
        return;
    }
    ?>
    <script>
    ( function () {
        var box = document.querySelector( '.wpide-page-logo' );
        if ( ! box || ! window.wp || ! wp.media ) {
            return;
        }

        var input = box.querySelector( 'input[name="wpide_page_logo_id"]' );
        var preview = box.querySelector( '.wpide-page-logo__preview' );
        var remove = box.querySelector( '.wpide-page-logo__remove' );
        var metaKey = box.getAttribute( 'data-meta-key' );
        var frame = null;

        // In the block editor, also store the value in the page itself so "Save" picks up the change.
        function setValue( id ) {
            input.value = id ? String( id ) : '';
            remove.hidden = ! id;
            if ( wp.data && wp.data.select( 'core/editor' ) ) {
                var meta = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'meta' );
                if ( meta && Object.prototype.hasOwnProperty.call( meta, metaKey ) ) {
                    var change = {};
                    change[ metaKey ] = id || 0;
                    wp.data.dispatch( 'core/editor' ).editPost( { meta: change } );
                }
            }
        }

        box.querySelector( '.wpide-page-logo__choose' ).addEventListener( 'click', function () {
            if ( ! frame ) {
                frame = wp.media( {
                    title: 'Choose a logo for this page',
                    button: { text: 'Use as page logo' },
                    library: { type: 'image' },
                    multiple: false
                } );

                frame.on( 'select', function () {
                    var image = frame.state().get( 'selection' ).first().toJSON();
                    var img = document.createElement( 'img' );
                    img.src = image.sizes && image.sizes.medium ? image.sizes.medium.url : image.url;
                    img.alt = '';
                    img.style.maxWidth = '100%';
                    img.style.height = 'auto';
                    preview.textContent = '';
                    preview.appendChild( img );
                    setValue( image.id );
                } );
            }
            frame.open();
        } );

        remove.addEventListener( 'click', function () {
            preview.textContent = '';
            setValue( 0 );
        } );
    } )();
    </script>
    <?php
};

add_action( 'admin_footer-post.php', $wpide_page_logo_script );
add_action( 'admin_footer-post-new.php', $wpide_page_logo_script );

// Classic editor (and the meta box form the block editor sends after saving).
add_action( 'save_post', function ( $post_id, $post ) use ( $wpide_page_logo_post_types, $wpide_page_logo_meta_key ) {
    if ( ! isset( $_POST['wpide_page_logo_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['wpide_page_logo_nonce'] ) ), 'wpide_page_logo_save' ) ) {
        return;
    }

    if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || wp_is_post_revision( $post_id ) || ! in_array( $post->post_type, $wpide_page_logo_post_types, true ) || ! current_user_can( 'edit_post', $post_id ) ) {
        return;
    }

    $logo_id = isset( $_POST['wpide_page_logo_id'] ) ? absint( $_POST['wpide_page_logo_id'] ) : 0;

    if ( $logo_id && wp_attachment_is_image( $logo_id ) ) {
        update_post_meta( $post_id, $wpide_page_logo_meta_key, $logo_id );
    } else {
        delete_post_meta( $post_id, $wpide_page_logo_meta_key );
    }
}, 10, 2 );

// Swap the logo on the front end. This covers get_custom_logo(), the_custom_logo() and the Site Logo block.
add_filter( 'theme_mod_custom_logo', function ( $logo_id ) use ( $wpide_page_logo_post_types, $wpide_page_logo_meta_key ) {
    if ( is_admin() || ! did_action( 'wp' ) || ! is_singular( $wpide_page_logo_post_types ) ) {
        return $logo_id;
    }

    $page_logo = (int) get_post_meta( get_queried_object_id(), $wpide_page_logo_meta_key, true );

    return ( $page_logo && wp_attachment_is_image( $page_logo ) ) ? $page_logo : $logo_id;
}, 20 );
```

## Notes

Add more post types at the top, for example array( 'page', 'post' ). Remove the page logo to go back to the site logo. The logo is shown at the size your theme or Site Logo block uses.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Different Logo on Selected Pages" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
