# Members-Only Post Type

> Sends logged-out visitors to the login page when they open entries or the archive of a chosen post type, and hides those entries from them in the REST API.

- Type: PHP
- Runs: Run everywhere
- Category: [Custom Post Types & Fields](https://wpide.com/library/category/post-types/)
- Tags: members, custom-post-types, access
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/members-only-post-type/

## Code

```php
// Post types only logged-in users may see.
$wpide_members_types = array( 'resource' );

add_action( 'template_redirect', function () use ( $wpide_members_types ) {
    if ( is_user_logged_in() || ! ( is_singular( $wpide_members_types ) || is_post_type_archive( $wpide_members_types ) ) ) {
        return;
    }

    $requested = home_url( add_query_arg( array() ) );
    wp_safe_redirect( wp_login_url( $requested ) );
    exit;
} );

foreach ( $wpide_members_types as $wpide_members_type ) {
    add_filter( "rest_{$wpide_members_type}_query", function ( $args ) {
        if ( ! is_user_logged_in() ) {
            $args['post__in'] = array( 0 );
        }

        return $args;
    } );
}

add_filter( 'rest_request_before_callbacks', function ( $response, $handler, $request ) use ( $wpide_members_types ) {
    if ( is_user_logged_in() || is_wp_error( $response ) ) {
        return $response;
    }

    foreach ( $wpide_members_types as $type ) {
        $object = get_post_type_object( $type );

        if ( $object && $object->show_in_rest && 0 === strpos( $request->get_route(), '/' . ( $object->rest_namespace ?: 'wp/v2' ) . '/' . ( $object->rest_base ?: $type ) . '/' ) ) {
            return new WP_Error( 'rest_forbidden', 'Please log in to view this content.', array( 'status' => 401 ) );
        }
    }

    return $response;
}, 10, 3 );

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

    $types = $query->get( 'post_type' );

    if ( $types && 'any' !== $types ) {
        $query->set( 'post_type', array_values( array_diff( (array) $types, $wpide_members_types ) ) );
    } else {
        $query->set( 'post_type', array_values( array_diff( get_post_types( array( 'exclude_from_search' => false ) ), $wpide_members_types ) ) );
    }
} );
```

## Notes

After logging in, visitors return to the page they wanted. Combine with noindex if the content was public before.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Members-Only Post Type" 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/
