iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Hooks (Actions / Filters)

WordPress hooks are extension points: add_action runs your callback at a named event; add_filter transforms a value as it passes through the system. Hooks are how every plugin, theme, and admin tweak modifies WP without forking it.

Real action + filter recipes

EXAMPLE
<?php
// 1) Action — run at a named moment
add_action('init', function () {
    register_post_type('product', [
        'public'       => true,
        'label'        => 'Products',
        'supports'     => ['title', 'editor', 'thumbnail', 'excerpt'],
        'show_in_rest' => true,        // enables Gutenberg + REST API
    ]);
});

// 2) Action — enqueue scripts/styles on the front-end
add_action('wp_enqueue_scripts', function () {
    wp_enqueue_style(
        'theme',
        get_stylesheet_directory_uri() . '/style.css',
        [],
        wp_get_theme()->get('Version'),
    );
    wp_enqueue_script(
        'app',
        get_stylesheet_directory_uri() . '/app.js',
        ['wp-element'],
        wp_get_theme()->get('Version'),
        true,                          // in footer
    );
});

// 3) Action — admin notice on Settings page
add_action('admin_notices', function () {
    if (!current_user_can('manage_options')) return;
    echo '<div class="notice notice-warning is-dismissible"><p>Don&rsquo;t forget to set your API key.</p></div>';
});

// 4) Filter — transform a value
add_filter('the_content', function ($content) {
    if (!is_singular('post')) return $content;
    return $content . '<p class="share"><a href="#">Share this post</a></p>';
}, 20);

// 5) Filter — change excerpt length
add_filter('excerpt_length', fn() => 30);
add_filter('excerpt_more',   fn($more) => ' …');

// 6) Filter — modify the WP_Query for the main loop
add_action('pre_get_posts', function ($q) {
    if (is_admin() || !$q->is_main_query()) return;
    if (is_home()) {
        $q->set('posts_per_page', 12);
        $q->set('post_type',      ['post', 'product']);
    }
});

// 7) Filter — sanitise/transform incoming form data on save
add_filter('pre_update_option_site_url', fn($v) => esc_url_raw(trim($v)));

// 8) Hook priority + acceptable args
add_filter('the_title', 'my_title_filter', 10, 2);
function my_title_filter($title, $post_id) {
    return get_post_type($post_id) === 'product' ? '🛒 ' . $title : $title;
}

// 9) Remove a hook — defuse a plugin's bad behaviour
remove_action('wp_head', 'wp_generator');         // hide WP version
remove_filter('the_content', 'wpautop');          // turn off auto-paragraphs

// 10) Run code once per request — protect against double-firing
add_action('save_post_product', function ($post_id, $post, $update) {
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
    if ($post->post_status !== 'publish') return;
    // safe to do work here
}, 10, 3);

// 11) Discovery — find every hook a page fires
// Tools: Query Monitor (plugin), `wp hook list` (WP-CLI), `do_action_ref_array` calls in source

// 12) Custom hook — let other code extend YOURS
do_action('my_plugin_after_user_signup', $user_id);
$message = apply_filters('my_plugin_welcome_subject', 'Welcome to ' . get_bloginfo('name'));

Why it matters

Hooks are how WordPress stays small. Any plugin that wants to extend behaviour should be using add_action / add_filter — never editing core files. The cost: read your hooks list with Query Monitor to know what’s actually firing.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// Actions — do something at a moment.
add_action('init', 'my_init');
// Filters — transform a value.
add_filter('the_title', fn($t) => strtoupper($t));
Try it Yourself »

Exercise

Hook type that lets you modify a value.

Test yourself

Q1. WordPress hooks come in two flavours:
Q2. An action lets you…
Q3. A filter lets you…

Discussion

Loading…