I am a rookie theme developer (3 months in) and I am trying to figure out how to implement the following functionality:

  1. The theme I am building has a logo which I would like for users to be able to change.
  2. I'd like for them to NOT have to do so in the code.
  3. Rather I'd like to develop some type of low-tech "Theme Control Panel" or some such thing where they can add the logo to the header.

Here is a screenshot so you can see more clearly what I am trying to do.

I am using Theme-Check which is currently telling me:

RECOMMENDED: No reference to add_custom_image_header was found in the theme. It is recommended that the theme implement this functionality if using an image for the header.

But I don't think this applies to my theme as I am NOT using the ENTIRE header for an image. Rather, just a portion is used for the logo (plus it is absolutely positioned).

So is there some template tag which can accomplish this? Cuz, I surely cant find it in the Codex.

Thanks In Advance, sleeper


3 Answers 3


You can create a basic theme options page using the WordPress settings api

Here is a simple example that will create an input field for the user to enter a path to the custom logo.

// Add a menu for our option page
add_action('admin_menu', 'prefix_myplugin_add_page');
function prefix_myplugin_add_page() {
    add_options_page( 'My Theme Options', 'Theme Name Options', 'manage_options', 'prefix_mytheme', 'prefix_myplugin_option_page' );

// Draw the option page
function prefix_mytheme_option_page() {
    <div class="wrap">
        <h2>Really Simple Google Analytics</h2>
        <form action="options.php" method="post">
            <?php settings_fields( 'prefix_mytheme_options' ); ?>
            <?php do_settings_sections( 'prefix_mytheme' ); ?>
            <input name="Submit" type="submit" value="Save Changes" />

// Register and define the settings
add_action( 'admin_init', 'prefix_mytheme_admin_init' );
function prefix_mytheme_admin_init(){
        'Enter text here',

// Draw the section header
function prefix_mytheme_section_text() {
    echo '<p>Enter path to custom logo.</p>';

// Display and fill the form field
function prefix_mytheme_setting_input() {
    // get option 'text_string' value from the database
    $options = get_option( 'prefix_mytheme_options' );
    $text_string = $options['text_string'];
    // echo the field
    echo "<input id='text_string' name='prefix_mytheme_options[text_string]' type='text' value='$text_string' />";

Calling the custom logo option in your header.php file:

$options = get_option( 'prefix_mytheme_options' );
if ( ! empty( $options['text_string'] ) ) { 
    $logo = $options['text_string'];
} else { $logo = 'http://path_to_default_logo'; 
  • 1
    BINGO! Now we talkin! I see it AND I understand it. After 3 days and plenty of AWESOME comments, I got a handle on what I need to study (starting with this code). Truly patience is a virtue. Thank you so much. And thanks to everyone that participated. This forum is great!
    – sleeper
    Commented Feb 18, 2012 at 0:13

I just finished posting this My Options Panel a couple of hours a ago which will answers you question.

  • Lone link is a poor answer, summarize the contents of the link in your answer.
    – mor7ifer
    Commented Feb 16, 2012 at 2:01
  • @Brian Fegter OK. Thanks for the answers, and yes, they are both really great apps. "Respect Mon". I'll prob. use them in production. But for now, I am trying to learn to do this MYSELF not use a tool which (while very cool) doesn't teach me anything. I'm looking for tips, pointers, links to codex articles and the like. Not plugins, etc. unless you can point to some code in the plugin which teaches me how to do this myself. I'm going to leave this question open for a bit longer in hopes of getting an answer which addresses these needs. Thanks Again!
    – sleeper
    Commented Feb 16, 2012 at 6:47
  • @Brian Fegter Just re-read your post. You DID mention the WordPress Settings API in that post. Does that section addresses my issue as well?
    – sleeper
    Commented Feb 16, 2012 at 6:57

Even if your image doesn't cover the typical full-width area you're used to seeing in twentyten and twentyeleven, add_custom_image_header is the appropriate way to do this, and it's far simpler to use the built-in functionality than building a new options panel to handle it.

In the process of declaring support for custom headers, you define the height and width of your image; you also control the code in which you output it, including whatever positioning you choose to apply to it. So there's really no reason to limit your design thinking to only a full-width header.

  • I used to think likewise, but I've since been convinced that I was wrong. :) The header image is intrinsically different from a logo, and it probably isn't best to use add_custom_image_header() for adding a custom logo. At least, it might or might not be, depending on the design of the Theme, and the needs of the end user. (Part of the problem using it is that it limits the logo to very specific width/height dimensions, which won't always work for logos.) Commented Feb 17, 2012 at 0:18
  • Might or might not be, sure, except that in this point, the OP was talking about designing a theme to take a logo of a specific size in the header -- I'd agree that a logo may not work as a banner image, but I think it's more to the point for this question that the get_header_image() call can be in whatever size or shape element you want it to be. And I'd rather see people using the native function than build options for something that's already there.
    – sabreuse
    Commented Feb 17, 2012 at 2:46
  • Oh, for sure, I agree that native functionality should be used wherever feasible/appropriate. :) Commented Feb 17, 2012 at 3:49
  • @sabreuse Can you (or some kind person) briefly outline the steps involved in this process? As I stated in the original post, I cant seem to find instruction on the proper template tags to accomplish this.
    – sleeper
    Commented Feb 17, 2012 at 5:34

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.