Build WordPress plugins from scratch: actions and filters, shortcodes, settings pages, custom post types, meta boxes, AJAX, REST endpoints, custom tables, cron and blocks.
Lessons
An action hook is a named point in WordPress's execution where it calls every function registered with add_action() for that name — letting your plugin run code when a post is saved, a user logs in or a page is rendered.
<?php
add_action(
'publish_post', // 1. The hook name.
'gdc_books_notify_admin', // 2. Your callback.
10, // 3. Priority: lower numbers run first. Default 10.
2 // 4. How many arguments your callback accepts. Default 1.
);
function gdc_books_notify_admin( $post_id, $post ) {
wp_mail(
get_option( 'admin_email' ),
'New post published',
sprintf( '"%s" was just published: %s', $post->post_title, get_permalink( $post_id ) )
);
}WordPress core contains do_action( 'publish_post', $post_id, $post ). When that line runs, it calls every callback registered for publish_post, passing the arguments along. Because you set the fourth parameter to 2, your function receives both.
Watch out: The single most common hook bug: your callback expects two arguments but you left the fourth parameter of add_action() at its default of 1. PHP then throws "Too few arguments". If your function signature has N parameters, pass N.When several callbacks hook the same action, priority decides the order. Callbacks with the same priority run in the order they were added.
<?php
add_action( 'wp_footer', 'gdc_books_footer_last', 100 ); // Runs after most others.
add_action( 'wp_footer', 'gdc_books_footer_first', 1 ); // Runs before most others.| Hook | Fires when | Typical use |
|---|---|---|
plugins_loaded | Every plugin is loaded | Check for other plugins, run upgrades |
init | WordPress is ready, before output | Register post types, taxonomies, shortcodes, blocks |
admin_menu | Building the dashboard menu | Add admin pages |
admin_init | Every admin page load | Register settings, handle admin form posts |
wp_enqueue_scripts | Front-end assets are being collected | Load front-end CSS and JS |
admin_enqueue_scripts | Admin assets are being collected | Load admin CSS and JS |
save_post | A post is saved | Save meta box fields |
rest_api_init | The REST API is starting | Register REST routes |
template_redirect | Before a front-end template loads | Redirects and access control |
<?php
// A method on an object:
add_action( 'init', array( $plugin, 'register_post_types' ) );
// A static method:
add_action( 'init', array( 'GDC_Books_Setup', 'register' ) );
// A closure — fine for tiny callbacks, but it can never be removed later:
add_action( 'init', function () {
add_post_type_support( 'page', 'excerpt' );
} );Tip: Prefer named functions or methods for anything another plugin or a site owner might want to switch off. remove_action() needs the exact same callback, and a closure cannot be referred to a second time.<?php
// Remove a callback: same hook, same callback, same priority.
remove_action( 'wp_head', 'wp_generator' );
// Has it been added?
if ( has_action( 'init', 'gdc_books_register_post_type' ) ) { /* ... */ }
// Has the hook already fired? Useful before relying on something registered there.
if ( did_action( 'init' ) ) { /* ... */ }publish_post and write the post title to debug.log with error_log().wp_footer callbacks with priorities 1 and 100 and check the output order in the page source.In accordance with Section 6 & Section 7 of the DPDP Act 2023, third-party analytics and marketing trackers are strictly gated behind your affirmative consent. You may withdraw consent at any time under Section 6(4).
Essential for session authentication (ci_session), Cross-Site Request Forgery security (csrf_cookie_name), and Cloudflare DDoS/bot prevention. Cannot be disabled.
Gated under DPDP Section 7. Allows Google Analytics 4 (Google Consent Mode v2) to measure aggregate, anonymized tool usage.
Enables browser local storage to preserve your theme selection (dark/light mode) and code editor layout between visits.
Used to display developer sponsorships and native tool partner notices.