Hooks: Actions & Filters

Hooks are the single most important concept in WordPress. They are the mechanism that lets you run your own code at specific points in WordPress's execution, or change data as it flows through the system — all without ever editing a WordPress core file. Themes, plugins, and even WordPress's own admin dashboard are built almost entirely out of hooks. If you understand hooks deeply, the rest of WordPress development becomes a matter of "which hook do I need, and what do I do with it."

Why this matters: Editing core files directly is a cardinal sin in WordPress development — your changes get wiped out the moment WordPress updates itself. Hooks exist precisely so you never have to touch core code to customize behavior.

Two Kinds of Hooks: Actions vs. Filters

WordPress has exactly two categories of hooks, and beginners often blur the line between them. The distinction is simple once you see it stated plainly:

Hook typePurposeReturns a value?Registered withFired with
ActionDO something at a specific point in time (log an event, send an email, output HTML, create a table)No — the return value is ignoredadd_action()do_action()
FilterMODIFY a piece of data as it passes through WordPress, then hand it backYes — must return a valueadd_filter()apply_filters()
Rule of thumb: If your callback function needs to return a modified value, you're writing a filter. If it just needs to perform an action (echo something, write to the database, send a request), you're writing an action.

A Full Worked Action Example

Actions let you hook into a moment in WordPress's lifecycle and run arbitrary code. A very common use case is hooking into wp_footer, which fires right before the closing </body> tag on every front-end page, to output a custom script tag:

<?php
// Output a custom analytics snippet just before </body>
function my_custom_footer_script() {
    ?>
    <script>
        console.log('Custom footer script loaded via wp_footer hook');
    </script>
    <?php
}
add_action('wp_footer', 'my_custom_footer_script');

Notice the function does not return anything — it simply performs an action (echoing markup) when WordPress reaches the wp_footer point in its page rendering. This snippet would typically live in your theme's functions.php or inside a plugin file.

A Full Worked Filter Example

Filters intercept a value, let you change it, and hand it back. A classic example is the_content, which fires every time post content is displayed, letting you append text after every post automatically:

<?php
// Append a note to the end of every post's content
function append_note_to_content($content) {
    $note = '<p><em>Thanks for reading this post!</em></p>';
    return $content . $note;
}
add_filter('the_content', append_note_to_content);
Critical detail: Notice the return statement. A filter callback that forgets to return its value (or returns nothing) will silently wipe out the content it was supposed to modify — this is one of the most common WordPress beginner bugs.

Priority and Accepted Arguments

Both add_action() and add_filter() accept two optional parameters beyond the hook name and callback — priority and the number of arguments your callback accepts:

<?php
add_action('init', 'my_function', 10, 1);
ParameterMeaning
10 (priority)Controls the order callbacks run when multiple functions are hooked to the same hook. Lower numbers run earlier. The default is 10, so passing a lower number (e.g. 5) makes your callback run before other default-priority callbacks, and a higher number (e.g. 20) makes it run later.
1 (accepted args)How many arguments WordPress should pass into your callback function when it fires the hook. Many hooks pass extra context (like the_content passing the content string) — if you need a second or third argument, you must raise this number, otherwise WordPress only passes the first one.

Firing a Hook vs. Listening for a Hook

A common point of confusion for beginners is mixing up the "listen" functions with the "fire" functions. They serve opposite roles:

FunctionRole
add_action() / add_filter()Listening — "when this hook fires, please run my function." This is what you write in your theme or plugin.
do_action() / apply_filters()Firing — "this hook is happening right now, run everything that's listening." WordPress core calls these internally (e.g. do_action('wp_footer') lives inside WordPress's own template files), and you can call them yourself too, if you're building a plugin or theme that wants to be extensible by others.

In other words: you almost always write add_action/add_filter calls as a theme or plugin developer. You'd only write do_action/apply_filters yourself if you're creating a custom hook point for other developers to extend your own code.

Some of the Most Commonly Used Hooks

There are hundreds of hooks in WordPress core, but a handful come up constantly in day-to-day development:

HookTypeFires when...
initActionWordPress has finished loading but before any headers are sent — the standard place to register custom post types, taxonomies, and shortcodes
wp_enqueue_scriptsActionThe front-end is about to load its scripts and stylesheets — the correct hook for adding your own CSS/JS (covered in the Enqueuing Scripts & Styles lesson)
the_contentFilterPost content is about to be displayed — lets you modify or append to it, as shown above
save_postActionA post (of any post type) is created or updated — commonly used to save related custom field data

Where Do These Hooks Live?

Hook callbacks are typically registered in your theme's functions.php file, or inside a plugin's main PHP file. There is no special syntax needed beyond calling add_action() or add_filter() — WordPress scans and runs whatever is registered by the time each hook point is reached during the page request lifecycle.

Remember: This website's own project does not have WordPress installed, so these examples are static, correct WordPress code meant to be copied into your own WordPress installation's functions.php or a plugin file — not something that runs live on this page.
Once you're comfortable with hooks, the next logical step is learning how to define your own structured content types — continue to Custom Post Types & Taxonomies.