# Members-Only Posts and Pages With Role Choice

> Adds a "Members only" box to the post and page editor; restricted content shows a login prompt to visitors and to roles you did not tick, and stays out of search and feeds for them.

- Type: PHP
- Runs: Run everywhere
- Category: [Memberships](https://wpide.com/library/category/memberships/)
- Tags: members, restrict, content
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/members-only-posts-meta-box/

## Code

```php
// Post types that get the box.
$wpide_mo_post_types = array( 'post', 'page' );

$wpide_mo_can_view = function ( $post_id ) {
    if ( ! get_post_meta( $post_id, '_wpide_members_only', true ) ) {
        return true;
    }

    if ( ! is_user_logged_in() ) {
        return false;
    }

    $roles = (array) get_post_meta( $post_id, '_wpide_members_roles', true );
    $roles = array_filter( $roles );

    return ! $roles || array_intersect( $roles, (array) wp_get_current_user()->roles ) || current_user_can( 'edit_post', $post_id );
};

add_action( 'add_meta_boxes', function () use ( $wpide_mo_post_types ) {
    add_meta_box( 'wpide-members-only', 'Members only', function ( $post ) {
        $roles = array_filter( (array) get_post_meta( $post->ID, '_wpide_members_roles', true ) );
        wp_nonce_field( 'wpide_members_only', 'wpide_members_only_nonce' );
        printf( '<p><label><input type="checkbox" name="wpide_members_only" value="1" %s> Only logged-in members can read this</label></p><p>Limit to these roles (optional):</p>', checked( (bool) get_post_meta( $post->ID, '_wpide_members_only', true ), true, false ) );

        foreach ( wp_roles()->role_names as $role => $name ) {
            printf( '<label style="display:block"><input type="checkbox" name="wpide_members_roles[]" value="%1$s" %2$s> %3$s</label>', esc_attr( $role ), checked( in_array( $role, $roles, true ), true, false ), esc_html( translate_user_role( $name ) ) );
        }
    }, $wpide_mo_post_types, 'side' );
} );

add_action( 'save_post', function ( $post_id ) {
    if ( ! isset( $_POST['wpide_members_only_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['wpide_members_only_nonce'] ), 'wpide_members_only' ) ) {
        return;
    }

    if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) || ! current_user_can( 'edit_post', $post_id ) ) {
        return;
    }

    if ( empty( $_POST['wpide_members_only'] ) ) {
        delete_post_meta( $post_id, '_wpide_members_only' );
        delete_post_meta( $post_id, '_wpide_members_roles' );
        return;
    }

    $roles = isset( $_POST['wpide_members_roles'] ) ? array_map( 'sanitize_key', (array) wp_unslash( $_POST['wpide_members_roles'] ) ) : array();
    update_post_meta( $post_id, '_wpide_members_only', 1 );
    update_post_meta( $post_id, '_wpide_members_roles', array_values( array_intersect( $roles, array_keys( wp_roles()->role_names ) ) ) );
} );

$wpide_mo_message = function () {
    $login = wp_login_url( get_permalink() );

    if ( is_user_logged_in() ) {
        return '<div class="wpide-members-only"><p>This content is not available with your current membership.</p></div>';
    }

    $html = '<div class="wpide-members-only"><p>This content is for members. <a href="' . esc_url( $login ) . '">Log in</a>';

    if ( get_option( 'users_can_register' ) ) {
        $html .= ' or <a href="' . esc_url( wp_registration_url() ) . '">create a free account</a>';
    }

    return $html . ' to keep reading.</p></div>';
};

add_filter( 'the_content', function ( $content ) use ( $wpide_mo_can_view, $wpide_mo_message ) {
    $post = get_post();

    return ( $post && ! $wpide_mo_can_view( $post->ID ) ) ? $wpide_mo_message() : $content;
}, 1 );

add_filter( 'get_the_excerpt', function ( $excerpt, $post ) use ( $wpide_mo_can_view ) {
    return ( $post && ! $wpide_mo_can_view( $post->ID ) ) ? '' : $excerpt;
}, 10, 2 );

// Keep restricted items out of search results and feeds for visitors.
add_action( 'pre_get_posts', function ( $query ) {
    if ( is_admin() || is_user_logged_in() || ! $query->is_main_query() || ! ( $query->is_search() || $query->is_feed() ) ) {
        return;
    }

    $meta   = (array) $query->get( 'meta_query' );
    $meta[] = array( 'key' => '_wpide_members_only', 'compare' => 'NOT EXISTS' );
    $query->set( 'meta_query', $meta );
} );
```

## Notes

Tick no roles to allow every logged-in user. Titles stay public; only the content and excerpt are hidden. Works in the block and classic editors.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Members-Only Posts and Pages With Role Choice" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
