Common WordPress Hooks Reference

John
18 min read

Introduction

This is a quick reference guide to the most frequently used WordPress hooks. These are the hooks you'll use in 90% of your WordPress development work.

Hook Categories

WordPress hooks are organized by functionality:

WORDPRESS HOOKS STRUCTURE
=========================

Initialization Hooks
├── plugins_loaded
├── init
├── after_setup_theme
└── wp_loaded

Template Hooks
├── wp_head
├── wp_footer
├── get_header
├── get_sidebar
└── get_footer

Content Hooks (Filters)
├── the_title
├── the_content
├── the_excerpt
└── body_class

Script/Style Hooks
├── wp_enqueue_scripts
├── admin_enqueue_scripts
└── login_enqueue_scripts

Admin Hooks
├── admin_menu
├── admin_init
├── save_post
└── admin_notices

User Hooks
├── user_register
├── wp_login
└── wp_logout

Initialization Hooks

plugins_loaded

Type: Action

When: After all plugins are loaded

Use: Plugin initialization, check for other plugins

add_action('plugins_loaded', 'my_plugin_init');

function my_plugin_init() {
    // Check if another plugin is active
    if (class_exists('WooCommerce')) {
        // Initialize WooCommerce integration
    }

    // Load text domain for translations
    load_plugin_textdomain('my-plugin', false, dirname(plugin_basename(__FILE__)) . '/languages');
}

init

Type: Action

When: WordPress initialization complete

Use: Register post types, taxonomies, shortcodes

add_action('init', 'my_custom_init');

function my_custom_init() {
    // Register custom post type
    register_post_type('book', [
        'public' => true,
        'label' => 'Books',
        'has_archive' => true,
    ]);

    // Register custom taxonomy
    register_taxonomy('genre', 'book', [
        'label' => 'Genres',
        'hierarchical' => true,
    ]);

    // Register shortcode
    add_shortcode('my_shortcode', 'my_shortcode_handler');
}

after_setup_theme

Type: Action

When: After theme is loaded

Use: Theme setup, add theme support

add_action('after_setup_theme', 'my_theme_setup');

function my_theme_setup() {
    // Add theme support
    add_theme_support('post-thumbnails');
    add_theme_support('custom-logo');
    add_theme_support('title-tag');

    // Register navigation menus
    register_nav_menus([
        'primary' => 'Primary Menu',
        'footer' => 'Footer Menu',
    ]);
}

wp_loaded

Type: Action

When: Everything is loaded (WordPress, plugins, theme)

Use: Operations requiring everything to be ready

add_action('wp_loaded', 'my_custom_operation');

function my_custom_operation() {
    // Everything is loaded, safe to use any WordPress function
    if (is_user_logged_in()) {
        // Do something for logged-in users
    }
}

Frontend Template Hooks

Type: Action

When: Inside <head> section before </head>

Use: Add meta tags, inline CSS, tracking codes

add_action('wp_head', 'add_custom_meta_tags');

function add_custom_meta_tags() {
    ?>
    <meta name="author" content="John Doe">
    <meta name="description" content="<?php echo get_the_excerpt(); ?>">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <?php
}

Type: Action

When: Before closing </body> tag

Use: Add scripts, analytics, modals, pop-ups

add_action('wp_footer', 'add_analytics_code');

function add_analytics_code() {
    ?>
    <script>
        // Google Analytics
        gtag('config', 'GA_MEASUREMENT_ID');
    </script>
    <?php
}

get_header

Type: Action

When: After header.php is loaded

Use: Modify header output

add_action('get_header', 'my_header_customization');

function my_header_customization() {
    // Add something after header
    echo '<div class="site-announcement">Special Offer!</div>';
}

get_sidebar

Type: Action

When: After sidebar.php is loaded

Use: Modify sidebar

add_action('get_sidebar', 'add_sidebar_ad');

function add_sidebar_ad() {
    echo '<div class="sidebar-ad">Advertisement</div>';
}

Type: Action

When: After footer.php is loaded

Use: Modify footer

add_action('get_footer', 'add_footer_widgets');

function add_footer_widgets() {
    dynamic_sidebar('footer-widgets');
}

Content Filters

the_title

Type: Filter

When: Post/page title is displayed

Parameters: $title, $post_id

Use: Modify post titles

add_filter('the_title', 'customize_title', 10, 2);

function customize_title($title, $post_id) {
    // Add emoji to product titles
    if (get_post_type($post_id) === 'product') {
        $title = '🛍️ ' . $title;
    }

    return $title;
}

the_content

Type: Filter

When: Post content is displayed

Parameters: $content

Use: Modify post content

add_filter('the_content', 'add_content_footer');

function add_content_footer($content) {
    // Only on single posts
    if (is_single()) {
        $footer = '<div class="content-footer">';
        $footer .= '<p>Share this article!</p>';
        $footer .= '</div>';

        $content .= $footer;
    }

    return $content;
}

the_excerpt

Type: Filter

When: Post excerpt is displayed

Parameters: $excerpt

Use: Modify excerpt

add_filter('the_excerpt', 'custom_excerpt');

function custom_excerpt($excerpt) {
    return $excerpt . ' <a href="' . get_permalink() . '">Read More &rarr;</a>';
}

excerpt_length

Type: Filter

When: Excerpt length is determined

Parameters: $length

Use: Change excerpt word count

add_filter('excerpt_length', 'custom_excerpt_length');

function custom_excerpt_length($length) {
    return 30; // Change from default 55 to 30 words
}

excerpt_more

Type: Filter

When: Excerpt "more" indicator is displayed

Parameters: $more

Use: Change [...] text

add_filter('excerpt_more', 'custom_excerpt_more');

function custom_excerpt_more($more) {
    return '... <a href="' . get_permalink() . '" class="read-more">Continue Reading</a>';
}

CSS Class Filters

body_class

Type: Filter

When: Body CSS classes are output

Parameters: $classes (array)

Use: Add custom body classes

add_filter('body_class', 'custom_body_classes');

function custom_body_classes($classes) {
    // Add logged-in class
    if (is_user_logged_in()) {
        $classes[] = 'user-logged-in';
    }

    // Add browser-specific class
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'Safari') !== false) {
        $classes[] = 'safari';
    }

    return $classes;
}

post_class

Type: Filter

When: Post CSS classes are output

Parameters: $classes, $class, $post_id

Use: Add custom post classes

add_filter('post_class', 'custom_post_classes', 10, 3);

function custom_post_classes($classes, $class, $post_id) {
    // Add featured class if post has thumbnail
    if (has_post_thumbnail($post_id)) {
        $classes[] = 'has-featured-image';
    }

    return $classes;
}

Script and Style Hooks

wp_enqueue_scripts

Type: Action

When: Frontend scripts/styles should be enqueued

Use: Add CSS/JS files to frontend

add_action('wp_enqueue_scripts', 'enqueue_custom_assets');

function enqueue_custom_assets() {
    // Enqueue stylesheet
    wp_enqueue_style(
        'custom-style',
        get_template_directory_uri() . '/css/custom.css',
        [],
        '1.0.0'
    );

    // Enqueue script
    wp_enqueue_script(
        'custom-script',
        get_template_directory_uri() . '/js/custom.js',
        ['jquery'],
        '1.0.0',
        true
    );

    // Pass data to JavaScript
    wp_localize_script('custom-script', 'myData', [
        'ajaxUrl' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('my-nonce'),
    ]);
}

admin_enqueue_scripts

Type: Action

When: Admin scripts/styles should be enqueued

Parameters: $hook (current admin page)

Use: Add CSS/JS to admin area

add_action('admin_enqueue_scripts', 'enqueue_admin_assets');

function enqueue_admin_assets($hook) {
    // Only load on our custom page
    if ($hook !== 'toplevel_page_my-plugin') {
        return;
    }

    wp_enqueue_style('my-admin-style', plugins_url('css/admin.css', __FILE__));
    wp_enqueue_script('my-admin-script', plugins_url('js/admin.js', __FILE__));
}

login_enqueue_scripts

Type: Action

When: Login page scripts/styles should be enqueued

Use: Customize login page

add_action('login_enqueue_scripts', 'custom_login_styles');

function custom_login_styles() {
    ?>
    <style>
        #login h1 a {
            background-image: url('<?php echo get_template_directory_uri(); ?>/images/logo.png');
            width: 200px;
            height: 100px;
            background-size: contain;
        }
    </style>
    <?php
}

Admin Hooks

admin_menu

Type: Action

When: Admin menu is being constructed

Use: Add admin menu pages

add_action('admin_menu', 'add_custom_admin_page');

function add_custom_admin_page() {
    add_menu_page(
        'My Plugin Settings',           // Page title
        'My Plugin',                    // Menu title
        'manage_options',               // Capability
        'my-plugin-settings',           // Menu slug
        'render_my_plugin_page',        // Callback function
        'dashicons-admin-generic',      // Icon
        20                              // Position
    );

    add_submenu_page(
        'my-plugin-settings',           // Parent slug
        'Advanced Settings',            // Page title
        'Advanced',                     // Menu title
        'manage_options',               // Capability
        'my-plugin-advanced',           // Menu slug
        'render_advanced_page'          // Callback
    );
}

function render_my_plugin_page() {
    ?>
    <div class="wrap">
        <h1>My Plugin Settings</h1>
        <form method="post" action="options.php">
            <?php
            settings_fields('my-plugin-settings');
            do_settings_sections('my-plugin-settings');
            submit_button();
            ?>
        </form>
    </div>
    <?php
}

admin_init

Type: Action

When: Admin area is initialized

Use: Register settings, redirect, check permissions

add_action('admin_init', 'register_my_settings');

function register_my_settings() {
    // Register setting
    register_setting('my-plugin-settings', 'my_option');

    // Add settings section
    add_settings_section(
        'my-settings-section',
        'General Settings',
        'my_settings_section_callback',
        'my-plugin-settings'
    );

    // Add settings field
    add_settings_field(
        'my-field',
        'My Setting',
        'my_field_callback',
        'my-plugin-settings',
        'my-settings-section'
    );
}

function my_settings_section_callback() {
    echo '<p>Configure your settings below:</p>';
}

function my_field_callback() {
    $value = get_option('my_option', '');
    echo '<input type="text" name="my_option" value="' . esc_attr($value) . '">';
}

save_post

Type: Action

When: Post is saved

Parameters: $post_id, $post, $update

Use: Save custom data, trigger actions

add_action('save_post', 'save_custom_metadata', 10, 3);

function save_custom_metadata($post_id, $post, $update) {
    // Don't save during autosave
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return;
    }

    // Check user permissions
    if (!current_user_can('edit_post', $post_id)) {
        return;
    }

    // Check nonce
    if (!isset($_POST['my_nonce']) || !wp_verify_nonce($_POST['my_nonce'], 'my_action')) {
        return;
    }

    // Save custom field
    if (isset($_POST['custom_field'])) {
        update_post_meta($post_id, '_custom_field', sanitize_text_field($_POST['custom_field']));
    }

    // Clear cache when post is updated
    if ($update) {
        delete_transient('homepage_posts');
    }
}

admin_notices

Type: Action

When: Admin notices should be displayed

Use: Show admin messages

add_action('admin_notices', 'show_custom_notice');

function show_custom_notice() {
    $screen = get_current_screen();

    if ($screen->id === 'edit-post') {
        ?>
        <div class="notice notice-info is-dismissible">
            <p>Welcome to the post editor!</p>
        </div>
        <?php
    }
}

User Hooks

user_register

Type: Action

When: New user is registered

Parameters: $user_id

Use: Set up new user data, send welcome email

add_action('user_register', 'setup_new_user', 10, 1);

function setup_new_user($user_id) {
    // Add custom user meta
    add_user_meta($user_id, 'registration_date', current_time('mysql'));

    // Send welcome email
    $user = get_userdata($user_id);
    wp_mail(
        $user->user_email,
        'Welcome to our site!',
        'Thank you for registering...'
    );

    // Add to mailing list
    subscribe_to_newsletter($user->user_email);
}

wp_login

Type: Action

When: User logs in

Parameters: $user_login, $user

Use: Track logins, redirect, update data

add_action('wp_login', 'track_user_login', 10, 2);

function track_user_login($user_login, $user) {
    // Update last login time
    update_user_meta($user->ID, 'last_login', current_time('mysql'));

    // Log the login
    error_log("User {$user_login} logged in");

    // Increment login count
    $login_count = get_user_meta($user->ID, 'login_count', true);
    update_user_meta($user->ID, 'login_count', $login_count + 1);
}

wp_logout

Type: Action

When: User logs out

Use: Clean up session data, track logouts

add_action('wp_logout', 'handle_user_logout');

function handle_user_logout() {
    $user_id = get_current_user_id();

    // Update logout time
    update_user_meta($user_id, 'last_logout', current_time('mysql'));

    // Clear custom session data
    delete_user_meta($user_id, 'temp_session_data');
}

Comment Hooks

comment_post

Type: Action

When: Comment is posted

Parameters: $comment_id, $comment_approved

Use: Process comments, notifications

add_action('comment_post', 'notify_on_comment', 10, 2);

function notify_on_comment($comment_id, $comment_approved) {
    if ($comment_approved === 1) {
        $comment = get_comment($comment_id);
        $post = get_post($comment->comment_post_ID);

        // Notify post author
        wp_mail(
            get_the_author_meta('user_email', $post->post_author),
            'New comment on your post',
            "Someone commented on: {$post->post_title}"
        );
    }
}

comment_text

Type: Filter

When: Comment text is displayed

Parameters: $comment_text

Use: Modify comment display

add_filter('comment_text', 'highlight_admin_comments');

function highlight_admin_comments($comment_text) {
    $comment = get_comment();

    if (user_can($comment->user_id, 'administrator')) {
        $comment_text = '<div class="admin-comment">' . $comment_text . '</div>';
    }

    return $comment_text;
}

Widget Hooks

widgets_init

Type: Action

When: Widgets are initialized

Use: Register widget areas, custom widgets

add_action('widgets_init', 'register_custom_sidebars');

function register_custom_sidebars() {
    // Register sidebar
    register_sidebar([
        'name' => 'Footer Sidebar',
        'id' => 'footer-sidebar',
        'before_widget' => '<div class="widget">',
        'after_widget' => '</div>',
        'before_title' => '<h3 class="widget-title">',
        'after_title' => '</h3>',
    ]);

    // Register custom widget
    register_widget('My_Custom_Widget');
}

Query Hooks

pre_get_posts

Type: Action

When: Before posts are queried

Parameters: $query (WP_Query object)

Use: Modify queries

add_action('pre_get_posts', 'modify_main_query');

function modify_main_query($query) {
    // Only modify main query on frontend
    if (!is_admin() && $query->is_main_query()) {
        // Show 20 posts on blog page
        if ($query->is_home()) {
            $query->set('posts_per_page', 20);
        }

        // Exclude category from blog
        if ($query->is_home()) {
            $query->set('cat', '-5'); // Exclude category ID 5
        }
    }
}

Quick Reference Tables

Most Common Actions

HookWhenCommon Use
initWordPress loadedRegister CPTs, taxonomies
wp_enqueue_scriptsEnqueue time (frontend)Add CSS/JS
admin_enqueue_scriptsEnqueue time (admin)Add admin CSS/JS
wp_headIn <head>Meta tags, CSS
wp_footerBefore </body>Scripts, analytics
admin_menuBuilding admin menuAdd admin pages
save_postPost savedSave metadata
user_registerUser registeredWelcome email
wp_loginUser logged inTrack login

Most Common Filters

HookWhat It FiltersCommon Use
the_titlePost titleModify titles
the_contentPost contentAdd content
the_excerptPost excerptCustomize excerpt
body_classBody CSS classesAdd classes
post_classPost CSS classesConditional classes
excerpt_lengthExcerpt word countChange length
login_redirectLogin redirect URLCustom redirect
upload_mimesAllowed file typesAdd file types

Summary

This reference covers the most essential WordPress hooks. Remember:

  • Actions: Use to execute code at specific points
  • Filters: Use to modify data before it's used
  • Check the WordPress Developer Reference for complete documentation
  • Use appropriate hooks for your specific needs
  • Always check if you're in the right context (frontend/admin/etc.)