# Private Pages for Individual Members

> Adds a "Page owner" setting to pages so you can build a private page for one member or client; only that person and editors can open it, and a [wpide_my_pages] shortcode lists a member's pages.

- Type: PHP
- Runs: Run everywhere
- Category: [Memberships](https://wpide.com/library/category/memberships/)
- Tags: private, members, pages
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/private-client-pages/

## Code

```php
add_action( 'add_meta_boxes_page', function ( $post ) {
    add_meta_box( 'wpide-page-owner', 'Page owner', function ( $post ) {
        wp_nonce_field( 'wpide_page_owner', 'wpide_page_owner_nonce' );
        echo '<p><label for="wpide-page-owner">Only this member (and editors) can view the page:</label></p>';
        wp_dropdown_users( array(
            'name'              => 'wpide_page_owner',
            'id'                => 'wpide-page-owner',
            'selected'          => (int) get_post_meta( $post->ID, '_wpide_page_owner', true ),
            'show_option_none'  => 'Everyone (not private)',
            'option_none_value' => 0,
        ) );
    }, 'page', 'side' );
} );

add_action( 'save_post_page', function ( $post_id ) {
    if ( ! isset( $_POST['wpide_page_owner_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['wpide_page_owner_nonce'] ), 'wpide_page_owner' ) || ! current_user_can( 'edit_post', $post_id ) ) {
        return;
    }

    $owner = isset( $_POST['wpide_page_owner'] ) ? absint( $_POST['wpide_page_owner'] ) : 0;

    if ( $owner ) {
        update_post_meta( $post_id, '_wpide_page_owner', $owner );
    } else {
        delete_post_meta( $post_id, '_wpide_page_owner' );
    }
} );

add_action( 'template_redirect', function () {
    if ( ! is_page() ) {
        return;
    }

    $page_id = get_queried_object_id();
    $owner   = (int) get_post_meta( $page_id, '_wpide_page_owner', true );

    if ( ! $owner || get_current_user_id() === $owner || current_user_can( 'edit_post', $page_id ) ) {
        return;
    }

    if ( ! is_user_logged_in() ) {
        auth_redirect();
    }

    global $wp_query;
    $wp_query->set_404();
    status_header( 404 );
    nocache_headers();
} );

add_shortcode( 'wpide_my_pages', function () {
    if ( ! is_user_logged_in() ) {
        return '';
    }

    $pages = get_posts( array(
        'post_type'     => 'page',
        'numberposts'   => 50,
        'meta_key'      => '_wpide_page_owner',
        'meta_value'    => get_current_user_id(),
        'orderby'       => 'title',
        'order'         => 'ASC',
        'no_found_rows' => true,
    ) );

    if ( ! $pages ) {
        return '<p>You do not have any private pages yet.</p>';
    }

    $html = '<ul class="wpide-my-pages">';
    foreach ( $pages as $page ) {
        $html .= '<li><a href="' . esc_url( get_permalink( $page ) ) . '">' . esc_html( get_the_title( $page ) ) . '</a></li>';
    }

    return $html . '</ul>';
} );
```

## Notes

Visitors are sent to the login screen and other members get a 404, so the page's existence is not revealed.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Private Pages for Individual Members" 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/
