A Newbie’s Guide to WordPress Hooks and Functions

When people start wanting to customize WordPress, specifically a theme like Thematic, or a plugin like WooCommerce, I always see questions like:

How do I add “something”, “somewhere”?

or

How do I remove “something” from “somewhere”?

or

How do I change “something”?

At first it is easy to think that adding a div to the #header is different from adding a menu to the #footer, but once you understand how filters and action hooks work, you’ll see these questions really all follow the same pattern. You just need to learn how to speak WordPress! Be patient with yourself, because you literally are learning a new language… especially if you aren’t already familiar with PHP.  I’ll be using examples for working with the Thematic Theme Framework but you don’t understanding hooks and functions and eventually filters will be handy in any WordPress project.  Let’s start…

What the heck is an Action Hook

Action hooks look like this:

do_action('this_is_the_action_hook_name');

In a plugin such as WooCommerce, if you investigate in the templates folder you will find all sorts of action hooks. The WooCommerce templates are extremely well-documented and tell you right there which functions are hooked into that action hook and in what order. In the theme, Thematic most of these are buried in the library/extensions folder.  In fact, in the actual templates (like index.php, category.php etc) you will see hooks that look more like:

// action hook for placing content above the index loop
thematic_above_indexloop();

But if you go searching for the definition of that function you will find that it is in content-extensions.php

/**
 * Register action hook: thematic_above_indexloop
 *
 * Located in index.php
 * Just before the loop
 */
function thematic_above_indexloop() {
  do_action('thematic_above_indexloop');
} // end thematic_above_indexloop

Now an action hook is sort of like a parking spot. Some are empty, some have cars on them. you can move the cars around, but the spots themselves stay put. When wordpress gets to an action hook, it will run all the functions that are attached to that particular hook. If it gets to a parking spot and finds a car, it will run that car. If not, then it will continue on to the next hook/space.

How To Add Any Function to any Hook

A completely fictitious example:

function function_you_want_to_add(){
echo "I heart bacon!";
}
add_action('destination_hook','function_you_want_to_add', $priority, $args );

The add_action line is doing the heavy lifting here, and always takes this same “form”…. it sort of reads like this in english:

Add the function called ‘function_you_want_to_add’ to the hook called ‘destination_hook’ in the order of $priority with some optional extra arguments called $args.

You can read all about add_action in the WordPress Codex (hint: there is a TON of info there, but I understand it can be overwhelming at first).

The $priority is always a number. It is like a traffic cop in the parking lot, or maybe just an orange cone. if more than 1 function wants to be on a particular hook the priority decides which goes first. If 2 cars wanted to be in the same spot, the one with the lower number priority would get ground level parking and the one with the higher priority would be stacked on top. Yay 3-d parking! Sorry, prepare yourself we are going to beat this metaphor to death. The default priority is 10, so if you don’t need to change that you don’t even need to define it in your add_action line.

Some hooks pass additional variables to the functions that operate on them, but this is pretty advanced so for an introductory primer we will ignore it.

Now, a practical example:

function function_you_want_to_add(){
echo "I heart bacon!";
}
add_action('thematic_above_indexloop','function_you_want_to_add');

If you add the practice example to your child theme’s functions.php you will see “I heart bacon!” appear on your blog page. Now leave that there and add the following just underneath it in your functions.php.

function kia_another_function(){
echo "Guacamole makes me happy!“;
}
add_action('thematic_above_indexloop','kia_another_function', 5);

Notice the priority number is 5. This means it has a lower priority number than the first function, which is 10 by default since we didn’t specify anything. When you reload your theme you should now see Guacamole makes me happy! on the blog index above the line about loving bacon. Bacon and guacamole together. It must be code heaven.

How to Remove Something From a Hook

removing stuff works a bit differently:

function remove_stuff(){
remove_action('hook_location','function_you_want_to_remove',$priority );
}
add_action('init','remove_stuff');

In english this sort of translates to:

When WordPress runs the init hook, please remove the function called “function_you_want_to_remove” that is located on the hook called “hook_location” with a priority of $priority.

init is just a WordPress hook. in fact, it is the one of the earliest hooks that run when WP starts whirring… it is like priority parking. You can see most all of the hooks that run in the WordPress process again at the Codex: Action Hooks  To remove something that had a specific priority originally, you must remove_action it with the same priority.  A good practical example would be removing the Thematic blog title.

function remove_thematic_header(){
remove_action('thematic_header','thematic_blogtitle', 3);
}
add_action('init','remove_thematic_header');

Paste the above into your functions.php, reload your child theme and poof the blog title is gonzo!

Moving the #access menu is another practical example, that combines adding and removing functions.  I’ll include it here because I see this question asked all the time.

function remove_thematic_header(){
remove_action('thematic_header','thematic_access', 9);
}
add_action('init','remove_thematic_header');
add_action('thematic_aboveheader','thematic_access');

Note that we don’t have to define thematic_access, because it already is defined by thematic. We can simply add_action it to a new parking spot.

Overrides R’ Us

Thematic has a bunch of functions built in that if you define them, they automagically replace the function thematic was going to add to a specific hook, with your custom function.  In WordPress parlance, this is called a pluggable function.  Many thematic functions can be overridden by copying a thematic function to your functions.php and altering the function’s prefix from thematic_ to childtheme_override_.  The overrides completely change the car that is parked on a particular parking spot but they don’t change its location.

For instance to override the thematic_blog_description you could put the following in your functions.php

function childtheme_override_blogdescription(){
echo "Evil laugh! Now your blog is only about bacon!";
}

Refresh your theme and you will see the blog description has been taken over by bacon. , which I think is neat.  Note that with pluggable functions you do not need to also call add_action.  Doing so will add the function twice.  Most functions in thematic have this override capability, but not all.  You can browse through the extensions folder (look but don’t touch the parent theme!)

If you see something like:

if ( function_exists('childtheme_override_blogdescription') )

That’s a sign that you can use the override feature.  The full IF statement reads something like:

If you define a child_theme_override function then Thematic will add your custom function to the appropriate hook instead of its own function.

Overrides are significantly more intuitive than filters, but filters can be more elegant: the scalpel instead of a broadsword if you don’t need to change the entire function.  However, this post is crazy long, so I will leave filters for the next part of series.

Additional Resources

To help you know what hooks are available in Thematic, here are 2 visual aids:

http://www.bluemandala.com/thematic/thematic-structure.html

http://visualizing.thematic4you.com

Additional Help

I’ve tried to make this as beginner-friendly as possible, but I’ve been doing this for a few years now and so it makes total sense to me. Please let me know in the comments if something about this tutorial is not clear so that I can make it better.

Also, I don’t have time to respond to specific support requests in the comments. If you have Thematic questions post them at the Thematic Forums or contact me for some premium support.

View all posts in this series
This entry was posted in Understanding the Basics and tagged , . Bookmark the permalink. Trackbacks are closed, but you can post a comment.

20 Comments

  1. Posted August 30, 2013 at 10:59 am | Permalink

    This is really useful. I can’t believe I’m the first person to comment on it. I’ve been fiddling around with thematic hooks and such and never really understood what I was doing – just copy and paste and hope it works.

    Now I understand, thanks to you!

    • Posted August 30, 2013 at 12:01 pm | Permalink

      The good thing is that all WordPress hooks and filters work the same way. So once you have an understanding you can change all kinds of things in WordPress core, plugins and other themes. This article is Thematic-specific, but as more of an example for something more general.

  2. Andrew
    Posted November 9, 2013 at 10:41 am | Permalink

    Thanks so much for this super clear intro – just what I needed to help with some woocommerce customization I was starting to despair of :)

    • Posted November 9, 2013 at 2:46 pm | Permalink

      You’re welcome, Andrew. WooCommerce has a ton of hooks and filters. And while many are unique to WooCommerce, the basic approach still remains the same.

  3. Mike
    Posted November 11, 2013 at 3:24 pm | Permalink

    This is the best resource I’ve found yet for woocommerce hooks – I can’t believe that there isn’t a central repository somewhere online of woocommerce customisation tips. I suppose there’s no incentive for Woo to do it – it would take away from the ‘woo workers’ supply of people needing to change minor things. I’m trying to do nothing more than a simple ‘echo’ of a hook and am no nearer a fix after two full days of trying!

    • Posted November 11, 2013 at 9:16 pm | Permalink

      Hi Mike, this sure didn’t start out as a WooCommerce tutorial, but I’m glad you found it helpful. Ultimately, all hooks/filters work the same way across WordPress core and all its themes and plugins. Maybe in the future I will write a WooCommerce-specific tutorial. And to be fair, Woo does have very extensive documentation.

      • Acrane
        Posted April 10, 2014 at 8:01 pm | Permalink

        I came here because of WooCommerce!

        • Posted April 10, 2014 at 9:06 pm | Permalink

          Cool. Have anything WooCommerce-specific you think that I should write about?

          • Acrane
            Posted April 29, 2014 at 1:38 pm | Permalink

            I’ve been thinking about this… I was one of those designers angry at the non html structure of thematic and Woocommerce and having to use functions to arrange the elements the way I wanted, but I’m slowly starting to grasp everything. So, having that perspective, I think a visual would greatly help. I would want to see a visual of the default output of the actions and where in the templates they are located. I would’ve also like to have known that when I declared my “shop” page, it won’t recognize my WP page template “shop” but that I could declare it elsewhere, and use a custom loop on another shop page of my choosing. Also, in addition to the hooks for the product loops, I’d love to know a list of quick “tags” I could use to display simple product loops I create myself. For example, if I wanted to throw in a simple loop of 3 latest products in the sidebar and all I wanted to show was a thumbnail and price. You know… stuff like that :)

  4. John Lion
    Posted March 22, 2014 at 9:13 pm | Permalink

    Thanks Kathy, the priority bit was where I’ve been going wrong with remove_action(). I’ve tried using this it over the last few months, sometimes it worked sometimes it didn’t. I read this last night, today I was learning my way around woocommerce and found that I among many people couldn’t get some of the hooks working. Then yeah! Kathy said about priority! and woo make it very clear in their comments everything you need to know. I love learning, all the best and hope you get the urge to write some more some time. Cheers

    • Posted March 24, 2014 at 5:44 pm | Permalink

      The priority thing was something that tripped me up too when I started. Glad I could help. I’m open to writing more, I just haven’t had any inspiration lately. Anything in particular that you would like to have me cover?

      • 1klbGuerilla
        Posted May 1, 2014 at 3:56 pm | Permalink

        I’ve been wrestling with woocommerce for about a week now and have made very little progress, even though I consider myself a pretty advanced web designer.

        My sentiments were summarized here http://wordpress.org/support/topic/most-basic-customisation-seems-impossible (where I find this page), even after I learned how to use hooks.

        It seems to me that wc could be offered two different ways, one way for advanced developers (as it is) and another for everyone else who are comfortable with tweaking wordpress themes without becoming programming experts.

        I stumbled across a $95 plugin that essentially replaces the woocommerce templates with a more familiar theme template, using their shortcodes: http://d7j863fr5jhrr.cloudfront.net/wp-content/uploads/2012/11/Single-product-Content-template1.jpg

        I know there are wc shortcodes that already exist (that we don’t have to pay for) and it would probably bridge the giant gap for everyone if there was a basic set of sample templates like the one in that photo that used wc’s own shortcodes instead. Even if they used ?php echo do_shortcode(‘[shortcode_goes_here]’); ? for each shortcode.

        If there were already sample templates like that for single-product.php / content-single-product.php, I would cry tears of joy.

        • Posted May 2, 2014 at 11:57 am | Permalink

          Wow, interesting. It seems like you and @Arcane both would appreciate a bit of a code to visual translation. I can’t make any promises (especially because I have a month-long training camp coming up in Brazil), but that’d be something interesting to write about.

  5. Samuel Gates
    Posted May 30, 2014 at 3:17 am | Permalink

    Your explanation is great! This is very helpful for wrapping my head around these concepts.

  6. Michael Van Den Berg
    Posted June 10, 2014 at 11:07 am | Permalink

    Hi Kathy! You’re awesome! ;) I had a bit of a difficulty understanding hooks, but after reading this it's much more clearer now! Thank you!

    • Posted June 10, 2014 at 11:59 am | Permalink

      Hooks and filters don’t make the most sense when you start. I’m glad the article was able to help you.

  7. Davide
    Posted September 14, 2014 at 3:18 pm | Permalink

    Thank you :) for this guide… you have saved my life :)

    • Posted October 30, 2014 at 9:09 pm | Permalink

      You’re welcome Davide. I’m glad you found it helpful. Cheers!

  8. Michael Smtih
    Posted October 30, 2014 at 7:22 pm | Permalink

    Thank You! You are the first person who has been able to explain that in a way i could follow AND implement.

    • Posted October 30, 2014 at 9:08 pm | Permalink

      You’re welcome, Michael. Glad it could help and thanks for stopping by.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

You may use markdown syntax in the comments.

Comment Spam Protection by Spam Hammer

This site's anti-spam requires Javascript; enable it and refresh this page to continue.

NoScript Users: Whitelist the domain services.wpspamhammer.com and refresh.