Memberships are not all the same. Some memberships last a lifetime, others last a year, or a month. Some memberships are for an individual, others for a couple, others for an entire family.
Some memberships are for a particular time period -- the 2017 season, the 2017/18 school year, Summer -- others are for a particular length of time starting when you purchase it.
And then there's the behind the scenes stuff -- the "CRM" (Customer Relationship Management) systems of reminders to renew, lists of memberships up for renewal, grace periods between when a membership technically expires and the hard cut-off date, and renewal policies -- does it start on the day you pay for the renewal, or the day your previous membership expired?
What if a member wants to upgrade or downgrade their membership in the middle of their membership term? How do you account for a cost difference between membership levels? What if a student starts part way into a season, do they get a pro-rated price? What if one parent signs a child up for one session, and a different parent registers them for a later session?
In short, membership programs are complicated things. Every membership organization has its own business policies, its own rules, its own benefits.
These are a few of the variations we've run across so far, when implementing membership plans for a client.
Memberships in Drupal 8
Drupal has long been a great platform for a membership site, largely because it is so flexible. With Drupal, memberships can be easily configured to create roles, add users to groups, provide special pricing in a commerce site, grant access to content or the ability to create content, or whatever. Figure out your membership structure and the rest is easy.
However, until Drupal 8, creating memberships with the ability to provide the variations outlined above pretty much always involved a fair amount of custom work. The relatively new Membership Entity module, combined with Membership Entity Commerce goes a long ways towards making a flexible membership system, though there are still gaps, such as offering memberships that expire on a particular date.
We recently launched our first membership site in Drupal 8. We took our experience from nearly a dozen different membership sites over the years, with the full range of variations, and built a brand new membership term and role system with these variations in mind. We are working with the new maintainer of the Membership module to get is is all going to get published on Drupal.org, but for the time being, we've posted our code on Github.
Today this system is built around 1-year membership terms, with a 60-day renewal grace period -- during that grace period, the member still has full access, but if they renew, the renewal starts on the expiration date of the previous term. This seems to be a very common pattern among associations.
The other things that work swimmingly well are email reminders that get sent as the membership term expires. Our client wanted a sequence of 4 different messages that get sent 4 weeks before the expiration date, 7 days before the expiration, 1 week after the expiration date, and a "last chance" message 1 week before the end of the grace period. We built a new Scheduled Message module to handle this, basing the architecture on the algorithm recently added to an experimental Webform submodule. The cool thing about the way we implemented this, is that these messages get suppressed if the member renews. And we can send a "thank you for renewing" message as this is confirmed.
The membership module we fleshed out follows a similar architecture as the Drupal 7 membership_entity module. Memberships are the main entity, and can be active or expired. Memberships may be attached to multiple user accounts, and roles can be granted or revoked based on the status of a membership.
The "active" period of a membership is a separate entity, the "membership term". Each membership can have one active term, but any number of other terms in other states -- expired, expiring, renewed, pending, etc.
Many associations have a grace period -- a period of time where membership benefits are still active, but the term is effectively expired. And so this functionality is baked into the new membership_term module, with a corresponding "expiring" state.
The bulk of the work we did was all around managing what happens when a membership term expires, and gets renewed. For the first site, we set up rules that specify:
- When a member renews a membership_term that is "active" or "expiring", the effective dates of the new term are calculated from the expiration date of the old term. For example, if a term expires on July 20, 2017, any renewal that is done before that date or up until September 19 extends the valid membership to July 20, 2018.
- When a new membership_term is added, the old one is set to the "renewed" state, suppressing all future email reminders associated with that term.
- When a member renews a membership_term that is expired, the new membership term starts on the date of purchase. (This assumes the member renews after the grace period, and has lost their membership privileges.)
- An administrator can edit the active dates, and/or the revoke date of any membership_term, and the scheduled message send dates will adjust accordingly.
Module development in Drupal 8
This was our first foray into building a complex module for Drupal 8, and I found it to be a great learning experience. It exposed us to a large part of the Drupal API, including:
- The plugin system - Creating plugins, plugin types
- Dependency Injection, specifying interfaces rather than objects to facilitate tests with mock objects
- The Event system
- Creating Services and using the container
- The state_machine module -- we still need to port to the newer "workflow" module that has been added to core
- The Queue API
Next up, hooking up self-registration and e-commerce.
If your organization needs a custom membership solution, let us know! We'd love to help...
Thanks for the comment! This sounds much more like a CRM question than a Membership question... What you're asking for sounds like Relation module. I've used that a little, but never really warmed to it. It looks like it's still in dev for D8.
The point of Relation module is exactly what you're asking for -- being able to specify a related item, with metadata about the relation itself. The way Drupal 7 and 8 are organized, everything is an entity, so the main thing to do to make this work is promote the relationship from a simple entityreference field to a full-fledged entity, and add fields to that relationship entity. That's what Relation does... although I've never found an effective UI using that module.
You can essentially do the same thing with Paragraphs, or Entity Construction Kit (ECK) with inline entity form (IEF) -- I think the IEF "Complex wdiget" is by far the best UI for this kind of relationship.
IEF with a working Relation module might be just the thing...
Hi. Am I understanding correctly that you are using th membership module, and that your mention of the membership entity and membership entity commerce modules was in passing only and you are not using them? If so, what do you foresee as a connection between the membership module and being able to offer digital content to the members?
Yes, we are using a D8 module called "membership" that is currently up on github, awaiting attention by the maintainer to get merged and posted on Drupal.org. We made a lot of additions to this module to make it architecturally similar to the D7 membership_entity module. Membership Entity Commerce is forthcoming -- it sounds like our main client is nearly ready to move forward with adding commerce...
We tried to install the dev version but the module does not seem to work properly. Is the module actually running on a Drupal 8 site?
Oh yeah, this is my area of interest. I've built a lot of member management systems over the years; in Drupal and prior to Drupal.
Currently I use Drupal/CiviCRM which centralizes member, events, groups, commerce, accounting, communications and the all important reporting. There are are other activities like campaigns and pledges in CiviCRM but I don't find the need for them at the moment.
One area that is really important is related contacts. So you have individual contacts and organization contacts. The individual is related to the organization in an employee/employer relationship. Have you looked at this from a Drupal centric point of view.
Great work. I'll be looking at this in more detail. If I could solve all membership needs within D8, I'd be a happy camper for sure.