Ways to Restrict Content in your code with WooCommerce Memberships

In this tutorial — custom text and HTML restriction by a user membership plan. Conditional checks for custom post types and taxonomies. Code only.

#WooCommerce, #WCMemberships  /    /   23

How to Give Custom Content Access for Users with Any Active Memberships #

1. [wcm_restrict] basic usage

The easiest way to restrict content is with the help of WooCommerce Memberships shortcodes. The advantage of this method is that you can use it in your content editor in /wp-admin/ and directly in the code as well. In the post editor it will look like this:

We begin with the public content.
 
[wcm_restrict]
This text or <em>HTML</em> is available for members with any active plan.
[/wcm_restrict]
 
This content is availale for everyone again.

How to implement the same in the code? Easily — with the standart WordPress do_shortcode() function.

echo do_shortcode('We begin with the public content. [wcm_restrict]This text or <em>HTML</em> is available for members with any active plan.[/wcm_restrict] This content is availale for everyone.');

The shortcode has some useful parameters as well, scroll down or click here to find out more.

2. wc_memberships_restrict() basic usage

Actually this cool function lays in the base of the [wcm_restrict] shortcode.

wc_memberships_restrict('This content is available for members with <u>any active</u> plan');

The function has some interesting parameters described below.

Providing Content Access for Users with Specific Plans Only (with any status) #

wc_memberships_is_user_member()

This simple conditional function returns true if user is subscribed to a specific plan, and no matter what status his membership has — active or expired or paused etc.

wc_memberships_is_user_member( $user_id = null, $membership_plan )
$user_id
(int) By default — current user.
$membership_plan
(int|string|object) Membership Plan slug, post object or its post ID.

How to find out a plan ID? — read this detailed article. Where to get a plan slug then? — look on the screenshot below.

To find WC Memberships plan slugs, go to WooCommerce > Memberships and then switch to the Membership Plans tab.
You can find WC Memberships plan slugs on the Membership Plans tab if you go to the WooCommerce > Memberships page in /wp-admin/.

Some examples:

if( wc_memberships_is_user_member( 11, 'mypremium' ) ) {
	// here do stuff for user with ID 11 with "mypremium" plan with any status (active, expired, etc)
}
if( wc_memberships_is_user_member( null, 5101 ) ) {
	// here do stuff for current users with the plan with ID 5101 with any status (active, expired, etc)
}
$user_id = 11; // not current user
$plan_id = 5101;
$plan = get_post( $plan_id ); // I get plan object here just to show you how it works
 
if( wc_memberships_is_user_member( $user_id, $plan ) ) {
	// do stuff for a specific user with a specific plan
}

3 Ways of your Custom Content Restriction for Users with Specific Active Plans #

1. [wcm_restrict] with «plans» parameter #

We begin with the public content.
 
[wcm_restrict plans="premium_silver, premium_gold"]
This piece of content is only visible to premium members with premium_silver or premium_gold active plans
[/wcm_restrict]
 
This content is availale for everyone again.

plans parameter accepts plan IDs, plan slugs (multiple comma-separated plans are allowed).

The other useful parameters of [wcm_restrict] shortcode – delayed access or start after trial

[wcm_restrict delay="5 week"]
This piece of content will be available for any active plan users after 5 weeks they've registered.
[/wcm_restrict]

You can also pass to this parameter such time values as 20 days, 3 weeks, 1 month, 2 years.

But it also can accept the exact date parameter. In fact it understands several date formats but my recommendation is the ISO (yyyy-mm-dd), like in the example below:

[wcm_restrict delay="2017-05-25"]
This piece of content will be available for any active plan users at May 25, 2017
[/wcm_restrict]

I think everything should be clear with start_after_trial shortcode parameter:

[wcm_restrict start_after_trial="yes"]
This piece of content will be available to any plan members when their membership moves from "Free Trial" to "Active" status.
[/wcm_restrict]

The only thing that needs proper understanding is using both delay and start_after_trial parameters in the same shortcode:

[wcm_restrict delay="5 days" start_after_trial="yes"]
This piece of the content will be available for all members 5 days after their trial period ends
[/wcm_restrict]

2. wc_memberships_restrict() #

Now let me show all the function parameters. It lays in base of [wcm_restrict] shortcode, so, everything looks very similar.

wc_memberships_restrict( $content, $membership_plans = null, $delay = null, $exclude_trial = false )
$content
(string) Piece of text or HTML code you would like to restrict.
$membership_plans
(int|string|array) Membership plan ID, slug or an array of ID or slugs for multiple plans.
$delay
(string) Time delay in content access after the user membership plan becomes active. Accepts time values like 2 months, 5 days, 1 year or the exact date like 2017-05-02 (yyyy-mm-dd — recommended) or May 2, 2017.
$exclude_trial
(bool) If true — the content is restricted for trial members.

Let’s look at the example with all the parameters in one place:

$content = 'This is the <em>piece of content,</em> we would like to restrict.';
wc_memberships_restrict( $content, array( 5101, 'premium_gold' ), '1 week', true );

Now let me explain: in the above example we have a piece of content, and only non-trial users with the membership plan with id 5101 or with the plan premium_gold can access it after 1 week their membership become active.

If user doesn’t have this membership, function returns nothing. If a user membership is in the trial period (or one week has not passed yet), the function prints the message that the content is the part of user’s membership but not yet — and this message can be customized with the wc_memberships_get_content_delayed_message filter.

3. wc_memberships_is_user_active_member()

This is a very simple conditional function and it is similar to wc_memberships_is_user_member(), the only difference is that it returns true only for active memberships (trial users are also included).

wc_memberships_is_user_active_member( $user_id = null, $plan )
$user_id
(int) By default — current user.
$plan
(int|string|object) Membership Plan slug, post object or its post ID
if( wc_memberships_is_user_member( null, 'premium_gold' ) ) {
	// do stuff for the current user with active "premium_gold" plan (even in trial period)
}

Conditional Checks: Custom Post Types #

wc_memberships_user_can()

This is the only standart WC Memberships function that allows you to check easily if user can view a specific post, page, product or another custom post type element. This function can be used to check if the user can buy a specific product as well.

wc_memberships_user_can( $user_id, $action, $target, $when = '' )
$user_id
(int) User ID is required, you can pass the current user ID by the get_current_user_id() function.
$action
(int|string) Only one of the following values view or purchase (products only).
$target
(array) Currently this parameter supports only a simple array like array( 'post' => id ) — for any custom post types except product or array( 'product' => id ) — for products only (do not forget to replace ‘id’ with the actual value of the post/product ID).
$when
(int|string) UTC timestamp to compare for content access (defaults to now)

And the example:

if( wc_memberships_user_can( get_current_user_id(), 'view' , array( 'post' => 32 ) ) )
	echo 'Yes'; // Yes - the current user can view the post/page/product with ID 32
else
	echo 'No';

current_user_can() and user_can()

wc_memberships_user_can() function is great, but you can do completely the same with already familiar (I hope 😁) functions like current_user_can() and user_can().

Let me show you an example – let’s check if the current user can view a post with a certain ID.

if( current_user_can( 'wc_memberships_view_restricted_post_content', $post_id ) ) {
	// show content
}

But you can also do this check for any user, just pass a user ID as a first function parameter.

if( user_can( $user_id, 'wc_memberships_view_restricted_post_content', $post_id ) ) {
	// show content
}

Restricted Category Access (Works for Tags and Taxonomy Terms too) #

Currently I know only one working way to check if a user can view restricted taxonomy term content or not.

if( current_user_can( 'wc_memberships_view_restricted_taxonomy_term', 'category', $term_id ) ) {
	// show something
}

Do not forget to replace the second parameter category with you custom taxonomy name if you are going to use it for taxonomy terms. You can also use user_can() function to restrict content for a certain user.

Previously I used the function below to check this, but it has stopped working in the latest WooCommerce Memberships version. I just leave it here in case you need it.

/**
@param int $user_id Default: Current User 
@param string $taxonomy Taxonomy name
@param int $term_id
 
@return bool true if user can view the specific taxonomy term, false - otherwise
*/
if( function_exists('wc_memberships') ) {
	function misha_if_user_can_view_term( $user_id = null, $taxonomy, $term_id ) {
 
		if ( ! $user_id ) {
			$user_id = get_current_user_id();
		}
 
		if ( ! $user_id ) {
			return null;
		}
 
		$r = wc_memberships()->get_rules_instance()->get_taxonomy_term_content_restriction_rules( $taxonomy, $term_id );
		return wc_memberships()->get_rules_instance()->user_has_content_access_from_rules( $user_id, $r, $term_id );
	}
}

And this is how to use it:

if( misha_if_user_can_view_term( null, 'category', 30 ) ) {
	// do stuff if current user can view category with ID 30
}

If you have any question or recommendation to this post, I will be glad to have a conversation with you in comments below.

Misha Rudrastyh
About the author Misha Rudrastyh

Passionate about WordPress and snowboarding, creating websites for over 10 years! Let's work together — just contact me.

If you are a developer too, subscribe to my facebook page.

Comments 23

  • Thanks for the very helpful tutorial.

    Is it possible to add multiple plans in a statement like this?

    if( wc_memberships_is_user_member( null, 'premium_gold' ) )

    I’ve tried adding multiple plans but can’t get it to work.
    Thanks

    • Hi Jimmy,

      I think you can make it something like this:

      if( wc_memberships_is_user_member( null, 'premium_gold' ) 
      || wc_memberships_is_user_member( null, 'premium_silver' ) )
  • Thank you, thank you, thank you, Misha! This is SO helpful.

  • super helpful! thank you!

  • do you know why this code doesn’t work

    if ( $product->id !== 411 || $product->id !== 412 ) {
    }
    • Well if your comment was just “Do you know why my code doesn’t work?” it certainly would be enough info for me to help you 😁 😁

  • Misha,

    Great post here! Any suggestions of how to use this membership ID restriction function to allow access to Buddypress user tabs or wildcard URL slugs in general? I am building a membership site designed to allow access to various parts of a buddypress platform based upon WC membership level.

  • I am using the restrict shortcode for members that are logged in…

    [wcm_restrict delay=”2 weeks”]
    This content will be available to members of any plan once they’ve been a member for two weeks.
    [/wcm_restrict]

    It works fine and exactly as I need, but now the issue I’m having is that there is this message right in the middle of many content pages (“This content is part of your membership, but not yet! You will gain access on…”). I’ve been able to hide this message with CSS but now there’s a real big gap right in the middle of the pages and looks real ugly. I’ve been searching Google for code where I can remove this completely until it’s time to reveal the restricted content. So far I can’t find anything on this. I can’t imagine that I’m the only one that’s ever needed this. Any help would be greatly appreciated.

    • Hey Ken,

      wc_memberships_get_content_delayed_message filter hook should help you.

      Example if you do not want to display anything:

      add_filter( 'wc_memberships_get_content_delayed_message', 'your_custom_msg', 9999 );
       
      function your_custom_msg( $message ){
      	return '';
      }

      Please let me know if it works for you.

      • Misha,

        It worked perfectly!

        Thank you so much.

        This is exaclty what I was looking for.

        Have A Blessed Day :)

  • Jonathan Sharp

    Hi Misha. Great post thanks.
    I want to show a coming soon button for 7 days then show a link to the content. I can successfully use the restrict, plan and delay shortcodes to show the button and content after 7 days but am hoping there is a way to show a coming soon message or button until then and then make it disappear when the 7 days comes around.

    • Hi Jonathan,

      Not sure if I understand you correctly. Dod you try wc_memberships_get_content_delayed_message fiter hook?

      • Jonathan Sharp

        Hi Misha – Thanks for the reply. The site is essentially a group of online courses with 7 weeks of content.

        I have created an account page where only those course that have been purchased show up using the [wcm_restrict plans=”membership”] and the [wcm_nonmember] codes.

        I also have course pages where the courses are released on a weekly basis. Each week uses a variation of [wcm_restrict plans=β€œmembership” delay=”1 week”] to only show the content as it becomes available.

        However, with the code above the content is invisible until the 1 week is up. I want to put a “coming soon” message until the week and then make that disappear and the content come up.

      • MishaAuthor

        Maybe I just didn’t understand you correctly, sorry, but for me it seems like the code below should help you:

        add_filter( 'wc_memberships_get_content_delayed_message', 'my_custom_msg', 9999 );
         
        function my_custom_msg( $message ) {
        	return 'Coming soon...';
        }
  • Hi Misha

    Great tutorial.

    Conditional Checks: Taxonomy Terms

    user_has_content_access_from_rules is no longer available

  • Hi Misha, Nice article thanks for the tips

    Do you know if its possible To Hook in and add content after the restriction message box?

    We need a more elaborate restriction message / landing but still want to use the lead in text if done automatically.

    wc_memberships_the_restricted_content would we be able to use that to add html under the message box you think?

    • Hi Tarik,

      Sure, try this hook wc_memberships_content_restricted_message. Example:

      add_filter( 'wc_memberships_content_restricted_message', function( $message, $post_id, $products ){
       
      	return $message . 'You custom text / HTML here';
       
      }, 10, 3 );
      • Hi Misha,

        Thanks for your reply!

        I understand this will replace the message in the box. Can we replace the box itself or put something after the div that contains the message ?

        Thanks

        T

      • In my example the box won’t be replaced, just a custom message will be added after it.

Comments are closed.
If you need my personal help, please contact me. Contact me