DiggingIntoWordPress

by Chris Coyier & Jeff Starr

WordPress functions.php Template with 15 Essential Custom Functions

Posted by on

When designing WordPress themes, I always add a common set of custom functions to the theme’s functions.php file. This speeds up development time because I don’t have to hunt for and individually copy the same slew of functions for every theme. I just drop in a copy of my functions.php template and build up from there. This takes care of all those little things that always need to be done:

  • Include jQuery
  • Enable threaded comments
  • Add feed links to the header
  • Disable unused widget areas
  • Adding Google Analytics to the footer
  • Stop the “Read More” link from jumping to the middle of the next page ;)

One of the things that I like about these functions is that they’re all so concise, simple, and effective. The functions.php template file currently contains 15 different functions and is a continual work in progress. Not everyone is going to need or use everything in the file, but the idea is to modify this template into something that works for you. It’s a starting point with some really useful functions.

Update! Check out part 2 of this article for more awesome custom WordPress functions »

In this DiW article, we first provide an explanation of each of the 15 functions and then bring them all together into the working functions.php template. Just copy and paste the template code at the end of this article or grab a copy of the zipped functions.php file and enjoy a custom collection of functions that will help you optimize your development process while enhancing WordPress with essential functionality.

Add feed links to header

Since version 2.8, WordPress can add all relevant feed links (main, comments, categories, et al) to your <head> area. It doesn’t happen by default, however, because you have to add the following snippet to make it work:

// add feed links to header
if (function_exists('automatic_feed_links')) {
	automatic_feed_links();
} else {
	return;
}

This will check to see if you’re using a version of WordPress that is compatible, and then enable the automatic feed links. A couple of notes: first, this method assumes that you are not manually including any feed links in your <head>. Also, I read a recent Trac ticket that looked like this functionality was being integrated with add_theme_support, so keep your eyes open for that.

Automatic jQuery inclusion

We’ve discussed how to include jQuery the right way by placing a little snippet in your document head, but here is a way to do it from your theme’s functions.php file:

// smart jquery inclusion
if (!is_admin()) {
	wp_deregister_script('jquery');
	wp_register_script('jquery', ("http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"), false);
	wp_enqueue_script('jquery');
}

This code ensures that only one copy of jQuery is included, and calls it from Google’s servers to save bandwidth and take advantage of any primed caches that happen to be visiting. Note that this function needs to be located before the threaded-comments function in order for it to work.

Enable threaded comments

As we explain in the book, enabling threaded comments requires adding a snippet of code into your <head> area just before the wp_head tag. After a little experimenting, I discovered that you can include this snippet from the functions.php file:

// enable threaded comments
function enable_threaded_comments(){
	if (!is_admin()) {
		if (is_singular() AND comments_open() AND (get_option('thread_comments') == 1))
			wp_enqueue_script('comment-reply');
		}
}
add_action('get_header', 'enable_threaded_comments');

This helps keep your document <head> a little cleaner. Note that this function needs to be located after the jQuery-inclusion function in order for it to work.

Thanks to Peter Wilson (404 link removed 2014/08/05) for this awesome technique (404 link removed 2014/08/03)!

Remove unwanted crap from the head section

As we’ve mentioned before, WordPress spits out a ton of crap in the document <head> – stuff like the version number and WLW, RSD, and index links. To clean things up, we add this nice little snippet into the functions.php template:

// remove junk from head
remove_action('wp_head', 'rsd_link');
remove_action('wp_head', 'wp_generator');
remove_action('wp_head', 'feed_links', 2);
remove_action('wp_head', 'index_rel_link');
remove_action('wp_head', 'wlwmanifest_link');
remove_action('wp_head', 'feed_links_extra', 3);
remove_action('wp_head', 'start_post_rel_link', 10, 0);
remove_action('wp_head', 'parent_post_rel_link', 10, 0);
remove_action('wp_head', 'adjacent_posts_rel_link', 10, 0);

Add Google Analytics to the footer

Another annoying task that has to be done for all of the sites I create is adding Google Analytics code to the footer.php file. Recently it occurred to me to just add the code to my functions.php and never worry about it again:

// add google analytics to footer
function add_google_analytics() {
	echo '<script src="http://www.google-analytics.com/ga.js" type="text/javascript"></script>';
	echo '<script type="text/javascript">';
	echo 'var pageTracker = _gat._getTracker("UA-XXXXX-X");';
	echo 'pageTracker._trackPageview();';
	echo '</script>';
}
add_action('wp_footer', 'add_google_analytics');

A couple of notes here: first, obviously you want to replace the “UA-123456-1” with your actual GA code. Second, you may want to check out the three currently available Analytics options and modify the code accordingly. Currently, this function is using the newer “ga.js” tracking code, but that is easily changed to either of the other methods.

Custom excerpt length

Instead of using the default 55-word limit, this function enables you to specify any length for your excerpts.

// custom excerpt length
function custom_excerpt_length($length) {
	return 20;
}
add_filter('excerpt_length', 'custom_excerpt_length');

Just set your preferred number of words by editing the “20” to whatever you wish.

Custom excerpt “continue” string

Or whatever they call that funky bracketed ellipses thing “[...]” that is appended to your post excerpts by default. I like to remove the brackets, but with this functions.php snippet you can change it to anything:

// custom excerpt ellipses for 2.9+
function custom_excerpt_more($more) {
	return '...';
}
add_filter('excerpt_more', 'custom_excerpt_more');

/* custom excerpt ellipses for 2.8-
function custom_excerpt_more($excerpt) {
	return str_replace('[...]', '...', $excerpt);
}
add_filter('wp_trim_excerpt', 'custom_excerpt_more'); 
*/

As you can see, there are two different versions of this code, depending on your version of WordPress. We like to stay current, so we commented out the older method but left it there in case you need it. For either version of this technique, just replace the “...” with “pants on the ground” or whatever happens to suit your needs.

No “more” jumping for the “read more” link

One of the weirdest things that WordPress does is “jump” the reader to the location of the “<!--more-->” tag on the single-post-view when the “read more” link is clicked. It’s just awkward — if the jump was on the same page, it would make sense, but to load a new page and then take the reader halfway down without explaining anything is just wrong. In any case, here is a nice little function that will stop the jumping once and for all:

// no more jumping for read more link
function no_more_jumping($post) {
	return '<a href="'.get_permalink($post->ID).'" class="read-more">'.'Continue Reading'.'</a>';
}
add_filter('excerpt_more', 'no_more_jumping');
add_filter('the_content_more_link', 'remove_more_jump_link');

Nothing else needs to be done for this to work – just plug it in and enjoy your new “jumpless” functionality. Note that this is also a convenient place to customize the “read more” link with whatever attributes or custom text you wish.

Add a favicon to your blog

You just gotsta have a favicon for your blog, and this code makes it super easy to do. Just create your image and upload to site’s root directory. The following code in your functions.php file makes it so by adding the required line to your <head> area:

// add a favicon to your 
function blog_favicon() {
	echo '<link rel="Shortcut Icon" type="image/x-icon" href="'.get_bloginfo('wpurl').'/favicon.ico" />';
}
add_action('wp_head', 'blog_favicon');

Feel free to change the directory to whatever you desire. Also make sure that the wp_head is present within your theme’s header.php file.

Add a different favicon for your blog’s Admin area

While we’re here, let’s add a unique favicon to our Admin pages, so that they are easier to recognize when bookmarked or working with tabs. Just create a favicon and upload to your theme’s /images/ directory. This code takes care of the rest:

// add a favicon for your admin
function admin_favicon() {
	echo '<link rel="Shortcut Icon" type="image/x-icon" href="'.get_bloginfo('stylesheet_directory').'/images/favicon.png" />';
}
add_action('admin_head', 'admin_favicon');

As before, feel free to change the directory to whatever you desire. It might be best to keep your admin favicon in a separate directory than your blog favicon. Just sayin’.

Custom Admin Login logo

You know that snazzy blue WordPress logo that is branding your various login pages? Yeh, you can change that to whatever you want. Just create your custom login image, name it “custom-login-logo.png”, and upload it to your theme’s /images/ directory. This code will take care of the rest:

// custom admin login logo
function custom_login_logo() {
	echo '<style type="text/css">
	h1 a { background-image: url('.get_bloginfo('template_directory').'/images/custom-login-logo.png) !important; }
	</style>';
}
add_action('login_head', 'custom_login_logo');

The key here is to make sure that the path and image names match that of your setup. Also, when creating your image, you may want to keep in mind the properties of the original: 30px length, 31px height, transparent GIF format, and header background color of #464646 (for the image matte).

Disable unused widget areas

Justin Tadlock shares this handy function for removing unwanted widget areas from our theme – a must for customizing existing themes:

// disable all widget areas
function disable_all_widgets($sidebars_widgets) {
	//if (is_home())
		$sidebars_widgets = array(false);
	return $sidebars_widgets;
}
add_filter('sidebars_widgets', 'disable_all_widgets');

This code is plug-&-play – no other modifications need to be made. Note: if you only want to disable widgets on your Home page, then remove the two comment slashes (“//”) from the third line.

Kill the WordPress update nag

This is one of my favorites, but I know it’s not for everyone. In any case, you know that “Please update now..” message that appears on every page in the WordPress Admin when new versions are available? This sweet little function kills it dead (or disables it, actually):

// kill the admin nag
if (!current_user_can('edit_users')) {
	add_action('init', create_function('$a', "remove_action('init', 'wp_version_check');"), 2);
	add_filter('pre_option_update_core', create_function('$a', "return null;"));
}

Feel free to comment this one out or remove it if you rely on the Admin nag to keep you informed of changes.

Include category ID in body_class and post_class

By default, WordPress body_class and post_class do not include the ID of the category of the current post. This custom function changes all that:

// category id in body and post class
function category_id_class($classes) {
	global $post;
	foreach((get_the_category($post->ID)) as $category)
		$classes [] = 'cat-' . $category->cat_ID . '-id';
		return $classes;
}
add_filter('post_class', 'category_id_class');
add_filter('body_class', 'category_id_class');

Even if you aren’t using it, it’s a nice function to have around, which is why it’s included here for this custom functions.php template of essential functions. Keywords in the house because we can.

Get the first category ID

Another useful function when working with different categories is the ability to get the first category ID of the current post. This function makes it happen:

// get the first category id
function get_first_category_ID() {
	$category = get_the_category();
	return $category[0]->cat_ID;
}

Strictly plug-&-play: just use <?php get_first_category_ID(); ?> in your theme template file to access the data.

Putting it all together..

As promised, here is the full-meal deal – the entire collection neatly organized into a single chunk of code:

<?php // custom functions.php template @ digwp.com

// add feed links to header
if (function_exists('automatic_feed_links')) {
	automatic_feed_links();
} else {
	return;
}


// smart jquery inclusion
if (!is_admin()) {
	wp_deregister_script('jquery');
	wp_register_script('jquery', ("http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"), false, '1.3.2');
	wp_enqueue_script('jquery');
}


// enable threaded comments
function enable_threaded_comments(){
	if (!is_admin()) {
		if (is_singular() AND comments_open() AND (get_option('thread_comments') == 1))
			wp_enqueue_script('comment-reply');
		}
}
add_action('get_header', 'enable_threaded_comments');


// remove junk from head
remove_action('wp_head', 'rsd_link');
remove_action('wp_head', 'wp_generator');
remove_action('wp_head', 'feed_links', 2);
remove_action('wp_head', 'index_rel_link');
remove_action('wp_head', 'wlwmanifest_link');
remove_action('wp_head', 'feed_links_extra', 3);
remove_action('wp_head', 'start_post_rel_link', 10, 0);
remove_action('wp_head', 'parent_post_rel_link', 10, 0);
remove_action('wp_head', 'adjacent_posts_rel_link', 10, 0);


// add google analytics to footer
function add_google_analytics() {
	echo '<script src="http://www.google-analytics.com/ga.js" type="text/javascript"></script>';
	echo '<script type="text/javascript">';
	echo 'var pageTracker = _gat._getTracker("UA-XXXXX-X");';
	echo 'pageTracker._trackPageview();';
	echo '</script>';
}
add_action('wp_footer', 'add_google_analytics');


// custom excerpt length
function custom_excerpt_length($length) {
	return 20;
}
add_filter('excerpt_length', 'custom_excerpt_length');


// custom excerpt ellipses for 2.9+
function custom_excerpt_more($more) {
	return '...';
}
add_filter('excerpt_more', 'custom_excerpt_more');

/* custom excerpt ellipses for 2.8-
function custom_excerpt_more($excerpt) {
	return str_replace('[...]', '...', $excerpt);
}
add_filter('wp_trim_excerpt', 'custom_excerpt_more'); 
*/


// no more jumping for read more link
function no_more_jumping($post) {
	return '<a href="'.get_permalink($post->ID).'" class="read-more">'.'Continue Reading'.'</a>';
}
add_filter('excerpt_more', 'no_more_jumping');


// add a favicon to your 
function blog_favicon() {
	echo '<link rel="Shortcut Icon" type="image/x-icon" href="'.get_bloginfo('wpurl').'/favicon.ico" />';
}
add_action('wp_head', 'blog_favicon');


// add a favicon for your admin
function admin_favicon() {
	echo '<link rel="Shortcut Icon" type="image/x-icon" href="'.get_bloginfo('stylesheet_directory').'/images/favicon.png" />';
}
add_action('admin_head', 'admin_favicon');


// custom admin login logo
function custom_login_logo() {
	echo '<style type="text/css">
	h1 a { background-image: url('.get_bloginfo('template_directory').'/images/custom-login-logo.png) !important; }
	</style>';
}
add_action('login_head', 'custom_login_logo');


// disable all widget areas
function disable_all_widgets($sidebars_widgets) {
	//if (is_home())
		$sidebars_widgets = array(false);
	return $sidebars_widgets;
}
add_filter('sidebars_widgets', 'disable_all_widgets');


// kill the admin nag
if (!current_user_can('edit_users')) {
	add_action('init', create_function('$a', "remove_action('init', 'wp_version_check');"), 2);
	add_filter('pre_option_update_core', create_function('$a', "return null;"));
}


// category id in body and post class
function category_id_class($classes) {
	global $post;
	foreach((get_the_category($post->ID)) as $category)
		$classes [] = 'cat-' . $category->cat_ID . '-id';
		return $classes;
}
add_filter('post_class', 'category_id_class');
add_filter('body_class', 'category_id_class');


// get the first category id
function get_first_category_ID() {
	$category = get_the_category();
	return $category[0]->cat_ID;
}

?>

Download the custom functions.php template file

If you prefer, you can download this code in a ready-to-go functions.php file in zipped format:

Download zipped functions.php Template File

Also..

If this post is useful to DiW readers, I’ll be writing up another article (part 2) with even more useful custom functions. If that happens, the second set of functions will include some slightly more advanced techniques as opposed to these “must-have” template functions. Stay tuned! Update: Custom functions.php Part 2 is here!

81 Responses

  1. Ian Storm Taylor March 22, 2010

    The “smart” way to implement jQuery is extremely useful. I’ve been plagued with duplication forever. Thank you!

  2. great post! thanks!

  3. Wow great post! The functions file is one thing I’ve to learn better.

  4. Yes, a really great article. These are useful snippets for my WordPress blogs. Thanks alot!

  5. Thank you for share this ideas. I try to use some soon.

  6. jQuery inclusion script seems to be broken (the add_action function is missing, there’s a semicolon after the if statement and the if statement is not wrapped with a function). “add feed links to header” seems to be broken too.

    • Jeff Starr

      I removed the extraneous semicolon, but everything else works fine. We are using the exact code here at DigWP.com. If there are specific issues with any of the other functions please let us know.

  7. richard hughes March 22, 2010

    holy cow – this is mega useful. many many thanks – i will be using on my next project

  8. Excellent Article there Jeff. This is going to be very useful for everyone. Retweeting it now.

  9. Gary Miller March 22, 2010

    How many times do you think: “I must do this and that” and never actually get around to it?

    Really grateful you did, great tool. Thanks!

  10. CMS Themes March 22, 2010

    This is awesome list! I will definitely use most the the codes in my WP next projects.

  11. Good stuff, good to see more people dislike all the junk in the head section :)

    Only thing that bugs me is the GA one: people will forget to change the UA code :) Also, if you’re doing this, go for the new asynchronous tracking, it’s a lot faster than ga.js. My own Google Analytics for WordPress plugin will reach version 4 quite soon and offers a slew of options that you’d never be able to get into your functions.php, so you might consider just using a plugin for it ;)

    • Jeff Starr

      Absolutely, we recommend your Google Analytics plugin in our book and do here as well. Thanks for the reminder!

  12. SIRRÖD March 22, 2010

    This is awesome! Implementing some of these today.

  13. countzeero March 22, 2010

    Great! will be using this for my future WP development work thanks for the code and easy to understand explanations.

  14. Congratulations for the post…

  15. Love the code snippets here. I’ve loved the jQuery enqueue from Google since I saw it published last year. Many useful bits in there. Will be used in some form on upcoming projects.

    Thanks Jeff, keep up the good work

  16. Thanks for these, they’re a big help… The login logo function is the first one that grabs my eye for sure. Thanks

  17. This is really a great post. Definitely useful for WP development.

  18. thanks for the great article..

  19. nelilly March 22, 2010

    Very cool.

  20. Sharing some other ones with I use personally (and which might be handy for others)

    /*
    Custom Contact Fields
    */
    function my_new_contactmethods( $contactmethods ) {
           // Add Twitter
           $contactmethods['twitter'] = 'Twitter <span class="description">(username)</span>';
           //add Facebook
           $contactmethods['facebook'] = 'Facebook <span class="description">(username)</span>';
           // Add LinkedIn
           $contactmethods['linkedin'] = 'LinkedIn <span class="description">(profilename)</span>';
           // Add Flickr
           $contactmethods['flickr'] = 'Flickr <span class="description">(profilename)</span>';

           // Remove unwanted contacts
           unset($contactmethods['yim']);
           unset($contactmethods['jabber']);
           return $contactmethods;
    }
    add_filter('user_contactmethods','my_new_contactmethods',10,1);

    You can query these later with the get_the_author_meta() function.

    Another one which I picked up somewhere on the web:

    /*
    Comment classes for user roles
    */
    function add_author_role($classes, $class, $comment_id, $post_id) {
           global $wpdb;
           $capabilities = $wpdb->prefix."capabilities";
           $comment = get_comment($comment_id);
                  if ( $comment->user_id > 0 && $user = get_userdata($comment->user_id) ) {
                         $classes[] = join(' author-role-', array_merge(array(''), array_keys($user->$capabilities)));
                  }
           return $classes;
    }
    add_filter('comment_class', 'add_author_role', 10, 4);

    And my little time based CSS switcher (for holidays, where we change the header logo and background)

    function Holidays() {
           // time based css switch
           $month = date("n");
           $day = date("j");
           if ($month == 12 && ($day >= 15 && $day <= 31)) {
                  wp_enqueue_style( 'kerst', 'http://example.com/css/xmas.css', '', '1.0', 'all');
           }
    }
    add_action('wp_print_styles', 'Holidays');

  21. Concerning script incusion:

    Why don’t you lose the wp_register_script()-line and enqueue the script directly?

    Isn’t the wp_register_script() function for the purpose of registering the script without calling it?

    (At least that’s what I read into the tiny difference in code between this function and wp_enqueue_script())

  22. One more thing:
    Currently you set up all feeds to be added to you <head>-section and remove the same actions a couple of lines after that.

    // remove junk from head
    remove_action('wp_head', 'feed_links', 2);
    remove_action('wp_head', 'feed_links_extra', 3);

    • Jeff Starr

      Yep, that’s for better flexibility. Depending on the site, I will comment one or the other out, add other functions, etc., until I get what I want. Again, this template is just a starting point.

  23. There seems to be a syntax error on line 95 with the add favicon.

    I’m not a PHP guy, but it appears that “.blog get_bloginfo” should be “.blogget_bloginfo”.

    • Jeff Starr

      Good call — both favicon functions should be using get_bloginfo. Both functions have been corrected in both locations in the article. Thanks for the heads up!

    • Never mind… Textmate bitches about it, but it’s OK.

      • Oops, replied then saw your response.

        Textmate PHP validation seems better than the PHP Toolkit plug-in for Panic’s Coda. Again, not a PHP guy.

  24. That’s pretty awesome Jeff :)

    Especially like the Analytics – hadn’t thought of that either.

  25. Daniel K March 22, 2010

    I don’t know about some people but I play around with themes and things offline (outside of wi-fi at McD’s and Hardee’s I have dial-up at home) so something to consider is downloading jquery and pointing it to your local instead of google’s. I had the hardest time with the All-AJAX theme until I kicked myself and realized that it was pointing to an online file.

    • In practice I’ve always preferred to host locally, at least until a site is finished and I do an optimization pass.

      The whole point of linking to the Google hosted script is to reduce server hit latency and depending on how you use the link syntax, keep your JQuery library up-to-date.

      Considering that JQuery is now at 1.4.x, bleeding edge folks might want to update the Google hosted link to the newer version. I’ve found that JQuery 1.4.x is indeed faster, but also a bit larger. A few plugins might break as well, but overall it seems solid. At least give it a try since it’s an easy text change in the file.

  26. gr8 work !!!.
    Wonder if you could also add a list of words to prevent spam, those russian bb code links via regex.

  27. I find this rather funny, I was just working on building a “functions.php template” of my own and decided to take a small break when I stumbled on this article. I’m definitely going to include some of these, thanks.

  28. reena verma March 22, 2010

    This is very nice…

  29. _DorsVenabili March 23, 2010

    Awesome post!!!, very useful thanks :D

  30. Darfuria March 23, 2010

    I don’t understand why threaded comments has to be enabled in functions.php, when there is a setting for it on the Settings > Discussion page. Otherwise, great set of snippets!

  31. Here’s the link to a great post on Yoast’s site about the update nag. You could actually have it disabled for any user except the “admin” (you) of the site. Check it out: http://yoast.com/disable-update-nag/

  32. Great stuff. One little correction on the Zip file:
    Line 92, the word “blog” got out of order:

    href="'.blog get_bloginfo

    should be

    href="'.get_bloginfo

  33. I’m using WordPress MU version 2.9.1.1 and there is a tag in the header:

    <meta name="framework" content="Alkivia Framework 0.8" />

    is there any way to remove that as well?

    • Put this in your theme’s function.php (instructions in Jeff’s post)

      remove_action('wp_head', '_ak_framework_meta_tags');

  34. I have been struggling to find a way to stop multiple jQuery files from loading and use Google jQuery. This code helped me a lot. Thanks.

    One more thing I need some help with (remove junk from head) code.

    // remove junk from head
    remove_action('wp_head', 'rsd_link');
    remove_action('wp_head', 'wp_generator');
    remove_action('wp_head', 'feed_links', 2);
    remove_action('wp_head', 'index_rel_link');
    remove_action('wp_head', 'wlwmanifest_link');
    remove_action('wp_head', 'feed_links_extra', 3);
    remove_action('wp_head', 'start_post_rel_link', 10, 0);
    remove_action('wp_head', 'parent_post_rel_link', 10, 0);
    remove_action('wp_head', 'adjacent_posts_rel_link', 10, 0);

    When I include this code in my functions.php file and reload the page everything goes blank. Can anybody help me with this one? Thanks!

    • I’d guess either you copied and missed a closing semi-colon, you placed that block outside of the tags or your site needs one or more of those functions for some reason. Make sure the code’s copied precisely and that your functions.php begins with . If all of that is fine, add those lines one by one until the site breaks, then leave out the remove_action call that breaks your site.

      • Thanks Ricky for you help. I don’t think I missed anything out. I think one of the remove_action is cussing the problem. I will try one by one and see if the site breaks.

  35. Great article, thank you!

  36. Awesome round up! Especially the jQuery queue. Here’re a couple of others I use, not “must have”, but nice to have in case:

    // Add custom post title via custom fields
    function custom_title() {
           global $wp_query;
           $postID = $wp_query->post->ID;
           if (get_post_meta($postID, 'custom_title', true) != '') {
                  echo get_post_meta($postID, custom_title, true);
           } else {
                  the_title();
           }
    }

    // Get first image in post
    function get_first_image() {
           global $post, $posts;
           $first_img = '';
           ob_start();
           ob_end_clean();
           $output = preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches);
           $first_img = $matches [1] [0];
           return $first_img;
    }

    • …almost forgot this one for WP 2.9 is a must have:

      add_theme_support( 'post-thumbnails' );

  37. A question on the jQuery function: when I add this to my functions.php file, I lose one of my jQuery effects: a “fancy-box” animation which makes thumbnails expand to full size and move to the center of the screen when you click on them. I’m still relatively new at this and am not sure why this is happening (I had the same issue when I implemented Chris’ “organic tabs” on my archives pages and tried to use only one jQuery call). Any explanations would be appreciated.

    For the record, here are the js calls as they currently stand in my header:

    <script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js?ver=1.3.2'></script>
    <script type="text/javascript" src="<?php bloginfo('template_url'); ?>/js/example.js"></script>

    <script type="text/javascript" src="<?php bloginfo('template_directory')?>/js/jquery.min.js"></script>
    <script type="text/javascript" src="<?php bloginfo('template_directory')?>/js/jquery.fancybox.yuic.js"></script>
    <!--[if lt IE 7]><script src="<?php bloginfo('template_directory')?>/js/jquery.pngFix.pack.js" type="text/javascript"></script><![endif]-->
    <script type="text/javascript" src="<?php bloginfo('template_directory')?>/js/satorii.js"></script>

    Thanks in advance.

    • If you code above comes before the wp_head() in header.php, that could be causing your problems.

      I’d suggest you use write js tags using the wp_enqueue_script function in your functions.php rather than hard coding them in header.php.

      A full explanation is in the codex, another good resource is at planetozh.

      • The above code *is* before the wp_head() in my header.php. I’ll try switching the order to see if that does anything.

        I’ll also check out the codex and planetozh. Thanks for the help.

      • Ok, I put the “automatic jQuery inclusion” in my functions.php file and eliminated the other jQuery tags in my header.php. The result was that the “fancy-box” stopped working. It apparently needs both of these to work:

        <script type="text/javascript" src="<?php bloginfo('template_directory')?>/js/jquery.min.js"></script>
        <script type="text/javascript" src="<?php bloginfo('template_directory')?>/js/jquery.fancybox.yuic.js"></script>

        which means that it’s on this line (the first in the excerpt above) that I can eliminate and not lose anything:

        <script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js?ver=1.3.2'></script>

        I am understanding you to say that *all* of the JavaScript and jQuery tags could/should be included in the functions.php file rather than the header? (Sorry if this is an obvious one — I’m still trying to understand it all.) If so, why would that be preferred? The site will still have to load the functions, won’t it?

        • You’re correct, all script should be called using the enqueue method. These methods allow dependancies to be assigned, and WordPress will make sure the files are loaded in the correct order.

          To use your example, fancybox relies on jQuery and, I presume, your custom file relies on fancybox and jQuery. In functions.php, the calls to wp_enqueue_scripts could be:

          //wp_enqueue_script ($handle-ID, $src, [$depends, [$ver, [$in_footer]]])
          wp_enqueue_script('custom', bloginfo('template_directory') . '/js/custom.js', array('fbox'));
          wp_enqueue_script('fbox', bloginfo('template_directory') . '/to/jquery.fancybox.yuic.js', array('jquery'));

          WordPress will deal with the apparent problems in the code above:

          1) WordPress will call jQuery, even though it’s not explicitly called, as WordPress knows about jQuery by default. I still recommend the code Jeff has above though.

          2) Fancy-box will be outputted before custom.js, despite the order above

          3) WordPress will figure out that custom.js depends on fancy-box depends on jQuery = custom depends on fancybox and jQuery

          I hope this helps, or at least amuses you as the incoherent ramblings of a mad-man.

        • I’ve just realised, I’ve made a typo in the code above, replace both instances of bloginfo('template_directory') with get_bloginfo('template_directory')

          Pete

  38. Here’s another useful function to replace the WordPress RSS feed to a Feedburner feed.

    remove_action('wp_head', 'feed_links', 2);

    function feedburner_rss() {
           $feedburner_url = 'http://feeds.feedburner.com/LDDCreations';
           echo '<link rel="alternate" type="application/rss+xml" title="RSS Feed" href="' . $feedburner_url . '" />' . "\n";
           echo '<link rel="alternate" type="application/rss+xml" title="Comments RSS Feed" href="' . get_bloginfo('comments_rss2_url') . '" />' . "\n";
    }

    add_action('wp_head', 'feedburner_rss');

  39. NgoiNhaSo March 28, 2010

    Thanks for you post !
    I love it !

  40. Maybe I missed it in the article, but can you explain the advantages of loading jQuery in the head? I had understood it bet to load it in the footer? I read the article on including jQuery the right way, but didn’t find a discussion on why it should be in the header, rather than the footer.

  41. Leandro Bennaton March 28, 2010

    Unfortunately I can’t do No “more” jumping for the “read more” link work!
    Could someone give to me a further support?

  42. Hi,

    To get the no more jumping for read more link function to work I needed to change ‘excerpt_more’ to ‘the_content_more_link’.

    • Steve Jones May 20, 2010

      Thanks, Jase! A minor annoyance finally eliminated. Shoulda looked through the comments a long time ago….

  43. Simply beautiful. I’ve begun putting my own recipe together for functions.php and this list of functions is extremely helpful in getting up to speed. Thank you for bundling these together and for some great additions in the comments!

    Has anyone explored wrapping these into a plugin – particularly in light of the fact that changing themes is a fairly fun thing for new WordPress users to try?

    A couple functions I like to add include obfuscate email with encoded content
    and also the “display if on decendant posts function” – great for the widget logic plugin

    function post_is_in_descendant_category( $cats, $_post = null )
    {
    foreach ( (array) $cats as $cat ) {
    // get_term_children() accepts integer ID only
    $descendants = get_term_children( (int) $cat, 'category');
    if ( $descendants && in_category( $descendants, $_post ) )
    return true;
    }
    return false;
    }

    function munge_mail_shortcode( $atts , $content=null ) {

    for ($i = 0; $i < strlen($content); $i++) $encodedmail .= "&#" . ord($content[$i]) . ';';

    return '<a href="mailto:'.$encodedmail.'">'.$encodedmail.'</a>';

    }
    add_shortcode('mailto', 'munge_mail_shortcode');

  44. Great roundup!

    One thing, on the logo login, the info you have on the original image is incorrect. The dimensions are 310px width, 70px height with a matte of #f9f9f9.

    I think what you are referring to is the W logo in the top admin bar.

  45. Leandro Bennaton April 2, 2010

    Unfortunately I still can’t solve the function No “more” jumping for the “read more” link work!

    Could someone give to me a further support? I use the string:

    And a sample post More reading?

    http://zoabonito.com/fotos/nicole-scherzinger-do-pussycat-dolls#more-4649

  46. Thanks for sharing !
    Very handy snippets I’ll start to use asap…

  47. nice tutorial, thanks

  48. Great post with great comments! One question though, is it possible to set up categories in functions.php, let’s say I want video, quotes and images categories set up through the functions.php?

  49. Great!
    Thank you very much!

  50. Hi Jeff,

    After implementing the Threaded Comments as in the DIW eBook my comments works perfectly however the comment form isn’t jumping to the comments and it give me a JS error “addComment is not defined” :S

    I’m using this before bu wp_head mate, any suggestion will be helpful.

  51. If only I had read this when I started my site…Oh, how much time I could’ve saved.

  52. “Kill the WordPress update nag” is NOT very smart. If you forget to update your blog version, your blog becomes a target for exploits!

    • Jeff Starr

      In general, I would agree, but there are specific cases where it’s certainly not needed. For example, I am running an old version of WordPress at my site, Perishable Press, and have done so for a couple of years now. Have not had a single problem whatsoever.

  53. my brain does not work in time of coding.

  54. Nice article, but I’m having a problem with the excerpt.

    This is the same code posted on wordpress.org, I tried it, but it only work on posts without any excerpt, it will get the first # of words on your post entry depending on the # you placed on the code posted above, but when you have a specific excerpt posted, it doesn’t work.

  55. Automatic jquery inclusion generates the following in the header of a site I’m working on:

    Huh? version 2.92? Any idea why this would get tacked on? BTW, I also implemented the function that removes the WP version (which is 2.9.2).

  56. Here’s the code again, hope this shows up:

    <script type='text/javascript' src='http://www.energy4me.org/js2010/jquery.js?ver=2.9.2'></script>

  57. Nice blog here! Also your website loads up very
    fast! What web host are you using? Can I get your affiliate link to your host?

    I wish my website loaded up as fast as yours lol

Comments are closed. Contact us with any critical information. Thank you!

Code is poetry