WordPress Hooks Explained: What Actions and Filters Actually Do
By The Quartermaster // March 31, 2026 // 9 min read // WordPress Fundamentals
WordPress hooks are the system that lets you change how WordPress works without touching a single core file. Every plugin, every theme customization, every custom feature you have ever added to a WordPress site runs on hooks. There are two types — actions and filters — and once you understand them, you unlock the ability to bend WordPress to your will.
WordPress core contains roughly 2,744 hooks. Those hooks are the reason 61,000+ free plugins exist. They are the reason you can change your login page, modify your post content, add custom admin menus, and rewrite email headers — all without hacking a single core file. Hooks are not an advanced topic. They are the foundation. And every WordPress developer needs to understand them. WordPress hooks shows up everywhere once you look for it.
This guide breaks down what hooks are, how actions differ from filters, the exact syntax for using them, and the most important hooks you should know by name. No fluff, no filler — just the practical knowledge that makes you dangerous with WordPress. Anyone serious about wordpress hooks should know this.
⚡ Key Takeaways
- Hooks let you modify WordPress behavior without editing core files — they are the entire plugin API
- Actions fire when something happens (like a post being saved) — they DO things but return nothing
- Filters take data, let you modify it, and return it — they CHANGE things
- Priority controls execution order (lower number = runs first, default is 10)
- The #1 filter mistake: forgetting to return the value — which makes content disappear entirely

What Are WordPress Hooks?
A WordPress hook is a specific point in the code where you can attach your own function. When WordPress reaches that point during execution, it checks if anything is hooked in, and if so, it runs your code. The official WordPress Plugin Handbook defines hooks as “a way for one piece of code to interact/modify another piece of code at specific, pre-defined spots.” And wordpress hooks gets easier the more you work with it.
Think of it like a ship with anchor points along the hull. Each anchor point has a name. You can attach your own rigging to any of those points, and when the ship passes through that part of its journey, your rigging activates. You never need to rebuild the hull — you just hook in where you need to. Knowing wordpress hooks inside and out separates amateurs from pros.
2,744
hooks built into WordPress core
Source: WordPress Core Hooks Database
Without hooks, every customization would require editing core WordPress files directly. Those files get overwritten on every update. Hooks solve that problem permanently — your code lives in your own files, attaches to named hook points, and survives every WordPress update. The same principle applies to wordpress hooks in real-world projects.

Actions vs Filters: The Two Types of WordPress Hooks
Every WordPress hook is either an action or a filter. The difference is simple but critical. When it comes to wordpress hooks, the practical details matter.
Action Hooks: Do Something
An action hook fires at a specific moment in WordPress execution. Your callback function runs, does its thing, and returns nothing. Actions are event-driven — something happened, now react to it. And wordpress hooks gets easier the more you work with it.
WordPress triggers an action with do_action('hook_name'). You attach your code with add_action().
<?php
// When WordPress loads scripts, add our custom stylesheet
add_action( 'wp_enqueue_scripts', 'my_custom_styles' );
function my_custom_styles() {
wp_enqueue_style( 'my-style', get_stylesheet_uri() );
// No return statement needed — actions just DO things
}
Filter Hooks: Change Something
A filter hook takes a piece of data, passes it through your function, and expects it back — modified or not. Filters are pipelines. Data goes in, your code modifies it, data comes out.
WordPress triggers a filter with apply_filters('hook_name', $value). You attach your code with add_filter().
<?php
// Modify the excerpt length from default 55 words to 30
add_filter( 'excerpt_length', 'my_custom_excerpt_length' );
function my_custom_excerpt_length( $length ) {
return 30; // MUST return a value — this is a filter
}
🏴☠️ PIRATE TIP: The fastest way to remember the difference — actions are cannons (fire and forget), filters are blacksmith forges (take something in, reshape it, hand it back). If you forget to return the value in a filter, the content vanishes entirely. Ask any developer who has stared at a blank page for an hour before realizing their filter ate the content.
Quick Comparison
| Feature | Action | Filter |
|---|---|---|
| Purpose | Execute code at a specific point | Modify data before it is used |
| Returns | Nothing | Modified value (required) |
| Triggered by | do_action() | apply_filters() |
| Attached with | add_action() | add_filter() |
| Example | Send email when post is published | Change excerpt length from 55 to 30 |

How to Use add_action() and add_filter()
Both functions share the same parameter structure. Four arguments, two required, two optional. WordPress hooks shows up everywhere once you look for it.
add_action( $hook_name, $callback, $priority, $accepted_args );
add_filter( $hook_name, $callback, $priority, $accepted_args );
- $hook_name (required) — The name of the hook you are attaching to
- $callback (required) — Your function that runs when the hook fires
- $priority (optional, default: 10) — Lower runs first. Use 1 to run early, 99 to run late
- $accepted_args (optional, default: 1) — How many parameters your callback receives
Priority: Controlling Execution Order
Multiple functions can hook into the same hook point. Priority determines the order. Default is 10. A function with priority 5 runs before one with priority 10, which runs before priority 20.
<?php
// This runs FIRST (priority 5)
add_action( 'wp_head', 'add_meta_tags', 5 );
// This runs SECOND (priority 10, the default)
add_action( 'wp_head', 'add_tracking_code' );
// This runs LAST (priority 99)
add_action( 'wp_head', 'add_custom_css', 99 );
Accepted Arguments: Getting More Data
Some hooks pass multiple values to your callback. You need to tell WordPress how many your function expects.
<?php
// The save_post hook passes 3 arguments: $post_id, $post, $update
add_action( 'save_post', 'my_save_handler', 10, 3 );
function my_save_handler( $post_id, $post, $update ) {
if ( $update ) {
// Post was updated, not newly created
error_log( "Post {$post_id} was updated" );
}
}
“Hooks are one of the big features that make WordPress so customizable. They allow developers to change or extend WordPress’ functionality without needing to edit the WordPress core code itself.”
— WPBeginner
💡 Want more WordPress guides that skip the fluff and get straight to the code? Check out our full library. Knowing wordpress hooks inside and out separates amateurs from pros.

The Most Important WordPress Hooks to Know
You do not need to memorize 2,744 hooks. You need to know about 30. Here are the ones that show up in almost every WordPress project, split by type. The same principle applies to wordpress hooks in real-world projects.
Essential Action Hooks
| Hook | When It Fires | Use It For |
|---|---|---|
init | After WP loads, before output | Register post types, taxonomies |
wp_enqueue_scripts | When front-end assets load | Enqueue CSS and JavaScript |
wp_head | Inside the <head> tag | Meta tags, custom CSS, analytics |
wp_footer | Before </body> closes | Footer scripts, tracking pixels |
admin_menu | When admin menu is built | Add custom admin pages |
save_post | When a post is saved | Custom save processing |
after_setup_theme | After theme is loaded | Declare theme support features |
rest_api_init | When REST API initializes | Register custom REST routes |
Essential Filter Hooks
| Hook | What It Filters | Use It For |
|---|---|---|
the_content | Post content before display | Add content before/after posts |
the_title | Post title before display | Modify titles dynamically |
excerpt_length | Word count for excerpts | Change excerpt length |
body_class | CSS classes on <body> | Add custom body classes |
upload_mimes | Allowed upload file types | Allow SVG or WebP uploads |
login_redirect | URL after login | Custom post-login redirect |
wp_nav_menu_items | Navigation menu HTML | Add items to nav menus |
script_loader_tag | Script tag HTML output | Add async/defer to scripts |

Where to Put Your Hook Code
Knowing hooks is half the battle. Knowing where to write your hook code is the other half. You have three good options and one terrible one. This is why understanding wordpress hooks pays off long term.
child theme‘s functions.php — Best for theme-specific customizations. If the code is about how your site looks or behaves visually, it goes here. Survives parent theme updates but not theme switches. This is why understanding wordpress hooks pays off long term.
Custom plugin — Best for site functionality that should survive theme changes. Create a simple plugin with a header comment, drop it in wp-content/plugins/, and activate it. If you switch themes, your functionality stays.
mu-plugins — For must-use code that should always run. Drop a PHP file in wp-content/mu-plugins/ and it auto-activates. No on/off switch — it just runs. Use this for security rules or critical functionality.
🏴☠️ PIRATE TIP: Never edit a parent theme’s functions.php, a plugin’s source files, or any WordPress core file. Updates will overwrite your changes. If you find a tutorial that says “open wp-includes/functions.php and add this code” — close that tab immediately. That tutorial is steering you into the rocks. When it comes to wordpress hooks, the practical details matter.

Common Hook Mistakes (and How to Fix Them)
These are the mistakes that eat hours of debug WordPressging time. Every WordPress developer hits at least one of these. Learn them now and save yourself the pain. WordPress hooks shows up everywhere once you look for it.
| Mistake | What Happens | Fix |
|---|---|---|
Forgetting return in a filter | Content disappears entirely | Always return $value at end of filter callbacks |
| Typo in the hook name | Code never runs, no error thrown | Copy hook names from the official reference |
| Registering the hook too late | Callback never fires | Ensure add_action() runs before the hook fires |
Wrong accepted_args count | Warnings or missing data | Match the parameter count to what the hook actually passes |
| Heavy code on hot hooks | Site performance tanks | Avoid database queries on init or the_content unless necessary |
Using init for admin-only code | Code runs on every page load unnecessarily | Use admin_init for admin-only functionality |
The single most common one is the missing return value in filters. A filter that does not return a value returns null by default in PHP. If you hook into the_content and forget to return the content, your entire post body vanishes. No error message, no warning — just a blank space where your content used to be.
For a visual walkthrough of hooks in action, the official Learn WordPress channel covers the fundamentals: When it comes to wordpress hooks, the practical details matter.
How to Debug WordPress Hooks That Aren’t Firing

You’ve added your hook code, refreshed the page, and… nothing happens. This is the most frustrating part of working with WordPress hooks, but it’s usually caused by one of three issues. First, check that you’re hooking into the right action or filter name—typos are common, and WordPress won’t throw an error for non-existent hooks. Second, verify your priority number isn’t being overridden by another function with higher priority (lower numbers run first). Third, make sure your code is actually being loaded before the hook fires.
Use these debugging techniques to track down the problem. Add error_log('Hook fired: ' . current_action()); inside your callback function to confirm it’s running. Check your debug.log file (enable WP_DEBUG_LOG in wp-config.php first) to see what’s happening. If the log entry never appears, your callback isn’t executing.
- Use
has_action('hook_name')orhas_filter('hook_name')to verify your function is attached - Add
var_dump(func_get_args());to see what parameters are being passed to your callback - Use the Query Monitor plugin to see all hooks firing on a page and their attached callbacks
Most hook problems come down to timing—your code loads after the hook has already fired. Move your add_action or add_filter calls earlier in the load sequence, typically in your theme’s functions.php or in a must-use plugin.
Frequently Asked Questions
What is the difference between a WordPress action and a filter?
An action executes code at a specific point during WordPress execution and returns nothing. A filter takes a value, lets you modify it, and requires you to return it. Actions do things, filters change things. Use add_action() for actions and add_filter() for filters.
How many hooks does WordPress have?
WordPress core contains approximately 2,744 hooks — a mix of action hooks and filter hooks. Plugins and themes can add their own custom hooks on top of that, so a typical WordPress installation may have thousands more available. Anyone serious about wordpress hooks should know this.
Where should I put my WordPress hook code?
For theme-related customizations, use your child theme’s functions.php file. For site functionality that should survive theme changes, create a simple custom plugin. For must-use code, place a PHP file in the wp-content/mu-plugins directory. Never edit core files or parent theme files directly. And wordpress hooks gets easier the more you work with it.
What happens if I forget to return a value in a WordPress filter?
The filtered content will be replaced with null, which typically means it disappears from the page entirely. This is the most common hook mistake in WordPress development. Every filter callback must return a value, even if you did not modify it. Knowing wordpress hooks inside and out separates amateurs from pros.
Can I create my own custom hooks in WordPress?
Yes. Use do_action('your_custom_hook') to create a custom action hook, or apply_filters('your_custom_filter', $value) to create a custom filter hook. This lets other developers (or your own plugins) extend your code without modifying it. The official Plugin Handbook covers custom hooks in detail.
⚔️ Pirate Verdict
WordPress hooks are not an advanced concept — they are the foundational concept. Every plugin you have ever installed, every theme customization you have ever made, every snippet you have ever pasted into functions.php runs on hooks. New plugin submissions doubled in 2025, largely driven by AI-assisted development, and every single one of those plugins uses hooks. Learn actions and filters, memorize the top 15-20 hook names, and you go from someone who installs WordPress to someone who controls it. That is the difference.
Start Using Hooks in Your Next Project
WordPress hooks are what separate someone who uses WordPress from someone who builds with it. Actions let you execute code at the right moment, filters let you reshape data before it hits the page, and together they give you full control over a system that powers 42.6% of the web — without touching a single core file.
Pick one hook from the tables above, write a small function, and hook it in. Start with wp_enqueue_scripts to load a custom stylesheet or the_content to append a message after every post. Once you see it work, the rest clicks into place.
What was the first WordPress hook you learned? Drop it in the comments below. Anyone serious about wordpress hooks should know this.