Understanding WordPress Hooks: Knowing What to Use Where

Understanding WordPress Hooks: Knowing What to Use Where

Recently, we explored getting started with WordPress hooks and look at what WordPress hooks are and how to use them. One problem with hooks is that it isn’t immediately obvious which hook to use in what situation, and what parameters you have at your disposal.

In today’s post I’ll show you a few tricks that I use to figure these things out. We’ll browse through some WordPress core code, looking at hook references and use some common logic along the way.

If you’ve been wondering how coders know what hook to use, I hope you’ll find some answers here.

Before moving on I recommend reading A Quick (and in-Depth) Guide to WordPress Hooks if you’re a relative newcomer to hooks as it will help you better understand this article.

Let’s get started.

Location, Location, Location

Just like in real estate, using hooks is all about location. We learned in the previous article that whenever WordPress encounters a hook, it executes all functions associated with it. When this happens (i.e. a hook is found in a particular location in the WordPress core code) is extremely important. Here’s an example to show you why:

Let’s say you are building a plugin which will tweet your mood whenever you save a post. The mood to tweet is stored as a custom field for the post. Here’s some incomplete code which would do that if we fleshed it out:

So how could this code depend on where the hook is called? It stands to reason that there is a function in the source code which takes care of saving a post along with its meta data. If the save_post hook is called before this is done, our function will fail.

The meta value for the post will not have been saved so we will end up tweeting an empty mood. As you can see, the location of the hook matters a lot.

Finding Hook Locations

There are a couple of ways you can go about this. In our example above the question is: Is the hook fired before or after a post is saved? You can answer this with a simple test by echoing a custom field and exiting:

If the hook is fired after the post is saved you should see the meta value displayed when you save a post. Keep in mind that our method can be misleading, which is why it isn’t my recommended method.

Imagine you created a post with the mood value of “Happy” and saved it as a draft. The next day you modify the post and change the mood to “Sad” and publish the post. Even if the hook is defined before the post is saved, your test function will return a value – but it will be the incorrect one. It will be the meta value from the previous draft – the new value has yet to be saved.

First of all, type “save_post action” into Google and you should find yourself on the Codex Page for it very quickly. If you read the page it actually contains are answer: “this action is triggered right after the post has been saved.”

So that was pretty easy, but not all hooks have such an extensive description. If the sentence above were not there, we could turn to the “Source File” section at the bottom of the page. This section exists for most hooks and has information about where it is triggered. In this case it is “Triggered by wp_insert_post and wp_publish_post in wp-includes/post.php.”

Let’s head over there now and take a look at the source code for wp_publish_post().

For here it is pretty obvious that the post is saved before our hook. Even if you don’t understand the code, all the hooks are at the end of the function, which is a strong indication.

Finding Hook Parameters

When a hook is called, a number of parameters are passed to it. If you know the name of the hook and how many parameters it takes you can create a hooked function, but you don’t know what these parameters are. Let’s look at the post_class filter, which you can use to modify classes added to posts.

In the filter reference there’s no page for this hook, but it does say it is called from the get_post_class() function. If you look at the documentation for that function you can find that it is defined in wp-includes/post-template.php. Searching that file for the call to this hook yields the following section:

The PhpDoc documentation gives us everything we need to de-cypher the parameters. Based on this we can use post data to add some dynamic classes:

The code above shows how we can add an “old-post” class to our posts if they were published before 2010.

A Note About Initialization Hooks

WordPress contains a number of init hooks which allow you to add functionality to WordPress at specific times. In many cases the use of these can technically be interchanged, but this may cause confusion or unexpected behavior.

The three most commonly used ones are init, admin_init and widgets_init. It’s important to know when to use these. Luckily, the documentation is pretty clear. Do you want to register an admin menu? Technically it could work with some of the initialization hooks, but you really should use the admin_menu hooks.

I know this because the documentation for add_menu_page() clearly shows this. On the other hand, if you want to add a custom post type you should use the init hook. This is obvious from the article on register_post_type().

The problem with these init hooks is that everyone knows they run pretty early, but very few people know exactly when. So when a developer wants to add a feature, they can sometimes fall back on an init hook, thinking that this will cause the least problems.

Make sure to ready the documentation of the functions you are using and you will mostly be in the clear init hook-wise.


In conclusion, there are basically two methods you can use to figure out how to use hooks: documentation and source code.

Your first step should usually be documentation since that will give you the clues needed to hunt down the needed hook in the source code.

I recommend the official Hooks Reference, or Adam Brown’s Hook Reference. The second resource is only up to date until WordPress 3.9, but it can still be a useful tool.

If you have other awesome methods to remember or figure out hooks, please share them in the comments below.