The WP Customizer's WP_Customize_Image_Control returns the attachment's URL, but I need the ID because I want to output the image like this:

echo wp_get_attachment_image( $user_logo_id, 'riiskit-user-logo' );

The reason for this is because I want the logo to be compatible with the WP Retina 2x plugin. That's why I'm using the thumbnail-sizing above. This way, the user only has to upload one big image and everything else will be taken care of by the code.

I've already tried all the different attachment_src_to_id functions out there but none of them works and only returns null or false. This for instance

Even when I type the URL manually as a parameter, it still returns negative.

However when I type the ID manually inside wp_get_attachment_image, it shows as expected.

Have something changed in WP v3.9 that causes these functions to return false?

Perhaps there is some way to extend the Customizer's image control to receive the attachment ID?

Any ideas? :)

2 Answers 2


This is very old, but for someone coming here via search

WP_Customize_Media_Control control in WP since 4.2 give you the attachment id.

Ref: https://make.wordpress.org/core/2015/07/16/new-customizer-media-controls-in-4-3-and-4-2/

  • 1
    This should be WP_Customize_Media_Control as WP_Customize_Cropped_Image_Control returns the url of a cropped image Sep 26, 2017 at 22:46

I know this is old but I was looking for an answer to this problem so that I could save a thumbnail rather than use the full size image for a log and couldn't. I have figured it out for my needs by doing the following:

When choosing an image I hook into the customize_sanitize_{$this->id} filter. This gives me the image url in a filter to do what I want with.

Initially I used attachment_url_to_postid to change the value in the filter callback and then return the new image url from the function, which would then be stored in place of the standard url. However, it turns out that the function that populates the uploader with any previous selection (found in the WP_Customize_Upload_Control class that the WP_Customize_Image_Control inherits from) uses this same function to get the attachment ID, and ultimately render the current selection. This breaks when the URL passed to it is a thumbnail, which is what I'd changed the database value to.

What I did instead was actually save the the value as a wp_option in the filter callback and just send the standard value right through the function so as not to break it as was happening:


function site_logo_save( $value ) {
    $id = attachment_url_to_postid($value);
    $thumb = wp_get_attachment_image_src( $id );
    $url = $thumb[0];
    update_option('site_logo', $url);
    return $value;
add_action('customize_sanitize_site_logo', 'site_logo_save');

Then in my theme file, instead of using get_theme_mod, I just used get_option to retrieve the url:


<div class="site-branding">
    <?php if($site_logo = get_option('site_logo')): ?>
        <img src="<?php echo get_option('site_logo'); ?>" class="site-logo" alt="<?php bloginfo( 'name' ); ?>">
    <?php else: ?>
        <h1 class="site-title"><a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></h1>
        <h2 class="site-description"><?php bloginfo( 'description' ); ?></h2>
    <?php endif; ?>
</div><!-- .site-branding -->

// Add this if we are in the customizer for reseting when no image selected
global $wp_customize;
if ( isset( $wp_customize ) ) : ?>
<div style="display: none;">
    <div class="site-branding-no-logo">
        <h1 class="site-title"><a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></h1>
        <h2 class="site-description"><?php bloginfo( 'description' ); ?></h2>
<?php endif; ?>

Additionally, because I wanted to use 'transport' => 'postMessage' for my setting I needed to make an admin-ajax call to get the image thumbnail I was actually going to use for whenever this customizer options was changed in order to reflect this live:


wp.customize( 'site_logo', function( value ) {
    value.bind( function( to ) {
        if (to == false) {
            var orig = $( '.site-branding-no-logo' ).html();
            $( '.site-branding' ).html( orig );
        } else {
            var data = {
                action: 'get_actual_site_logo_url'
            $.post(ajaxurl, data, function(response) {
                var $img = $('<img>').attr('src', response);
                $( '.site-branding' ).html( $img );
    } );
} );


function get_actual_site_logo_url_callback() {
    echo get_option('site_logo');

add_action( 'wp_ajax_get_actual_site_logo_url', 'get_actual_site_logo_url_callback' );

It's fair to say I had to go along way out of the way to get the functionality I wanted but it seems to be working well!

  • Great suggestion! You can also use sanitize_callback on the add_setting() call. May 29, 2015 at 0:02

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.