Action Hook since 1.2.0
wp_insert_post
Fires immediately after a post is inserted or updated in the database
Description
wp_insert_post looks like save_post but fires from every wp_insert_post() call, including programmatic inserts that never touch the block editor.
When it runs
Inside wp_insert_post(), right after the database write, just before save_post fires.
Signature
do_action( 'wp_insert_post', int $post_id, WP_Post $post, bool $update );Parameters
$post_idint — Inserted/updated post ID.$postWP_Post — Post object.$updatebool — True when updating an existing post.
Examples
Basic
add_action( 'wp_insert_post', function( $post_id, $post, $update ) {
if ( 'book' !== $post->post_type || $update ) {
return;
}
wp_mail( get_option( 'admin_email' ), 'New book added', get_the_title( $post_id ) );
}, 10, 3 );Email an admin only when a brand-new book post is created.
Common Use Cases
- Notify on new post creation (not updates)
- React to programmatic/import inserts
- Sync newly created posts to an external system
Common mistakes
- Using wp_insert_post to detect edits from the editor UI — save_post is the more common choice there; this fires for ALL inserts including imports
Related hooks
FAQ
Should I use wp_insert_post or save_post?
Use save_post for editor-driven saves; use wp_insert_post if you also need to catch posts created programmatically outside the editor.
Source: wp-includes/post.php