How to Find All Action and Filter Hooks in WordPress

The best way to customize systems on WordPress is to hook your code into execution via action and filter hooks. Usually, available hooks can be found by viewing the developer docs for the plugin or theme you are customizing.

This is not always helpful, however. Sometimes you cannot find the right hook for the job. Other times, the documentation is unclear and you are not sure how to make use of a hook. Additionally, you don't know exactly the hook's context. "What exactly is it? The hook name seems like what I'm looking for, so I guess I'll give it a shot."

A few hours, error_log()'s, and var_dump()'s later, you have finally discovered that the hook wasn't what you're needing. This can make simple customizations take an unnecessary amount of time. Sometimes, this guessing game workflow can even make a customization impossible for you all because the hook you need simply wasn't listed in the docs. You're forced to strike out before even getting in the game.

Finding and utilizing hooks should not be such a mystery. You may be a master at PHP and WordPress customizations, but you're missing one very crucial skill. Stop depending on outdated, unclear, and incomplete developer docs. It's time to head to the source (code)!

Introducing grep

If you've never used the command line before, it should definitely be next on your list of things to learn. And how convenient that I'm about to teach you the most important command you will probably use on a Unix system: grep.

grep is a shell command that searches for pattern matches in given input files. More specifically, you're able to recursively search files in bulk by specifying a regex pattern or fixed string to search. As it finds matches, grep will output the line containing the match and which file the match was found. Are angels singing in your head yet like they were for me?

Common grep Commands

I'm so excited to be the one sharing this with you today because this really is the beginning of the command line pocket of your web developer tool belt. You are going to go from a PHP/WordPress Master to a PHP/WordPress Expert. Seriously, it is a total game changer when it comes to your capabilities and work efficiency. Now's the time to overcome your fear of the command line!

To start, cd into the directory that you would like to search. This could be the root of a plugin, theme, or even a fresh download of WordPress if you're searching for WordPress Core hooks. You're now ready to start grep'ing! In my sample outputs, I'm using WooCommerce version 3.9.0.

Simple Recursive Search

grep -FR "do_action" .

Find all action hook uses recursively, starting in the current working directory. Outputs the relative file path and entire line for each match.
-F opts to match a fixed string rather than use a basic regular expression pattern, the default behavior.
-R opts to find matches recursively.
"do_action" is the pattern to match.
. is where to start searching. A period represents the current working directory.

./includes/abstracts/abstract-wc-data.php: do_action( 'woocommerce_before_' . $this->object_type . '_object_save', $this, $this->data_store );
./includes/abstracts/abstract-wc-data.php: do_action( 'woocommerce_after_' . $this->object_type . '_object_save', $this, $this->data_store );
./includes/abstracts/abstract-wc-order.php: do_action( 'woocommerce_before_' . $this->object_type . '_object_save', $this, $this->data_store );
...

List All Hook Uses

grep -ER "do_action|apply_filters" .

Find all action and filter hook uses.
-E opts to use extended regular expression (ERE) matching rather than grep's default, basic regex (BRE).
| separates an alternate expression in ERE, like an "or" operator.

...
./templates/myaccount/my-account.php:do_action( 'woocommerce_account_navigation' ); ?>
./templates/myaccount/my-account.php: do_action( 'woocommerce_account_content' );
./templates/myaccount/my-address.php: $get_addresses = apply_filters(
...

List Hooks with Keyword

grep -ER "do_action\s?\(\s?[\'\"].*checkout.*[\'\"][^\(\)]*\)" .

Find all action hook uses that include the word "checkout" in the hook name.
\s represents any common whitespace character.
? specifies a zero or single occurrence of the previous character.
\( is an escaped literal opening parenthesis.
[...] contains a list of possible characters.
\'\" is an escaped literal apostrophe followed by an escaped literal double quote.
.* represents any character, any number of times.
[^...] contains a set of excluded characters. Represents any character except what has been listed.
\) is an escaped literal closing parenthesis.

Exclude Files by Pattern

grep -FR --exclude="./includes/*" --exclude="*/.*" --exclude="*/assets/*" "do_action" .

Find all action hook uses excluding provided file path patterns. First, exclude everything in the initial "includes" directory. Second, exclude all hidden files. Third, exclude all "assets" directories.
--exclude is an option to exclude searching file paths matching the provided glob pattern.
. is a literal period character.
* is an unquantified (zero occurrences or more) wildcard character.

./packages/woocommerce-blocks/src/Domain/Bootstrap.php: do_action( 'woocommerce_blocks_loaded' );
./packages/woocommerce-blocks/src/RestApi/Controllers/Cart.php: do_action( 'woocommerce_add_to_cart', $cart_id, $product_id, $quantity, $variation_id, $variation, $cart_item_data );
./packages/woocommerce-blocks/src/RestApi/StoreApi/Utilities/CartController.php: do_action( 'woocommerce_add_to_cart', $cart_id, $product_id, $request['quantity'], $variation_id, $request['variation'], $request['cart_item_data'] );
...

Specify Files by Pattern

grep -R --include="*.php" "checkout" .

Only search files with the php extension.
--include is an option to exclude searching all file paths except ones matching the provided glob pattern.
. is a literal period character. At the start of a path, a single period represents the current directory. This is similar to how two periods represents the previous directory.
* is an unquantified (zero occurrences or more) wildcard character.

./packages/woocommerce-blocks/src/Domain/Bootstrap.php: do_action( 'woocommerce_blocks_loaded' );
./packages/woocommerce-blocks/src/RestApi/Controllers/Cart.php: do_action( 'woocommerce_add_to_cart', $cart_id, $product_id, $quantity, $variation_id, $variation, $cart_item_data );
./packages/woocommerce-blocks/src/RestApi/StoreApi/Utilities/CartController.php: do_action( 'woocommerce_add_to_cart', $cart_id, $product_id, $request['quantity'], $variation_id, $request['variation'], $request['cart_item_data'] );
...

Counting Matches per File

grep -FRc "apply_filters" .

Count all filter hook uses per file. Outputs the relative file path proceeded by the match count.
-c opts to display the number of matches per file instead of each matched line, the default output.

...
./includes/abstracts/abstract-wc-product.php:27
./includes/abstracts/abstract-wc-session.php:0
./includes/abstracts/abstract-wc-settings-api.php:3
./includes/abstracts/abstract-wc-shipping-method.php:11
...

Counting Total Hook Uses

grep -ER "do_action|apply_filters" . | wc -l

Count the number of lines output by the grep command.
| is a "pipe" operator in Bash. It means the output from the first command will be used as the input for the following command.
wc is the "word count" command.
-l opts for word count to only output the number of lines.

2682

Adding Context

grep -FR -A 5 "do_action( 'woocommerce_after_add_to_cart_quantity' )" .

Outputs the line containing the match followed by all 5 lines after the match.
-A NUM opts to display the provided number of lines after the match.

grep -FR -B 10 "do_action( 'woocommerce_after_add_to_cart_quantity' )" .

Outputs all 10 lines before the match followed by the line containing the match.
-B NUM opts to display the provided number of lines before the match.

grep -FR -C 3 "do_action( 'woocommerce_after_add_to_cart_quantity' )" .

Outputs all 3 lines before the match, the line containing the match, and all 3 lines after the match.
-C NUM opts to display the provided number of lines before and after the match.

Conclusion

Isn't it great how many ways you can search for hooks using grep? And who would've thought there's over 2,500 hook uses in WooCommerce 3.9.0!

Now you can work more efficiently by finding every hook in any open source WordPress system. Read the source code that's made available to you and no longer be limited to only what has been documented.

Topics