London Web Design Logo Black Cropped
Book a Call

WordPress Hooks and Filters | Complete Guide

October 19, 2025

WordPress Hooks and Filters Guide

WordPress hooks enable modifying behaviour without editing core files. Actions execute functions at specific points; filters modify data before output. Professional WordPress developers leverage hooks creating flexible, upgradeable customisations. London developers require hook mastery building sophisticated WordPress solutions maintaining compatibility through WordPress updates.

Understanding WordPress Hooks

WordPress hooks provide extension points throughout execution lifecycle. Hooks enable plugins and themes adding functionality or modifying behaviour at precise moments.

Two hook types exist: actions and filters. Actions execute custom code at specific points. Filters modify data passing through WordPress.

Hooks maintain upgrade compatibility. Direct core modifications break during updates; hook-based customisations survive upgrades automatically.

WordPress core includes hundreds of hooks. Themes and plugins add custom hooks extending extensibility.

Hook-based development enables ecosystem. Third-party developers extend functionality without accessing original code.

Mastering hooks distinguishes professional from amateur WordPress development practices.

WordPress Actions Explained

Actions execute functions at specific WordPress events. Actions trigger during WordPress execution enabling custom code injection.

How Actions Work:

WordPress reaches action points during execution. Code attached via add_action() executes at those moments.

Action Syntax:

add_action('hook_name', 'function_name', $priority, $accepted_args);

Parameters:

  • hook_name - Action hook name
  • function_name - Function to execute
  • priority - Execution order (default 10, lower executes first)
  • accepted_args - Number of arguments function accepts

Common Action Examples:

// Theme setup
function mytheme_setup() {
    add_theme_support('post-thumbnails');
    add_theme_support('title-tag');
}
add_action('after_setup_theme', 'mytheme_setup');

// Enqueue scripts
function mytheme_scripts() {
    wp_enqueue_style('main-style', get_stylesheet_uri());
    wp_enqueue_script('main-script', get_template_directory_uri() . '/js/main.js');
}
add_action('wp_enqueue_scripts', 'mytheme_scripts');

// Admin initialization
function myplugin_admin_init() {
    register_setting('my_options', 'my_option_name');
}
add_action('admin_init', 'myplugin_admin_init');

// Save post
function myplugin_save_post($post_id) {
    // Custom code when posts save
    update_post_meta($post_id, 'custom_field', 'value');
}
add_action('save_post', 'myplugin_save_post');

Actions don't return values. They execute code then continue WordPress execution.

Remove actions using remove_action() with identical parameters used attaching.

WordPress Filters Explained

Filters modify data before WordPress uses or displays it. Filters receive data, process it, and return modified versions.

How Filters Work:

Data passes through filters before output. Functions attached via add_filter() receive data, modify it, and return altered values.

Filter Syntax:

add_filter('hook_name', 'function_name', $priority, $accepted_args);

Filter Function Structure:

function filter_function_name($value, $arg2, $arg3) {
    // Modify $value
    $value = modify_somehow($value);
    
    // MUST return modified value
    return $value;
}

Critical: Filters must return values. Failing to return breaks functionality.

Common Filter Examples:

// Modify excerpt length
function mytheme_excerpt_length($length) {
    return 30; // words
}
add_filter('excerpt_length', 'mytheme_excerpt_length');

// Customize read more link
function mytheme_excerpt_more($more) {
    return '... <a href="' . get_permalink() . '">Continue Reading</a>';
}
add_filter('excerpt_more', 'mytheme_excerpt_more');

// Modify title
function myplugin_modify_title($title, $id) {
    if (is_singular('portfolio')) {
        $title = 'Portfolio: ' . $title;
    }
    return $title;
}
add_filter('the_title', 'myplugin_modify_title', 10, 2);

// Modify content
function myplugin_content_filter($content) {
    if (is_single()) {
        $content .= '<p>Thanks for reading!</p>';
    }
    return $content;
}
add_filter('the_content', 'myplugin_content_filter');

Filters enable sophisticated modifications without template editing.

Remove filters using remove_filter() matching original attachment parameters.

Action vs Filter: When to Use Each

Understanding differences between actions and filters determines correct implementation.

Use Actions When:

  • Executing code without modifying data
  • Adding functionality at specific points
  • Sending emails or notifications
  • Saving data or updating options
  • Enqueueing scripts or styles
  • Registering post types or taxonomies

Use Filters When:

  • Modifying text before display
  • Altering data before saving
  • Customising output without template changes
  • Adding or removing content from strings
  • Adjusting settings or configuration values

Key Differences:

ActionsFilters
Execute codeModify data
Don't return valuesMust return values
Can't change WordPress outputChange WordPress output
Side effects acceptableShould avoid side effects

Example Scenario:

Adding custom content to posts:

Wrong (Action):

// Won't work - actions don't modify output
function wrong_approach($content) {
    echo '<p>Additional content</p>';
}
add_action('the_content', 'wrong_approach');

Right (Filter):

// Works - filter modifies and returns content
function right_approach($content) {
    $content .= '<p>Additional content</p>';
    return $content;
}
add_filter('the_content', 'right_approach');

Choose appropriate hook types ensuring correct functionality.

Priority and Execution Order

Priority controls execution order when multiple functions attach to identical hooks. Understanding priority enables precise control over modification sequences.

Priority Basics:

Priority accepts integers (positive or negative). Default priority: 10.

Lower numbers execute first: Priority 5 executes before priority 10.

Same priority executes in attachment order.

Priority Examples:

// Executes first (priority 5)
add_action('init', 'early_function', 5);

// Executes second (default priority 10)
add_action('init', 'normal_function');

// Executes third (priority 15)
add_action('init', 'late_function', 15);

// Executes last (priority 999)
add_action('init', 'very_late_function', 999);

Strategic Priority Use:

Early Priority (1-5): Set up prerequisites other functions depend upon.

Default Priority (10): Most functionality. Avoid changing unless necessary.

Late Priority (15-20): Modify output from earlier functions.

Very Late Priority (100+): Final modifications or cleanup.

Priority Conflicts:

Multiple modifications to same data require careful priority management:

// First modification (priority 10)
function first_mod($content) {
    $content = str_replace('old', 'new', $content);
    return $content;
}
add_filter('the_content', 'first_mod', 10);

// Second modification (priority 20)
function second_mod($content) {
    $content = str_replace('new', 'final', $content);
    return $content;
}
add_filter('the_content', 'second_mod', 20);

Priority ensures predictable modification sequences.

Common WordPress Hooks

WordPress provides hundreds of hooks. Understanding frequently-used hooks enables powerful customisations.

Initialisation Hooks:

// Runs after WordPress loaded
add_action('init', 'function_name');

// Theme setup
add_action('after_setup_theme', 'function_name');

// Admin initialization
add_action('admin_init', 'function_name');

// Widgets initialization
add_action('widgets_init', 'function_name');

Enqueue Hooks:

// Frontend scripts/styles
add_action('wp_enqueue_scripts', 'function_name');

// Admin scripts/styles
add_action('admin_enqueue_scripts', 'function_name');

// Login scripts/styles
add_action('login_enqueue_scripts', 'function_name');

Content Hooks:

// Modify post content
add_filter('the_content', 'function_name');

// Modify post title
add_filter('the_title', 'function_name');

// Modify excerpt
add_filter('the_excerpt', 'function_name');

Template Hooks:

// Before header
add_action('wp_head', 'function_name');

// Before closing body
add_action('wp_footer', 'function_name');

// Body open
add_action('wp_body_open', 'function_name');

Post Hooks:

// Before post saved
add_action('save_post', 'function_name');

// After post deleted
add_action('delete_post', 'function_name');

// Post published
add_action('publish_post', 'function_name');

Explore comprehensive hook documentation in WordPress Codex or through code reference.

Creating Custom Hooks

Custom hooks enable others extending your themes or plugins. Professional development includes custom hooks providing extension points.

Creating Custom Actions:

// In your code where action needed
function process_data($data) {
    // Before processing
    do_action('myplugin_before_process', $data);
    
    // Process data
    $result = expensive_operation($data);
    
    // After processing
    do_action('myplugin_after_process', $result);
    
    return $result;
}

Using Custom Actions:

// Other developers extend your plugin
function log_processing($data) {
    error_log('Processing: ' . print_r($data, true));
}
add_action('myplugin_before_process', 'log_processing');

Creating Custom Filters:

// In your code where filtering needed
function get_settings() {
    $settings = array(
        'option1' => 'value1',
        'option2' => 'value2',
    );
    
    // Allow filtering
    return apply_filters('myplugin_settings', $settings);
}

Using Custom Filters:

// Other developers modify your plugin settings
function customize_settings($settings) {
    $settings['option3'] = 'value3';
    return $settings;
}
add_filter('myplugin_settings', 'customize_settings');

Naming Conventions:

Prefix custom hooks preventing conflicts: themename_hook_name or pluginname_hook_name.

Use descriptive names explaining hook purposes.

Document custom hooks enabling developers understanding extension points.

Custom hooks demonstrate professional development enabling ecosystem around your code.

Removing Hooks

Remove actions and filters when needing to disable or replace existing functionality.

Removing Actions:

// Remove action
remove_action('hook_name', 'function_name', $priority);

// Example: Remove default WordPress emoji
remove_action('wp_head', 'print_emoji_detection_script', 7);
remove_action('wp_print_styles', 'print_emoji_styles');

Removing Filters:

// Remove filter
remove_filter('hook_name', 'function_name', $priority);

// Example: Remove automatic paragraph formatting
remove_filter('the_content', 'wpautop');

Timing Considerations:

Remove hooks after they're added. Use appropriate timing:

// Wrong - too early
remove_action('init', 'parent_function'); // Doesn't work

// Right - wait for action to be added
function remove_parent_action() {
    remove_action('init', 'parent_function');
}
add_action('init', 'remove_parent_action', 11); // Priority > original

Removing Class Methods:

Class-based hooks require object references:

// If added like this
add_action('init', array($object, 'method'));

// Remove like this
remove_action('init', array($object, 'method'));

Alternative: has_action/has_filter:

Check before removing:

if (has_action('init', 'function_name')) {
    remove_action('init', 'function_name');
}

Removing hooks enables disabling unwanted functionality from themes or plugins.

Combine hook removal with child theme customisation modifying parent theme behaviour safely.

Hook Best Practices

Professional hook usage follows established patterns ensuring maintainable, efficient code.

Naming Conventions: Use descriptive function names with prefixes. mytheme_setup better than setup.

Single Responsibility: Each hooked function should perform one task. Separate concerns improving debugging.

Return Values: Filters must return values. Actions shouldn't return values.

Documentation: Comment hooks explaining purposes, parameters, and return values.

Minimal Processing: Keep hooked functions lightweight. Expensive operations slow sites.

Priority Management: Use default priority (10) unless specific ordering required.

Conditional Execution: Add conditionals limiting hook execution to relevant contexts:

function conditional_hook_function() {
    if (!is_admin() && is_singular('post')) {
        // Only executes on single posts in frontend
    }
}

Error Handling: Validate data in hooked functions preventing errors from invalid inputs.

Testing: Test hooks thoroughly ensuring functionality works across scenarios.

Professional practices distinguish quality development from amateur implementations.

Debugging Hooks

Debugging hooks identifies which functions execute and in what order. Several techniques reveal hook execution.

Query Monitor Plugin:

Query Monitor displays all hooks firing during page load. See execution order, timing, and sources.

Debug Logging:

function debug_hook() {
    error_log('Hook executed: ' . current_filter());
}
add_action('hook_name', 'debug_hook');

Show Hook Execution:

// Temporary debugging - remove after debugging
function show_hooks() {
    $hooks = $GLOBALS['wp_filter'];
    echo '<pre>';
    print_r($hooks);
    echo '</pre>';
}
add_action('wp_footer', 'show_hooks');

Conditional Debugging:

function conditional_debug($data) {
    if (current_user_can('administrator')) {
        error_log('Data: ' . print_r($data, true));
    }
    return $data;
}
add_filter('hook_name', 'conditional_debug');

WordPress Debug Bar:

Debug Bar plugin provides hooks panel showing fired hooks.

Systematic debugging reveals hook issues enabling efficient troubleshooting.

Understanding hooks enables sophisticated WordPress troubleshooting resolving complex issues.

Frequently Asked Questions

What's difference between do_action and apply_filters?

do_action() executes functions attached to actions without returning values. apply_filters() passes data through functions attached to filters returning modified values. Use do_action() executing code at specific points. Use apply_filters() modifying data before use. Actions change site behaviour; filters change site content. Choosing correctly ensures proper functionality and maintainability.

Can I use same function for multiple hooks?

Yes, attach identical functions to multiple hooks executing same code at different points. Useful for functionality needed in multiple contexts. Example: clearing cache on post save and post delete using same cache-clearing function. Ensure function works correctly regardless of triggering hook. Consider whether single hook with conditional logic proves more efficient.

How do I find available hooks?

WordPress Code Reference documents official hooks. Search "WordPress hooks" plus context (e.g., "WordPress save post hooks"). Review theme and plugin source code revealing available hooks. Use Query Monitor or Debug Bar plugins showing fired hooks. WordPress Codex provides hook references. Theme and plugin documentation often lists available custom hooks.

What happens if I forget to return value in filter?

Forgetting return statements in filters breaks functionality. Data passing through filter becomes null or undefined causing errors or blank content. Always return values in filter functions even if unmodified. PHP doesn't automatically return last statement; explicit return required. Debugging missing returns requires careful code review identifying filters lacking returns.

Can hooks slow down my WordPress site?

Excessive or inefficient hooks slow sites. Each hook adds processing overhead. Poorly optimised hooked functions, especially with expensive operations (database queries, external API calls), significantly impact performance. Use hooks judiciously. Profile hooked functions identifying performance bottlenecks using Query Monitor. Optimise slow functions or reduce hook usage. Well-written hooks have minimal performance impact. Combine efficient hooks with WordPress speed optimisation maintaining performance.

How do I remove hooks from plugins I don't control?

Remove plugin hooks using remove_action() or remove_filter() with correct function names and priorities. Identify function names and priorities through plugin source code or Query Monitor. Remove hooks after plugins add them using appropriate timing and priority. Example removing plugin action with priority 10: use remove_action('init', 'plugin_function', 10) at priority 11 or later ensuring plugin already added hook.

What's hook priority best practice?

Default priority (10) works for most situations. Use non-default priorities only when specific execution order required. Lower priorities (1-5) for setup functions others depend on. Higher priorities (15-20) for modifications depending on earlier processing. Very high priorities (100+) for final modifications. Document non-default priorities explaining why necessary. Excessive priority manipulation creates fragile code difficult maintaining.


Related WordPress Development Topics:


Written by the WordPress Development Team at London Web Design, leveraging hooks for powerful customisations since 2010.

London Web Design Logo Black Cropped
London Web Design offers award-winning website design services tailored to your unique business goals. With over a decade of design experience, our team of friendly web designers works closely with you to create attractive, bespoke designs that not only look stunning but also drive results.
Contact
London Office
Directions
[email protected]
+44 7305 523 333
© London Wesbite Design 2025
linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram