Decades were gone and WordPress is still the most used CMS solution globally. It evolved, of course, settling its market, but in my opinion part of the success can be explained by an old feature – WP hooks.

Hooks are specific points with the WP code which allow devs to “hook”, filter or alter anything. This is particularly useful when you are developing plugins and even themes.

Hooks provide a simple way of change or customize WP’s behaviour without messing up with the core script. But that is just part of the marvel: devs can’t just use existing hooks, but also create their own.

Using hooks

Using hooks in WordPress is actually quite simple. As a recap, there are two different types of hooks in WP – actions and filters. The first represent, literally, a point within the code where you can run or execute processes of yours. Filters, on the other hand, provide a way to replace arguments in a routine or a method before it runs. Let’s see a simple example for each .

add_filter('the_title', function($title, $id) {
  if($id == 20) {
    return 'New Title';

add_action('wp_footer', function() {
  echo 'Added footer description';

Explaining briefly. The filter <a href="">the_title</a> filters all post titles before rendering them. It admits two arguments, so I need to pass them in the function I hooked. In the previous example, if the post ID is equal to 20, then we modify the post title, returning “New Title”. For any other post ID, the original title will remain the same.

And as an action, wp_footer allows us to add processes or execute something else right before the footer renders. So the example will add the sentence “Added footer description” after the existing footer.

Of course we could add here more elaborated uses of actions and filters. However, no matter what use or how complex is the function, method or routine you hook, the mechanics will always be the same.

What about creating your own hooks?

It is possible, and even recommended, to add your own hooks while developing plugins or themes. For such, you just need to use two different WP core functions: do_action() and apply_filters().

Before any example, let me remind a simple difference between those two functions. While do_action can be used with a single parameter – the name of the action – apply_filters requires at least two parameters. The reason is simple: a filter is a hook that modifies a variable, so it would be impossible without passing that variable together.

So let’s see an example where we are using both of them at the same time.

function example($post_id) {
  $title = get_the_title($post_id);
  $author = get_post_field('post_status', $post_id);
  $separator = apply_filters('change_separator', ':');


  echo $title . $separator . $author;

The function is very straightforward. If we pass any post ID, it grabs the title and the author and prints them, with “:” as separator, like this: “Title of the Article:Name of the Author”. Regarding the hooks, we have two of them. Let’s see their usage:

//This grabs title and author for the post with 200 as ID and prints the message
//Post Title:Post Author

add_filter('change_separator', function($separator) {
  return '---';
//Replaces the separator - so now the function example() prints the message
//Post Title---Post Author

add_action('anything_before', function() {
  echo 'Message Before' . PHP_EOL;
//Now, if we run the function example(), we'd have two sentences
//Message Before
//Post Title---Post Author

Of course this is a very simple use of WP hooks. However, creating them always follow this same logic. Also, we can pass arguments through actions and filters, in addition to the name of the hook (or filterable variable, for filters). That helps coders to use the hooks and add new functionality using the variables you provided.

For instance, if we provided the post ID as a second argument for the action anything_before, coders could get the post object and add any other post meta. My suggestion? Start with the simple – actions and filters for additional content, change part of the renderized posts, etc.