save_post
Fires after a post of any type is created or updated. Use it to save extra data or clear caches when content changes.
When it fires
WordPress fires save_post at the end of wp_insert_post(), once the post has been written to the database. That covers publishing and updating in the editor, Quick Edit, imports and the REST API, but also revisions, autosaves and moving a post to the bin.
If the edit screen has classic meta boxes, the block editor saves them in a second request, which fires save_post again.
Parameters
$post_idint |
Post ID. |
|---|---|
$postWP_Post |
Post object. |
$updatebool |
Whether this is an existing post being updated. |
Example: Record who last edited a post
add_action( 'save_post', function ( $post_id, $post, $update ) {
if ( ! $update || wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
return;
}
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
if ( 'post' !== $post->post_type || ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
update_post_meta( $post_id, '_my_last_editor', get_current_user_id() );
}, 10, 3 );
Good to know
- Use save_post_{post_type}, for example save_post_page, to run for one post type only.
- Calling wp_update_post() inside this hook fires save_post again. Remove your callback first, or you'll create an endless loop.
- Terms and custom fields sent through the REST API can be saved after this hook runs. If you need them, use wp_after_insert_post (WordPress 5.6 and later).