Action Hook since 1.2.0
before_delete_post
Fires right before a post is permanently deleted
Description
before_delete_post is your last chance to act while the post (and its data) still exists — right after this, wp_delete_post() removes the row for good.
When it runs
Inside wp_delete_post(), only for a hard/permanent delete — does not fire when a post is simply moved to Trash (that's wp_trash_post).
Signature
do_action( 'before_delete_post', int $post_id, WP_Post $post );Parameters
$post_idint — ID of the post about to be deleted.$postWP_Post — The post object, still intact at this point.
Examples
Basic
add_action( 'before_delete_post', function( $post_id, $post ) {
if ( 'book' !== $post->post_type ) {
return;
}
global $wpdb;
$wpdb->delete( $wpdb->prefix . 'book_ratings', [ 'post_id' => $post_id ] );
}, 10, 2 );Delete an associated custom table row before the post itself is gone.
Real case
add_action( 'before_delete_post', function( $post_id ) {
$file = get_post_meta( $post_id, 'attached_export_file', true );
if ( $file && file_exists( $file ) ) {
unlink( $file );
}
} );Remove a generated file tied to the post before the post record disappears.
Common Use Cases
- Clean up custom database rows tied to a post
- Delete associated generated/uploaded files
- Sync the deletion to an external system
- Log permanent deletions for an audit trail
Common mistakes
- Confusing this with wp_trash_post — before_delete_post only fires on permanent deletion, never when a post is moved to Trash
Related hooks
FAQ
Does before_delete_post fire when I click 'Trash' on a post?
No. Moving a post to Trash fires wp_trash_post instead. before_delete_post only fires for a permanent/hard delete — either from Trash or via force-delete.
Source: wp-includes/post.php