If you’ve been working with WordPress for any length of time, especially if you’ve been doing anything that involves the use of code, you’ve probably heard of WordPress hooks. You’ve also, then, probably heard of Actions and Filters. If you’re a seasoned WordPress pro, these terms are second nature to you. For new users, however, they can be rather obscure. As someone who started with WordPress with ZERO knowledge, I did a lot of reading to better wrap my mind around these concepts. There are some good posts out there that helped me more than others but then there are many that describe the idea of WordPress hooks in ways that are still tricky for non-technical users to grasp. In this post, I want to dive into what exactly WordPress hooks are, why they exist and how to use them. Since applying them to real-world scenarios will only reinforce the concept, I’ll also include code examples to break down for you. Now, let’s get started.
Why do WordPress hooks exist?
To fully understand the WordPress hook system, you need to know why it’s there in the first place. WordPress is a content management system (CMS). It’s a framework that is built on. It can be modified to do almost anything and fit almost any need.
Think of WordPress as a closed off engine for your website that runs its own internal processes and makes everything go. The reason I suggest thinking of WordPress as “closed off” is not because it’s inflexible but, rather, because we do not want to touch the inside of it…meaning we never want to modify the core WordPress files. If we modify the core, we run the risk of seriously screwing things up, breaking our website altogether, and losing any changes we make when WordPress is updated (which has to be done).
Since WordPress core is something we leave alone, there must be some way to interact with it from the outside world so that we, as end users, can do our customizations. One of the methods WordPress provides for this is the hook system. That’s why WordPress hooks exist: to interact with and manipulate the core without actually changing the core.
What are WordPress hooks?
Now that you have that basic concept of why WordPress hooks exist, we can discuss what they are. As I mentioned earlier, you’ve probably also heard of actions and filters when you hear about hooks. That’s because the term hooks is the collective term for both actions and filters; actions and filters are hooks. Let’s take a look at each of these.
WordPress Actions – Do Something New
Action hooks are, in my opinion, easier to comprehend at first so I’ll start with them. An action in WordPress is an event that occurs at a specific time. When I was first learning, I thought of them as something that happens at a specific location. While this is true to an extent, it’s not entirely accurate. When WordPress runs its internal processes, certain events happen at certain times. For example, the init
event happens very early in the process, (before WordPress itself is fully set up) while template_redirect
occurs later, after WordPress is fully set up and anything within it can be accessed (i.e. posts, pages, etc.). Adding an action at these points will let you execute your own code at these times. Therefore, if you want to do something after a post has loaded, the init
point will be too early because the posts will not have loaded yet. For a full list of WordPress actions, see the WordPress Action Reference.
WordPress Action Anatomy
Again, actions will let us take action (a.k.a. run our own code) at the time we need. With that in mind, let’s break down the anatomy of the action structure and what makes running actions possible.
do_action()
Actions aren’t just there magically. To run an action, it has to be made possible. This is done by way of the do_action( $tag, $arg1, $arg2, $etc )
function, a very simple function that takes a tag and any number of arguments. The only required part of the function is the tag, which you can think of as the actual hook, which I’ll elaborate on in a minute. For example, do_action( 'run_my_custom_action' )
sets up a hook that will be executed when WordPress gets to the point where it was added. The other parameters are for passing custom arguments to that can be used within your code.
For those of you who are less familiar with functions and parameters/arguments (for all intents and purposes, arguments and parameters mean the same thing – information we pass into the function), you don’t need to pay much attention to this function in general. Just know this is what makes the next part I’m going to discuss possible.
add_action( $tag, $function, $priority, $args )
The add_action()
function is what will “hook” our own function onto the do_action()
we need to utilize. In the preceding example, we had a tag of run_my_custom_action within that function. The reason that tag is required is because it’s what identifies the hook we need to hook into. Without the tag, our code has nowhere to hook into.
The arguments for the add_action()
function are:
- $tag (required, string) – The name of the tag that is used in the do_action() function.
- $function (required, string) – The name of the function to run. You can also use an anonymous function if you know what that is but, for now, that’s outside the scope of this post. I’ll cover the function parameter next.
- $priority (optional, integer) – This parameter is an integer (whole number) and defines how early/late a function should run. This really only comes into play when an action is run multiple times for different purposes. For example, you might want to run your code at an earlier time than what a plugin is running its code on the same action hook. The default is 10 but you can make it 1, 99, etc. The lower the number, the earlier it runs.
- $args (optional, integer) – The is also an integer and defines the number of arguments to be passed into the function you’re running on the action. It’s not necessary and isn’t typically seen with basic action hooks.
Before getting to some examples, I want to describe the function parameter of add_action()
. This is the second parameter and is required. We need to pass in the name of the function that will contain the code we want to run. Since the name of the function is a string, it should be wrapped in single or double quotes, either is fine. We’ll be creating a new function for our examples so, if you’re not familiar with this stuff, pay attention to the function my_function_name(){}
part, which is the syntax required for creating a named function in PHP.
Examples of WordPress Actions
To demonstrate, let’s look at an actual example.
Redirect the user
//* Redirect the user if they are logged out add_action( 'template_redirect', 'rv_redirect_if_logged_out' ); function rv_redirect_if_logged_out() { if ( ! is_user_logged_in() && ! is_page( 2031 ) ) { wp_redirect( get_permalink( 2031 ) ); exit; } }
In this example, if the user is not logged in, we’re redirecting them to a specific page (i.e. the front-end login page). Let’s break this down, piece by piece.
In the add_action() part, take note of the template_redirect
because this is the tag. It indicates when our function is going to run. Next, the rv_redirect_if_logged_out
is just a random (but descriptive) name I decided to give my function.
Since we’re telling WordPress to run a function with the name of rv_redirect_if_logged_out, we need to create that function, which is done with:
function rv_redirect_if_logged_out(){ }
Our code is contained within the curly braces. As a whole, this function checks to see if the user is not logged in and if the current page does not have the ID of 2031, which for our example is the ID of the login page. If both of these checks are true, it redirects the user to that login page. You can read more about the is_user_logged_in(), is_page() and wp_redirect() functions if interested since I won’t be going into detail on them.
WordPress Filters – Change Something
Moving to filter hooks, we will need to change our mindset a bit. Whereas actions add/do something new at a given time, filters change something. They modify what’s already there. When you add a filter, you do the following:
- Intercept some data prior to it going through its normal process and/or being displayed.
- Pass that data into a function to run it through our own code.
- Return the modified data to its originally scheduled itinerary.
Filters also differ somewhat from actions in that you don’t have to determine the appropriate time to run certain code. For example, a redirect to an internal page using a WordPress function like get_permalink()
, such as the one we did in the action example, has to be done after WordPress is fully set up so that it can access the post with the provided ID. We could have tried that example using the init
action (which would have worked with evaluating whether the user is logged in or not) but that action hook occurs before WordPress has fully loaded and, as a result, the posts are not yet available. Therefore we used template_redirect
because it occurs at the right time. This is not really the case for filters because we’re just changing data when it’s reached, whenever that happens.
For a list of default WordPress filters, see the Filter Reference.
WordPress Filter Anatomy
For the most part, the anatomy of a filter is the same as that of an action but with a few differences.
As with actions, filters don’t come out of thin air. To add filterable content, a developer must use:
apply_filters( $tag, $value, $var1, $var2, $etc )
- $tag (required, string) – We’ve discussed the $tag value with action hooks and it’s the same for filters.
- $value – (required, mixed) – Here, we must pass the value/content that is to be filtered. I’ll explain more on this soon.
- $var1, $var2, $etc (optional, mixed) – Like with do_action(), you can send extra data into the function you run in the form of variables. That’s what these are.
In a bit, I’ll come back to apply_filters() to show an example of how filters are created. Once we’ve looked at add_filter(), revisiting this should help put everything into more perspective.
add_filter( $tag, $function, $priority, $args )
The add_filter()
function is what will “hook” our own function onto the apply_filters()
.
The arguments for the add_filter()
function are:
- $tag (required, string) – The name of the tag that is added in the apply_filters() function.
- $function (required, string) – The same as add_action()…name of the function to run.
- $priority (optional, integer) – The same as add_action().
- $args (optional, integer) – The same as add_action().
The function we create and pass into add_filter() as the second parameter is similar to add_action() but there are a few key differences to note. First, we need to pass in the data we’ll be using and returning to the original value. Second, we must return the data. Never echo or print anything inside add_filter() because, like I mentioned earlier, we are simply changing existing data and returning it to its normal process. This means that if the data gets printed to the screen in that process, it’s already taken care of. Therefore, always make sure to use return
.
Examples of WordPress Filters
Filter the content
//* Add a simple comment after a post's content add_filter( 'the_content', 'rv_add_comment_after_post' ); function rv_add_comment_after_post( $content ) { if ( is_singular( 'post' ) ) { $content .= sprintf( '<p>%s</p>', __( 'Thanks for reading my blog post!' ) ); } return $content; }
Here, we’re adding a very simple comment after a single post’s content using the_content
filter. In this filter, the content of a post is passed into our function (which we assign the variable $content) and, if the post is a single view (not archive) and the post type is “post”, we’ll append a paragraph onto the end that says “Thanks for reading my blog post!”. Finally, we return the value of $content. If the post was not a singular post, the comment is never added and the original content is returned, effectively doing nothing.
Notice how we passed in some data and returned that data at the end?
Returning to apply_filters()
Now that we’ve seen the process of filtering data, let’s look at how apply_filters() works to add some depth to our understanding. Here’s a simple bit of code that adds a shortcode and allows the user to filter what is returned/displayed when that shortcode is used.
//* Add an example shortcode add_shortcode( 'example_filter_shortcode', 'example_filter_shortcode_function' ); function example_filter_shortcode_function() { $original_value = 'Some data or text is stored in the $original_value variable.'; $filtered_value = apply_filters( 'filter_the_original_value', $original_value ); return $filtered_value; }
The only parts of this code that you need to pay attention to are the lines setting the $original_value and $filtered_value variables. This code can be cleaned up but I’m showing it this way to highlight what’s going on. First, we give $original_value a simple string value. Then, we set the value of $filtered_value to whatever is returned from running add_filter( 'filter_the_original_value', 'function_name' );
, where function_name() modifies $original_value (as you can see by the second parameter in apply_filters()).
Finishing Up
WordPress hooks (actions and filters) are some of the most important tools available to us as WordPress users. They give us tons of options and power to customize WordPress to meet our needs. Understanding what they are, why they exist and how to use them will greatly increase your ability to take advantage of the flexibility WordPress provides. Now that you’ve (hopefully) gained a better understanding of the WordPress hook system, it’s time for you to go learn more actions and filters that you can have fun with. Explore the core WordPress hooks by browsing the Action and Filter Reference pages, reading documentation of your plugins and themes to see what hooks they have available, and creating your own hooks to extend your own work. Good luck!
Featured Image Designed by Freepik
govertz says
Youre right, it’s a difficult subject to explain, and to understand. It takes a lot of reading to get it fully, and this is a very good read, and I feel a bit wiser with actions and filters. Thanks.
I’m not the one to point fingers, but I believe there’s a typo, in the filters section, in this sentence. “The function we create and pass into add_action() as the second parameter is similar to add_action() but there are a few key differences to note.” Two times add_action() shouldn’t it be add_filters(), the first time? 🙂
Anyway, thanks for a good read.
Ren says
Hi, govertz. Yes, you are correct and thank you for pointing that out. That sentence should have started with The function we create and pass into add_filter(). Sorry if it caused any confusion.