Woman On A Laptop Planning Strategy

Repeating a fixed date membership with WooCommerce memberships

CommerceCategory
11 min read
Beka Rice

The new year partly inspired this Memberships post, as a year cycle ends, and it’s likely that many of you Memberships users might have set up membership plans that are a year long. But how about plans that are set to start exactly on the 1st of January of any given year?

Since fixed dates memberships were introduced in version 1.7.0 there is the possibility in WooCommerce Memberships to create membership plans that will grant access to members starting and ending on fixed dates, unlike regular membership plans, which grant access for an amount of time relative to any date.

Let’s see how you can make use of this feature to program yearly fixed plans for your customers to join.

More About Fixed-Date Memberships

With fixed memberships, if a member joins a fixed-date plan before the start date is due, they included as members, but don’t get any access yet (the plan is “delayed”). If they join later, their membership will still expire on the pre-set end date with no possibility of renewing.

This is useful if you want to offer special memberships available to join for a limited time only; for example, when tying membership status to some event that happens on a specific date or within a specific time frame; or some kind of sale campaign; or to grant access to special content that is part of more expensive, but lengthier plans, for a limited time.

We were soon happy to find that Memberships users were quick to adopt this feature in their WooCommerce sites, to broaden their portfolio of products and the way they can sell and market their business. We also received interesting feedback on it: among the most frequent asked questions there could be summarized up as “How do I make a fixed membership automatically re-adjust the access dates for the next year/month/week?”.

It seems the most common use case for this type of membership plan is to create a year-long plan starting on the first day of January and ending on the last day of December. Some users wanted to adjust the year of the start and end dates to match the current year, every year, so that new members joining, would get access for the new year.

For example, I have a plan for the year of 2017, starting 1st of January 2017, ending 31st of December 2017. If a customer joins in February or March they will still get access for the 2017 plan, and their end date will be still 31st of December 2017. However, if it’s November or December 2017 already, it’s unlikely that customers who aren’t members would want to join for just 2 months of membership at the same cost as if the joined at the beginning of the year. If they purchase a product that grants access, they might want to have access to the 2018 membership plan.

This kind of usage is definitely supported by Memberships already, as we can make updates to a fixed-date plan that will work for members joining at the end of the term, along with members who want to renew for a new term.

How to Update a Fixed Date Membership

So far we advised our users to address this scenario in 2 possible ways, depending on their setup:

  1. Create different plans with fixed dates for each year and different products that grant access to each of these plans; perhaps delete older granting-access products as years pass.
    WooCommerce Memberships: Fixed Date Plans
    This set up is useful if these plans aren’t connected to each other in any way.
  2. Only use one plan with fixed dates and manually update its details in the WordPress admin screen, bumping the start and end dates year by year, before the actual end date is due, without editing or deleting products that grant access.
    WooCommerce Memberships: Update fixed date plan
    This is most useful for sites who want to allow previous members to renew (continuing with or maintaining a content-dripping schedule), or who want the “new year” access to be indistinguishable from previous access.

Generally we recommend the latter method, which seems to fit most use cases — for most sites, creating different products could be confusing or it’s just not possible as the access-granting product needs to remain the same.

The great news here is that updating a plan does not automatically update all existing memberships. This means that, if you had a member who purchased the annual plan, they won’t automatically get access extended for a new year.

Instead, to access the membership for the “new dates”, the member would have to re-purchase or renew to maintain access (which we’ve found to be the desired behavior in ~90% of cases).

When Should You Update Plans?

So the question we’ve gotten most often is this: when should I update my fixed-date plan?

This depends on the needs of your site, as well as the length of the membership itself. We recommend considering a few things:

  • If you want to send “expiring soon” emails to members, you likely want to update your membership before this is sent. For example, if you send the “expiring soon” email 14 days before the plan ends, definitely update your plan prior to this email being sent. This way, existing members will be asked to renew, and they can do something about it.
  • If you’re concerned with pricing and when you should update this access, we’ve seen a lot of sites achieve success by doing the following:
    • Calculating the half-way point for your membership length; set the purchasing product “on sale” at this point for members who purchase “late” so they’re getting a discount for signing up part of the way through. WooCommerce lets you schedule start and end dates for sales to achieve this.
    • Once the membership is ~75% to 85% of the way through, ensure your sale is over, and set the product back to full price. Update the membership dates to use the next cycle, which is now sold at full price again.
    • This way, once the cycle is far into the membership period, you can bump the dates. Existing members will retain their access and original end date, while new members will have a “delayed” membership until your cycle re-starts.
  • Be aware of the way you name your plan and the content of your membership emails to reflect what renewals should look like for your existing members.

Updating a fixed date is a manual process, but it is one you only have to take once per “cycle” for your membership. However, you could automate it a bit if you’re code-savvy or work with a developer for your site.

Automating Recurring Plan Changes

This portion of the guide requires intermediate PHP and WordPress development skills to implement on your site.

There’s also a third way forward here: automatically update the plan dates before the current membership access period is due to end, to give a chance to new customers to become members from the updated start date and get access to the new membership cycle. This approach works best with fixed year or month-long memberships but can be applied to any set of fixed dates.

This third approach requires adding some custom code to your Memberships installation, so it’s meant for more skilled users who are not afraid to run some custom script or to inspire developers as a starting point for more advanced customization in their clients sites. The idea is that you could either 1) set up a cron job in WordPress or 2) hook to an existing event to instruct Memberships to save new dates to a fixed plan.

In the first case (set up your own cron job), you could use the WordPress function wp_schedule_single_event() to schedule an event, say, on November 1st of the current year, and pass the ID of a Membership Plan that has fixed dates.

In the callback this function expects, you get the Membership Plan using wc_memberships_get_membership_plan() from the passed ID, then proceed to update the plan’s dates. You can write some code to dynamically create these single events each year.

In the latter case, you could hook to an event that is already scheduled and triggered by Memberships itself. An ideal candidate could be the one that is responsible to send memberships expiring soon emails. These would be sent also for fixed date plans and to make use of the corresponding hook, they need to have been enabled when at least one member joined the fixed plan.

So, if you have set these to be scheduled one month before expiration date, and this occurs December 31st, you could bump the dates exactly one month before, right when the existing members are receiving an email about their membership ending soon, where you could also prompt them for renewal (something that would not normally be possible with fixed dates memberships). Customers who aren’t currently members would have the chance to get access for the upcoming year, not the current one.

In either case (set your own event or use an existing one), you could look at the code below for inspiration — there are a bit of assumptions here and you shouldn’t copy the following code as it is, but adapt it to your specific use case instead. If you plan to schedule your own event, you can still use the callback as outlined below for 'wc_memberships_user_membership_expiring_soon', except you could pass a Membership Plan ID straight.

// We can conveniently trigger our update script by the time membership expiring soon
// emails are sent, right before emails are sent (e.g. priority 5, must be lower than 10).
add_action( 'wc_memberships_user_membership_expiring_soon', 'sv_update_fixed_dates_membership_plan', 5, 1 );

/**
 * Update fixed membership plan dates.
 *
 * Note: this is for example purposes, and follows the assumption that you only have
 * 1 fixed plan, it has year-long dates and you want to bump those exactly by one year.
 *
 * You might want to do necessary adjustments and introduce more variables or
 * checks according to your specific setup.
 *
 * @param array $args Array of arguments set by the wc_memberships_user_membership_expiring_soon event.
 */
 function sv_update_fixed_dates_membership_plan( $args ) {

   $user_membership_id = isset( $args['user_membership_id'] ) ? $args['user_membership_id'] : $args;
   // Bail out if:
   // - user membership ID is not an integer.
   // - the current action isn't for the membership expiring soon event.
   if ( ! is_numeric( $user_membership_id ) || 'wc_memberships_user_membership_expiring_soon' !== current_filter() ) {
      return;
   }

   $user_membership = wc_memberships_get_user_membership( $user_membership_id );

   // Proceed if the user membership exists.
   if ( $user_membership ) {

      $membership_plan = $user_membership->get_plan();

      // Check if the plan has fixed length and we haven't updated this before:
      if ( $membership_plan && $membership_plan->is_access_length_type( 'fixed' ) && date( 'Y' ) !== get_post_meta( $membership_plan->get_id(), '_dates_last_bumped', true ) ) {

         // Get the current fixed dates, as timestamps:
         $current_plan_start_date = $membership_plan->get_access_start_date( 'timestamp' );
         $current_plan_end_date   = $membership_plan->get_access_end_date( 'timestamp' );

         // Bump dates one year in the future, using strtotime magic:
         $renewed_plan_start_date = strtotime( '+1 year', $current_plan_start_date );
         $renewed_plan_end_date   = strtotime( '+1 year', $current_plan_end_date );

         // Set the new dates (they need to be in mysql format):
         $membership_plan->set_access_end_date( date( 'Y-m-d H:i:s', $renewed_plan_end_date ) );
         $membership_plan->set_access_start_date( date( 'Y-m-d H:i:s', $renewed_plan_start_date ) );

         // Set a flag so we don't update again this plan for this year:
         update_post_meta( $membership_plan->get_id(), '_dates_last_bumped', date( 'Y' ) );
      }
   }
}

*If you use strtotime() to compute relative dates such as +1 year, mind that this isn’t as accurate as using DateTime – but you get the idea you can do any sort of calculation to renew the plan’s fixed dates to anything you want!

Final notes

An important note about dates: regardless how you achieve this, if you edit the plan dates, remember that no user membership date will be updated. They are independent objects, so you won’t risk updating existing members if you change the configuration of any plan. The only plan changes that affect existing members are the ones related to access rules.

Don’t forget membership emails: if you are using membership emails to automatically send emails to plan members about their membership status, you might want to check the dates when membership expiration emails are supposed to be sent, to make sure these play well with your strategy with fixed dates memberships.