WordPress's hook system allows modifying behavior without editing core files. Actions DO things; filters TRANSFORM values.
Actions
// Basic action
add_action('wp_head', 'add_custom_analytics');
function add_custom_analytics() {
echo '<script>/* GA4 snippet */</script>';
}
// Remove a core action
remove_action('wp_head', 'wp_generator');
// Action with priority (lower = earlier) and argument count
add_action('save_post', 'on_post_save', 10, 2);
function on_post_save($post_id, $post) {
if ($post->post_type !== 'service') return;
// Clear cache, ping API, etc.
}
Common Action Hooks
| Hook | Fires When |
|------|-----------|
| init | Early initialization — register CPTs, taxonomies |
| wp_enqueue_scripts | Enqueue frontend scripts/styles |
| admin_enqueue_scripts | Enqueue admin scripts/styles |
| wp_head | Output to <head> |
| wp_footer | Output before </body> |
| save_post | After post saved to DB |
| template_redirect | Before template loads — redirect logic |
| widgets_init | Register sidebars and widgets |
| after_setup_theme | Theme features (add_theme_support) |
Filters
// Append CTA to single post content
add_filter('the_content', 'append_cta_to_posts');
function append_cta_to_posts($content) {
if (!is_single()) return $content;
return $content . '<div class="cta-box"><a href="/contact/">Get a Free Quote</a></div>';
}
// Modify excerpt length (default 55 words)
add_filter('excerpt_length', function() { return 30; });
// Change wp_mail sender name
add_filter('wp_mail_from_name', function() { return 'My Company'; });
// Modify login redirect by role
add_filter('login_redirect', function($url, $request, $user) {
if (isset($user->roles) && in_array('editor', $user->roles)) {
return admin_url('edit.php');
}
return $url;
}, 10, 3);
Common Filter Hooks
| Hook | What It Filters |
|------|----------------|
| the_content | Post body before display |
| the_title | Post title before display |
| excerpt_length | Auto-excerpt word count |
| upload_mimes | Allowed upload file types |
| pre_get_posts | WP_Query before DB — modify main query |
| wp_mail_from | From email address |
| login_redirect | Post-login redirect URL |
Custom Hooks
// Define in plugin/theme — lets third-party code hook in
do_action('myplugin_after_lead_saved', $lead_id, $lead_data);
$price = apply_filters('myplugin_service_price', $base_price, $service_id);
// Third-party hooks in
add_action('myplugin_after_lead_saved', 'send_lead_to_crm', 10, 2);
add_filter('myplugin_service_price', 'apply_member_discount', 10, 2);
Priority Rules
- Default priority: 10
- Lower number = fires earlier
- Same priority + same hook = fires in order added
remove_action/remove_filtermust match the exact priority used when adding