WordPress Hooks: Actions and Filters

If you understand WordPress hooks you understand one of the key elements that makes WordPress powerful. You also gain a sense of how well theme/plugin authors understand WordPress, and how friendly their code is to extend.

There are two types of hooks available in WordPress:

  1. Actions
  2. Filters

Both allow you to call a function at certain points in time, but they differ in their utility.

Actions

Do something at a specific time.

Actions are typically used to manipulate the flow of events (e.g. redirecting a user to a certain page after login), or to append/remove certain events.

To call your custom function for a particular action you would add something like the following to your functions.php file:


function my_custom_function() {
  // do my thing
}

add_action( 'the_action_name', 'my_custom_function' );

A common use case for this is wp_enqueue_scripts, which is used to add additional scripts and styles for the front-end of your site.


function custom_styles() {
  // add my custom stylesheet
  wp_enqueue_style( 'custom-styles', 'my-custom-style.css', false ); 
}

add_action( 'wp_enqueue_scripts', 'custom_styles' );

This ensures your code is called at the proper time, and included at the proper place.

Actions can also occur just before, or after, another action that you would want to manipulate. An example of this is save_post, which is triggered “whenever a post or page is created or updated, which could be from an import, post/page edit form, xmlrpc, or post by email.”


function custom_save_post( $post_id ) {
  // do something when a post is created/updated
}

add_action( 'save_post', 'custom_save_post' );

The save_post action also passes some data you can use in your custom function, namely the $post_id that you can use to retrieve information about the post that was just created/updated. By default the save_post action passes just that one piece of information, but you can use the following method to access additional data:


function custom_save_post( $post_id, $post, $updated ) {
  // do something when a post is create/updated - now with more data!
}

add_action( 'save_post', 'custom_save_post', 10, 3 );

In the snippet above the add_action call has two additional parameters this time.

The 10 value represents the priority that your custom function should run at. Lower number execute sooner, and functions with the same number will execute in the order they were added to the action.

The 3 value represent the number of arguments you expect in your custom function. In this case three are expected and the custom_save_post function has been updated to accept three parameters: $post_id, $post, and $update.

View the full actions reference on the WordPress Codex

Adding Actions to Your Plugin/Theme

Now you know how to use existing actions, but what about adding your own?

Wherever you’d like to allow someone to perform a custom action (sending an email, updating data, recording statistics, etc.) you can add an action using the do_action function.

For example if you had created a shopping cart plugin it may be useful for someone to perform actions after something has been added to the cart. In that case you would end up with a function like:


function my_item_add_to_cart( $item ) {
  // code to add the item to the cart
  // ...
  // item has been added to cart

  do_action( 'after_my_item_added_to_cart' );
}

This could be made more useful by passing information about the item that was just added to the cart:


function my_item_add_to_cart( $item ) {
  // code to add the item to the cart
  // ...
  // item has been added to cart

  do_action( 'after_my_item_added_to_cart', $item );
}

Now anyone can hook into your custom after_my_item_added_to_cart action:


function custom_after_cart_item_added( $cart_item ) {
  // do something after an item is added to the cart, and we have the $cart_item information if we need it
}

add_action( 'after_my_item_added_to_cart', 'custom_after_cart_item_added' );

You can pass as much information as you’d like through your custom action simply by adding more parameters to your do_action call. For example:


function my_item_add_to_cart( $item ) {
  // code to add the item to the cart
  // ...
  // item has been added to cart

  do_action( 'after_my_item_added_to_cart', $item, $customer_id, $shop_id );
}

Now you’re also providing the $customer_id and $shop_id if needed as well. It’s up to the user to determine what data they would like to use by specifying the number of arguments they’re expecting. If they wanted all three arguments they would have a function like:


function custom_after_cart_item_added( $cart_item, $customer_id, $shop_id ) {
  // do something after an item is added to the cart, and we have the $cart_item, $customer_id, and $shop_id if we need it
}

add_action( 'after_my_item_added_to_cart', 'custom_after_cart_item_added', 10, 3 );

That’s it! Now you know how to use existing actions provided by WordPress, or custom themes/plugins, as well as defining your own to make your themes/plugins more powerful in the hands of your users.

Now we dive into the second type of hook: filters.

Filters

Manipulate data before it is used.

Filters are typically used to manipulate data before it is used. This could be after something is read from the database, before something is saved to the database, before a query is performed, or before something is displayed to a user.

The format for adding a filter is similar to actions, but the function to call is add_filter.

For example, using filters you can modify the content of a post/page before it is displayed on the site:


function my_custom_function_behold( $content ) {
  // replace all occurrences of "look" in the content with "behold" 
  $content = str_replace( 'look', 'behold', $content );

  return $content;
}

add_filter( 'the_content', 'my_custom_function_behold' );

One thing to note with filters is that you need to return the data your are modifying in your custom function, otherwise you end up with an empty value.

Similar to actions you can also provide the priority for your custom function, as well as the number of arguments expected.

View the full filters reference on the WordPress Codex

Adding Filters to Your Plugin/Theme

Wherever you have data that is hard-coded is a possible candidate for a filter. This allows other users to modify the data for their needs, whether this is a message that gets displayed to site visitors, the contents of an email message, or event listings of things like states or countries. Filters can be added using the apply_filters function on your data.

For example if you have a list of colors:


$colors = array(
  'blue'       => 'Blue',
  'green'      => 'Green',
  'red'        => 'Red',
  'yellow'     => 'Yellow',
  'blue-green' => 'Blue Green'
);

This can be modified in a way that allows other developers to modify the colors as needed for their site:


$colors = apply_filters( 'my_site_colors', array(
  'blue'       => 'Blue',
  'green'      => 'Green',
  'red'        => 'Red',
  'yellow'     => 'Yellow',
  'blue-green' => 'Blue Green'
) );

Now if someone wants to modify the colors on their site they can do something like:


function change_site_colors( $colors ) {
  $custom_colors = array(
    'purple' => 'Purple',
    'pink'   => 'Pink'
  );
  
  return $custom_colors;
}

add_filter( 'my_site_colors', 'change_site_colors' );

Filters also allow for additional data to be passed in the same format as actions.

Assessing Themes/Plugins for Developer Friendliness

When viewing a theme/plugin you can now make assessments of how friendly it is to use as a developer. If the theme/plugin has provided hooks to allow you to modify the flow of events and data, it allows you to build much more custom solutions.