How to Register a Custom Post Type in WordPress (Step-by-Step)
The complete register_post_type() walkthrough, including the rewrite-rules gotcha that causes a confusing 404 every time.
Hooks are the mechanism that makes WordPress genuinely extensible without ever editing core files — and understanding them is the difference between "copying snippets from Stack Overflow" and actually being able to build anything in WordPress.
Think of WordPress core as running through its request lifecycle and periodically shouting "anyone want to do something here?" (an action) or "here's a value, does anyone want to change it before I use it?" (a filter). Your code just registers to listen.
add_action('init', 'my_function');
add_action('wp_enqueue_scripts', 'my_function');
add_action('admin_menu', 'my_function');
add_action('save_post', 'my_function');
Each of these fires at a genuinely different, specific moment in the request — init early and on every request, save_post only when a post is saved, admin_menu only in the admin area.
add_filter('body_class', function ($classes) {
$classes[] = 'my-custom-class';
return $classes;
});
The rule that trips up beginners most: a filter callback must always return a value — usually a modified version of what it received. Forget the return and you'll silently wipe out the value entirely.
add_action('wp_footer', 'my_function', 20, 1);
// ^ ^
// priority number of arguments accepted
Lower priority numbers run first (default is 10). If two plugins hook the same action, priority controls execution order — useful when your code needs to run after (or before) another plugin's.
You're not limited to WordPress core's hooks — plugins and themes commonly expose their own, so other developers can extend THEM the same way:
do_action('mytheme_before_footer');
$value = apply_filters('mytheme_footer_text', 'Default footer text');
Any well-built WordPress theme or plugin is really just a long, deliberate list of actions and filters — nothing more exotic than that underneath.
The complete register_post_type() walkthrough, including the rewrite-rules gotcha that causes a confusing 404 every time.
Field groups, repeaters, displaying ACF data in templates, and registering fields in code so they ship with your theme.
Actions vs filters, safe functions.php structure, and the defensive habits that keep a single typo from taking down your site.