Skip Navigation

[Resolved] How to make post visible to only logged in users?

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Sun Mon Tue Wed Thu Fri Sat
- 9:00 – 13:00 9:00 – 13:00 9:00 – 13:00 9:00 – 13:00 9:00 – 13:00 -
- 14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 -

Supporter timezone: Asia/Karachi (GMT+05:00)

This topic contains 9 replies, has 2 voices.

Last updated by himanshuS 1 year, 7 months ago.

Assisted by: Waqar.


Hey there,
It seems something that should be very easy to do but I am struggling with it. Here is my scenario -

1. I have a custom post type called 'Portfolio'.
2. This post type is created when a new user registers. Every user gets one portfolio post.
3. On creation, the post status is draft. Visibility is public. The user has full control to share, hide or leave it alone.
4. On the edit portfolio form, there are three options - A) Keep portfolio visible to me (author), B) Visible to logged-in users, C) Visible to everyone
5. I have been able to achieve A) and C) by changing the post status to draft and publish, respectively.
6. However, I am unable to achieve option (B) by publishing the post and changing visibility to private. I just get a 404 page.
7. In toolset access settings, every user role can view a post so it does not seem like an access issue.

My question is - how do I make a portfolio only visible to logged-in users, irrespective of roles IF the author chooses option B.


Also, I am unable to see an option to change post status to private for the custom post type. is that normal?

Link - hidden link



Languages: English (English )

Timezone: Asia/Karachi (GMT+05:00)



To deploy this content display logic, you can use the filter "wpv_filter_force_template":

You'll need two content templates for the "Portfolio" post type:
1. Regular content template that will show the content of the post
2. "No access" content template that will only show messages that you're allowed to view this page.

In the custom function attached to the "wpv_filter_force_template" filter, you'll check if it is a single Portfolio page and the option 'Visible to logged-in users' is selected, then see if the current visitor is logged in or not. If logged in, continue with the regular content template and if not, override and use the 'no access' content template.

In WordPress, the "Private" status is not available in the post status field. It can be controlled through the visibility field, as shown in the attached screenshot.



Thanks Waqar. But there is a better way to solve this issue.

We can edit the access setting for the user and allow them to view private posts. That way I am able to access the private post as a logged in user. But, it seems like I am not able to redirect users who are logged out from the 404 page to a login page if the post is in publish or private status.

Here is the code -

 * New custom code snippet (replace this with snippet description).

toolset_snippet_security_check() or die( 'Direct access is not allowed' );

// Put the code of your snippet below this comment.

add_action('init', 'redirect_private_draft_portfolios');

function redirect_private_draft_portfolios(){
global $post;
$post_type = get_post_type( $post->ID );
  if($post_type == 'portfolio'){
  $current_user_id = get_current_user_id();
  $post_status = get_post_status();
   $login_url = '<em><u>hidden link</u></em>';
    // redirect private posts and draft posts for logged out users
    $disallowed_status = array('draft','private');
  if($current_user_id == 0 && in_array($post_status,$disallowed_status)) {
   wp_redirect( $login_url );   
  } // redirect for private and draft posts for logges out users
    //redirect logged in users from portfolio if it is in draft status  
 if($current_user_id != 0 && $post_status =='draft') {
  wp_redirect( $login_url );  
  } // check if portfolio post type
} // end of function

What am I missing?



Languages: English (English )

Timezone: Asia/Karachi (GMT+05:00)

Thanks for writing back.

Can you please make sure that the "wp_redirect" calls are followed by "exit;"?
( ref: )



Languages: English (English )

Timezone: Asia/Karachi (GMT+05:00)

Another point to note here is that you'll also need to replace the "init" hook with the "template_redirect" hook because the "global $post;" is not available by the time the "init" hook is executed.


Thanks for the feedback. I applied your code change and I am still getting a 404.

Link - hidden link



Languages: English (English )

Timezone: Asia/Karachi (GMT+05:00)

Can you please share temporary admin login details, in reply to this message?

I'll also need your permission to download a clone/snapshot of the website, in case it needs to be investigated on a different server.

Note: Your next reply will be private and though no changes will be made on your website, it is recommended to make a complete backup copy, before sharing the access details.



Languages: English (English )

Timezone: Asia/Karachi (GMT+05:00)

Thank you for sharing these details.

During testing on my website with a similar setup, I discovered that the custom code is not working for the guests (i.e. non-logged-in visitors) because the global "$post" object is not set for them in case of draft or private post.

I was able to make this redirection work, using a different approach to get the current page/post information:

add_action('template_redirect', 'redirect_private_draft_portfolios');
function redirect_private_draft_portfolios() {

	global $wp_query, $wpdb;

	// set the login URL
	$login_url = '<em><u>hidden link</u></em>';
	// get current post's ID
	$page_id = $wpdb->get_var( $wp_query->request );
	// get current post's status
	$post_status = get_post_status( $page_id );
	// get current post's type
	$post_type = get_post_type( $page_id );

	// check if specific post type
	if( $post_type == 'portfolio' ) {
		// get current visitor's status
		$current_user_id = get_current_user_id();
		// if visitor is guest and post status is 'draft' or 'private'
		if( ($current_user_id == 0) && ($post_status == 'draft' || $post_status == 'private') ) {
			// redirect to the login page
			wp_redirect( $login_url, 302, 'Prowess' );  
		// if visitor is user and post status is 'draft'
		if( ($current_user_id != 0) && ($post_status =='draft') ) {
			wp_redirect( $login_url, 302, 'Prowess' );  



As usual amazing work, Waqar. My issue is resolved now. Thank you!

This ticket is now closed. If you're a WPML client and need related help, please open a new support ticket.