WordPress Hooks, Actions, and Filters: What They Do and How They Work

hook | wordpress hooks actions and filters

This article introduces one of the most important topics in WordPress development: WordPress hooks, including action hooks and filter hooks. Hooks are at the core not only of how WordPress plugins work, but nearly all code in the WordPress ecosystem: most WordPress themes use hooks heavily, as does “WordPress core” itself. WordPress hooks are absolutely a must-know topic in WordPress development.

We’ve jam-packed this explanation of WordPress hooks with a helpful overview video, key points, a detailed infographic, a quiz, and even a summary limerick(!). That’s because it’s not just one of our normal articles: It’s a sample chapter from our “learn WordPress development” course Up and Running.

If you like this article, be sure check out Up and Running. There’s about 40 more chapters where this one came from. We stand behind it as the single best guide to WordPress development out there.

Serious About Learning WordPress Development?

Get Up and Running Today

Up and Running is our complete “learn WordPress development” course. Now in its updated and expanded Third Edition, it’s helped hundreds of happy buyers learn WordPress development the fast, smart, and thorough way.


I think anyone interested in learning WordPress development NEEDS this course.

Before I purchased Up and Running, I had taught myself some WordPress code, but lacked direction. Watching the course’s videos was like a bunch of lights being turned on.

I went from being vaguely familiar with how themes, functions and WordPress itself worked to mastering these. Everything became much clearer.

I very happily recommend this course to anyone willing to listen.”

–Jason Robie, WordPress developer

Take the next step in your WordPress development journey!


Key Takeaways about WordPress Hooks:

  • WordPress hooks are a crucial WordPress feature that allows developers to insert custom code into WordPress’s PHP processing, at specified junctions during that processing.
  • Developers write this custom code in PHP functions called hooked functions. Two kinds of hooked functions exist: actions and filters.
  • Two kinds of hooks exist: action hooks and filter hooks. Action hooks “hook in” actions, and filter hooks “hook in” filters.
  • Filters are passed code or markup by their filter hooks; they modify what they are passed, and must return the result back for WordPress to use in its regular processing.
  • Actions, by contrast, do not need to return a value, and often are not passed specific parameters by their action hooks.

In this chapter, we’re covering one of the most important ideas in WordPress plugin and theme development: hooks. You could also say that this chapter is about “actions and filters,” because actions and filters are the two kinds of functions that interact with WordPress hooks.

Understanding hooks isn’t all that easy, partly because the terms themselves are rather tricky to visualize and distinguish from one another.

But the payoff is huge: as a developer, we find that working with filters and actions is probably the most common way we interact with WordPress. And over time, it’s become one of our favorite things to do in WordPress, as well.

Terminology — Hooks vs Actions vs Filters

Particularly in this case, understanding terms—”hook,” “action,” and “filter”—is half the battle. The WordPress Codex, for example, uses all three terms very casually and inconsistently.

The definitions we use in this chapter are the most common ones you’ll find in WordPress generally, and they’re the best for actually understanding what’s going on. So stick with the understanding we present here, and don’t get discouraged when other people use these terms in multiple ways.

How Hook, Action, and Filter Relate

Actions and filters are custom functions. They hook into action hooks and filter hooks.

This is just to get started; don’t worry if this doesn’t make total sense at the moment:

  • A hook is a place in WordPress’s code that can get functions added to it. When you create a hook, you give yourself and other developers the opportunity to add in additional functionality at that location.
  • Hooked functions are custom PHP functions that we can “hook into” WordPress, at the locations specified by its hooks.
  • Two types of hooked functions exist: actions and filters. Filters modify existing output, while actions can do any type of custom functionality.
  • Hooks come in two types—action hooks and filter hooks—based on which type of hooked function they accept.

Good so far? Don’t worry either way, and let’s move on. (At the end, you may want to come back and see if the above makes more sense.)

Here’s a visual summary of this information. It’s also in WordPress Hooks in Resources.

wordpress hooks visual guide

Don’t try to get into it too far for now—for now, just understand that “Actions hook into action hooks, and filters hook into filter hooks.”

WordPress Hooks: Bringing Outside Contractors into the WordPress Factory

Hooks are how WordPress invites the “outside contractors” that help it do its work.

To explain hooks, we’ll return to our central analogy of WordPress as a factory.

Remember that WordPress calls on outside contractors to do some of its work. Our contractors don’t have a permanent place in the WordPress factory—they’re stuck outside until they’re invited in by the factory itself.

For our purposes, these outside contractors come from two places:

  1. Plugins
  2. The functions.php file inside the parent or child theme

The outside contractors themselves are the custom code in the plugins and functions.php that alter the functioning of the WordPress factory.

Hooks pull in outside code, in specified ways and at specified places.

Hooks—both action hooks and filter hooks—are how WordPress calls on these outside contractors. In other words, WordPress hooks pull in outside code, in specified ways and at specified places.

How WordPress Calls on its “Contractors”

We can think of WordPress “hooks” as actual giant factory hooks, which the contractors ride in on, like this:

Each hook is labeled with a specific name, such as wp_head, corresponding to a part of the WordPress factory’s process (in the case of wp_head, the process of building the page’s HTML <head> section).

These hooks travel out to the lobby so that contractors can ride them in, and they do it in a specific order. The wp_head hook travels out to the lobby and back right before <head> completes, the wp_footer hook travels to the lobby and back right before <body> completes, and so on. So the contractor is always riding his hook directly to the active, to-be-worked-on part of the factory.

When a contractor wants to be part of a specific process, he waits for that hook to show up at the entrance—and rides that hook straight into the proper part of the factory.

If the contractor didn’t ride the proper hook in, he couldn’t get where he’s going in the factory. Hooks are what “invites” outside code (from functions.php, plugins, and so on) into defined areas of WordPress’s PHP processing.

Two Kinds of Hooks, Two Kinds of Contractors

We’re halfway to understanding WordPress hooks, actions, and filters. The other part is a bit more specific: the lobby has two kind of hooks, action hooks and filter hooks.

Look back up at the WordPress Hooks diagram, and let’s understand action and filter hooks.

Action Hooks

Action hooks tend to get dangled at milestones: for example, “you’re almost done building the page’s <head> section” for the wp_head action hook, or “you’re almost done building the page’s <body> section” for the wp_footer action hook.

When contractors ride action hooks into the factory, they tend to do just about anything they want: add a bunch of stuff to the page, or do completely other things like log an error or even send an email.

Filter Hooks

Filter hooks work a bit differently. Contractors who ride in on action hooks can do whatever they want, and have no responsibility to anyone. But contractors who ride in on filter hooks actually insert themselves in the normal workers’ process: they’re given something to handle—say a block of text—and have to give that same block of text (slightly modified, probably) back to the regular worker, via a PHP return statement.

So a contractor using a filter hook generally doesn’t just do whatever he wants; he works with the piece of work that he’s given in his section of the factory. “This section works on the post title,” the section’s manager might say. “Do whatever you want to the post title, but if you don’t hand me back the post title after you’ve made your changes, this whole process won’t work properly.”

What Are These Contractors?

Our “contractors” are custom PHP functions that we (or anyone else) can write.

Hopefully we’re making sense so far; now we’re going to get a bit more technical so you can actually start writing these things.

The contractors—both those hooked to action hooks and those hooked to filter hooks—are custom PHP functions that we or anyone else can write.

Because these functions make it into WordPress by attaching themselves to WordPress hooks—that is, being “hooked in” from outside—the formal term for them is hooked functions.

There are two kinds of hooked functions:

  1. Actions, also called action functions, which hook onto WordPress’s action hooks, and
  2. Filters, also called filter functions, which hook onto WordPress’s filter hooks.

Let’s look at one of each.

Example Use of a Filter Function

Our first contractor is a filter or filter function. In other words, it’s a function that rides a filter hook into the factory.

/* Environment: We're in functions.php or a PHP file in a plugin */

function wpshout_filter_example( $title ) {
	return 'Hooked: ' . $title;
add_filter( 'the_title', 'wpshout_filter_example' );

Here’s what to know about the code above:

  1. Our filter—that is, the code that hooks into our filter hook—is indeed a PHP function, hence the function { }.
  2. wpshout_filter_example is the name of the filter function.
  3. ($title) is the function’s single argument. It’s what the WordPress factory (WordPress core itself) passes to the contractor to work on.
  4. return 'Hooked: '.$title; is the work the function does. It adds the word “Hooked: ” to the title it was passed, and gives it back to WordPress core to continue to process regularly.
  5. return is very important: it’s how the function gives back its work to WordPress core. That line is perhaps best read right-to-left: it says: “Take the regular title and add ‘Hooked: ‘ before it, then pass it back.”
  6. add_filter('the_title', 'wpshout_filter_example'); is very important: it’s how you add filter functions to filter hooks! This merits its own bulleted list.

Now, here’s how to understand that last line:

  1. add_filter( ); is a WordPress function. It says: “Hook a new filter onto an existing filter hook.”
  2. 'the_title' is the name of the filter hook that we’re going to ride into the factory.
  3. 'wpshout_filter_example' is the name of the contractor: in other words, the name of the filter we’ve written, and that we want to hook onto the filter hook (in this case, the_title) that we’ve specified.

So the filter wpshout_filter_example() hooks onto the filter hook the_title. When it does, it simply adds “Hooked: ” to the title, and returns it back. Make sense?

The result, on a live site, looks like this:

Example Use of an Action Function

Our next contractor is an action or action function: a function that rides an action hook into the factory.

/* Environment: We're in functions.php or a PHP file in a plugin */

function wpshout_action_example( ) {
	echo "WPShout was here.";
add_action( 'wp_footer', 'wpshout_action_example' );

If you’ve understood the filter example above, you’ll understand almost everything about this example of a WordPress action:

  1. function wpshout_action_example() {} means that this action (or action function) is named wpshout_action_example() and carries no arguments.
  2. echo "WPShout was here."; is what the function does. echo is a PHP command that we’ll discuss shortly.
  3. add_action('wp_footer', 'wpshout_action_example'); is what hooks the wpshout_action_example action to the wp_footer action hook.

As we noted, the major difference from our filter example is that the hooked function doesn’t return anything. Instead, it echos (prints) a message directly onto the page. Where will this message print? It’ll print at the very beginning of the footer section—wherever the theme author has placed the wp_footer action hook.

This difference—actions can do most anything, filters must return modifications to what they’re given—is the main distinction between the two types of functions, who are otherwise quite similar.

On a live site, our action has this result:

What We’ve Learned

WordPress uses actions and filters to extend what it can do—from the silly examples we showed off today, all the way up to ultra-complex plugins like WooCommerce. We’ve learned what hooks, actions, and filters are for, and the basics of how they work.

To sum up: WordPress registers action and filter hooks at specific places in the WordPress page generation process. Any developer can then write their own functions that hook onto these action and filter hooks. Filters (or “filter functions”) modify what they’re given and hand it back via a return; actions (or “action functions”) can echo text, modify data, and just about anything else, and do not need to return a value.

The WordPress hooks system is really the gateway to full-fledged WordPress development, so don’t be afraid to go back over the material, experiment with it, and make it your own.


Summary Limerick

Here’s an idea for the books:
The system (in WordPress) of hooks.
At regular junctions
They hook in new functions,
Which change how the site acts and looks.

Quiz Time!

  1. A WordPress hook is a(n):
    1. Function containing custom code
    2. Way to pull in custom code
    3. Function that modifies custom code
  2. The following is not true of WordPress filters:
    1. They are always passed parameters by their hooks
    2. They are expected to return a value
    3. They may not change the site’s data or echo HTML output
  3. To automatically remove profanity from the site’s display of user comments, a developer would most likely use:
    1. A filter
    2. An action
    3. A methodology other than hooked functions

Answers and Explanations

  1. B. A refers to actions and filters, collectively called hooked functions: the functions that hooks pull in. C is mostly gibberish.
  2. C. Together, A and B describe how filter functions receive a piece of data (usually a string of HTML output) from their filter hook and must return a modified version of it. (Many action functions receive nothing from their action hook, and actions do not return back a value.) However, both filters’ and actions’ PHP logic can do anything—including change data, echo markup, log errors, or even send emails—and so C is false.
  3. A. Filtering content is a classic use of WordPress filters, as the name implies. The filter function would take the raw comment content, remove or alter words matching an array of targets, and return the modified content to the filter hook, for processing into the comments section of the webpage being constructed.

If you liked this chapter on WordPress hooks, you’ll love our full guide to WordPress development: Up and Running! It goes into way more detail about the depths of using hooks. Up and Running also covers all the key topics in WordPress development in a clear, well-ordered, and thoughtful way. You’ll learn way quicker than you could otherwise—clearly, logically, and without sidetracks.

Get Up and Running Now

And if you want some more hands-on learning about WordPress hooks, you can watch a free video webinar Fred led on the topic.

Image credit: Les Chatfield

51 Responses


  • Northwind says:

    This is fairly awesome, to say the least.

    Question: In “Example Use of a Filter Hook”, the last line is “add_filter(‘the_title’, ‘wpshout_filter_example’);”

    Where does ‘the_title’ come from? I see the name of the function and the name of the argument/variable ($title), but not sure where ‘the_title’ comes from. Is that a WP core function reference? Saying to do the function and add the full “return”-ed value as the new value for ‘the_title’ function, in the core? Or am I way off?

    Other than that confusing bit, this article is just what I needed!

    There’s some very specific functionality I need for a site and digging through available plugins leads to disappointment on a variety of levels for a variety of reasons. Developing my own plugin is what I’ve been advised, but thus far the task seems daunting at best. Your article here, however, makes it seem much more doable.

    • fredclaymeyer says:

      Hi! I think I understand your question. Basically, the_title is the name of an existing hook (specifically a filter hook) that already exists in WordPress core.

      Most of the time when you work with hooks, you’ll be hooking into preregistered action and filter hooks that already exist in WordPress core.

      Does that answer the question?

      • Northwind says:

        It does indeed. Sorry for my confusing verbiage. But you pounded that nail. Answered it completely. Many thanks! To be honest this is my first visit to this site – via “The WhiP.” I will definitely be more regular now! Thanks so much. 🙂

  • prodsign says:

    Nice article… Keep sharing 🙂

  • Your factory analogies are the best analogies I’ve seen yet when explaining WordPress hooks! I’ve read so many articles on hooks and every time I read, it gets clearer, but never quite there. This was the finishing touch. Exactly what I needed to completely understand.

    Also didn’t realize the Codex was so inconsistent – it probably explains why hooks take some time to make sense to people when the terms get all mixed up. I appreciate clearing that up for me too.

    Loved it! Thanks for writing this! 🙂

    • fredclaymeyer says:

      Thank you so much, Rachel! In my experience, hooks are one of the hardest things in WordPress to get an intuition for—really glad we could help. 🙂

  • Nad says:

    Great analogy. I am new to WordPress and I learned a lot by reading this article.

    Great job guys from Paris.

  • Mel Wilson says:

    You did a really great job explaining this! I’ve been using WP for about 5 months now, and I always wondered what hooks and filters meant.

  • Muhammad Rizwan says:

    In your first filter hook example, you have used a single argument $title in wpshout_filter_example function , where did $filter comes, i mean it is coming from core wordpress, where its location in core wordpress code?

    • fredclaymeyer says:

      Hi Muhammad, Thanks for the question. The code again is:

      function wpshout_filter_example($title) {

      return 'Hooked: '.$title;
      add_filter('the_title', 'wpshout_filter_example');

      There is no variable $filter in this code. We’re hooking into a preexisting filter called the_title, which you can check out here.

      WordPress knows what the single function argument $title means because of which filter we’re hooking into: the_title.

      So $title could be named anything—like just $var—but it would still refer to the post’s title. That’s because we’re hooking into the_title, and what the_title gives us to play with is the post’s title.

      Does that help?

      • Kirill Polevsky says:

        I have the same question as Muhammad had. Although your explanation above clears things a little bit more, I still don’t grasp it completely.

        A function which is fired when we use a certain filter hook can accept arguments, right? And you’re saying that if we use for example the_title filter hook, then we can pass an argument called $title (or we can name it however we want, e.g. $var), which will make changes to the title of the post we’re working with.

        The problem is, I don’t always know which arguments I can pass to the function. I know that I should find answers in the WP Codex, but in some cases it just doesn’t describe things as clearly as needed. For example the title action is documented thoroughly, but when I came across save post action, I was confused.

        In the first example they use $post_id parameter, which seems understandable, but then in the second example they add multiple parameters ($post and $update). Where do those parameters come from? Isn’t WP Codex supposed to describe them at the beginning of the article similar to what it did with the article on the_title hook?

        I just want to understand, are we dealing with a not very detailed documentation here, or am I missing on something?

        Thank you.

        • fredclaymeyer says:

          Kirill, that’s an excellent question.

          I believe you are correctly understanding how to use arguments for action and filter hooks.

          For the save_post question: The Codex’s documentation does indeed seem incomplete.

          The Function Reference, however, does directly list and describe the three parameters save_post will accept: https://developer.wordpress.org/reference/hooks/save_post/

          The Function Reference also links to the source code for save_post itself, where you can see directly what each of the three possible parameters means: https://core.trac.wordpress.org/browser/tags/4.4/src/wp-includes/post.php#L3385

          So you may want to use those references as well if the Codex is failing to make clear what parameters you may use for a given hook.

          Does this help?


          • Kirill Polevsky says:

            Thank you, Fred. This does help.

            Will make sure to check both The Codex and The Function Reference when searching for answers 🙂


  • BJ says:

    Thanks, very easy to follow and understand…. BUT, why do I always see numbers after actions and filters- there was no mention of them here…
    e.g. add_filter(‘woocommerce_shipping_method_chosen’, ‘reset_default_shipping_method’, 10, 2);

    • fredclaymeyer says:

      Hi BJ,

      Good questions, both!

      1. The numbers you’re seeing are two additional optional function arguments for add_filter() and add_action(). The first is “priority” – it defines the order in which multiple functions added onto the same hook will be run. (This can be important, for example if one hooked function makes a change that another will need to use.) 10 is the default; small numbers execute first and large numbers execute after. The second is an argument that lets you manually specify the number of arguments the hooked function accepts – two in the example you gave.

      2. You can indeed echo in a function that is hooked using add_filter. As always with echo, this will print whatever you’re echoing straight onto the page. However, you do also need to end your hooked function with return. For example, if you hook into the_title, and then don’t return anything, all the titles on your site will go blank.

      Does this answer your questions? I’d be happy to look at specific code if you’re having issues.


  • Surja says:

    Thank you for the article, the factory analogy is an excellent idea to teach beginners the fundamentals of hooks. I’ve never seen it being explained so clearly like the way it is done here.

  • upen singh says:

    Thanks a lot! nice description about HOOk

  • mukesh says:

    now finally i understand the concept of hooks. how clearly you describe this concept through factory example. really it was awesome. many time i have googled this concept but not found like this. thanks .

  • Anil Kumar says:

    Thanks for sharing this wonderful article.

  • Anisha says:

    An impressive post on Hooks & Action. Thanks for the post.

  • pramod khatiwada says:

    Awesome Explanation and example is not silly though, it’s great. Clearly understand able.

  • Simone says:

    Thanks so much for this article. Lovely! Perfect introduction! Please do write more!

  • The way you present Action Hook and Filter Hook are marvelous. Infographic presents it more clear and to the point. Thanks.

  • Tim says:

    The “Hooked: ” is showing up twice in my code and I can’t figure out why?


    According to the WP dev docs, the_title now takes a second arg, $id. I tried setting that to null but am still getting two “hooked: “‘s to print?