Halloween Sale 15% off Ends in See the plans
PHP

Inactive Subscribers Cleanup Page

Adds Users > Inactive Subscribers, listing subscriber accounts older than two years that have never commented, with checkboxes to delete the ones you select after a confirmation.

Don’t have WPIDE yet? Install it on your site

Code

// Accounts registered more than this many days ago are listed.
$wpide_inactive_days = 730;

add_action( 'admin_menu', function () use ( $wpide_inactive_days ) {
    add_users_page( 'Inactive Subscribers', 'Inactive Subscribers', 'delete_users', 'wpide-inactive-subscribers', function () use ( $wpide_inactive_days ) {
        global $wpdb;

        if ( ! current_user_can( 'delete_users' ) ) {
            return;
        }

        if ( isset( $_POST['wpide_delete_users'] ) && check_admin_referer( 'wpide_inactive_delete' ) ) {
            require_once ABSPATH . 'wp-admin/includes/user.php';
            $deleted = 0;
            foreach ( array_map( 'absint', (array) wp_unslash( $_POST['wpide_delete_users'] ) ) as $user_id ) {
                $user = get_userdata( $user_id );
                if ( $user && array( 'subscriber' ) === array_values( $user->roles ) && get_current_user_id() !== $user_id && wp_delete_user( $user_id ) ) {
                    $deleted++;
                }
            }
            printf( '<div class="notice notice-success"><p>%s</p></div>', esc_html( sprintf( 'Deleted %d account(s).', $deleted ) ) );
        }

        $users = get_users( array(
            'role'         => 'subscriber',
            'number'       => 200,
            'orderby'      => 'registered',
            'order'        => 'ASC',
            'date_query'   => array( array( 'column' => 'user_registered', 'before' => $wpide_inactive_days . ' days ago' ) ),
            'fields'       => array( 'ID', 'user_login', 'user_email', 'user_registered' ),
            'count_total'  => false,
        ) );

        $with_comments = array();
        if ( $users ) {
            $ids           = implode( ',', array_map( 'intval', wp_list_pluck( $users, 'ID' ) ) );
            $with_comments = array_map( 'intval', $wpdb->get_col( "SELECT DISTINCT user_id FROM {$wpdb->comments} WHERE user_id IN ($ids)" ) );
        }

        echo '<div class="wrap"><h1>Inactive Subscribers</h1>';
        echo '<p>' . esc_html( sprintf( 'Subscribers registered more than %d days ago who have never commented (first 200).', $wpide_inactive_days ) ) . '</p>';
        echo '<form method="post" onsubmit="return confirm(\'Delete the selected accounts permanently?\');">';
        wp_nonce_field( 'wpide_inactive_delete' );
        echo '<table class="widefat striped"><thead><tr><td class="check-column"></td><th>User</th><th>Email</th><th>Registered</th></tr></thead><tbody>';
        $shown = 0;
        foreach ( $users as $user ) {
            if ( in_array( (int) $user->ID, $with_comments, true ) ) {
                continue;
            }
            $shown++;
            printf(
                '<tr><th class="check-column"><input type="checkbox" name="wpide_delete_users[]" value="%1$d" aria-label="%2$s"></th><td>%3$s</td><td>%4$s</td><td>%5$s</td></tr>',
                (int) $user->ID,
                esc_attr( 'Select ' . $user->user_login ),
                esc_html( $user->user_login ),
                esc_html( $user->user_email ),
                esc_html( mysql2date( get_option( 'date_format' ), $user->user_registered ) )
            );
        }
        if ( ! $shown ) {
            echo '<tr><td colspan="4">No inactive subscribers found.</td></tr>';
        }
        echo '</tbody></table>';
        if ( $shown ) {
            submit_button( 'Delete selected accounts', 'delete' );
        }
        echo '</form></div>';
    } );
} );

Notes

Only the subscriber role is listed and nothing is deleted without your confirmation; customers of shops and members of membership plugins usually have their own roles.

How to add this snippet

  1. Install WPIDE on your WordPress site (it is free) and open Code Snippets.
  2. Use snippet above adds it from the library in one click. Or copy the code into a new snippet with the same code type.
  3. It is added inactive: review the code and settings, then switch it on.

Have a snippet worth sharing?

Publish it to the library from WPIDE or right here. Sign in with any WordPress site that runs WPIDE, free or Pro. Public snippets are reviewed by the WPIDE team before they appear.

Which site should get this snippet?

Enter the address of your WordPress site. WPIDE opens there in a new tab with the snippet ready to review and save.

Remembered in this browser only, so you are asked once.

Report this snippet

Tell the WPIDE team what is wrong: broken code, something harmful, spam or copied work.