Membership Manager lets users subscribe to paid membership to your organization. Membership Manager supports manual payment by any means, and automatic payment via PayPal Manager.
Members can view their account balance and pay their membership directly from your website. They will receive automatic emails as their bill becomes due. Members will be automatically disabled if they fail to pay within a configurable grace period, and the site admin will be notified by email.
Admins can manually edit member information and send balance statements. Admins receive automatic emails when a member is disabled by the system, in addition to the automatic emails dispensed by PayPal Manager.
Membership Manager is complex, and configuring it is a multi-step process.
Due to the breadth of functionality available in Membership Manager, and the importance of handling money correctly, we have provided a set of recipes that document standard procedures to handle proper money handling, complaints from members, automatic notifications, and other issues.
The user profile form templates need to be integrated with Membership Manager. The form needs to display descriptors and payment options, and it needs to be submitted to Membership Manager scripts, which understand how to handle the additional fields.
In the templates profile_form-admin.template
and profile_form-user.template
, usermanager
needs to be replaced with membershipmanager
. For instance:
# Replace
<FORM NAME=register-edit_profile ACTION=/admin/usermanager/admin_register-edit_profile_action.cgi METHOD=POST>
# With
<FORM NAME=register-edit_profile ACTION=/admin/membershipmanager/admin_register-edit_profile_action.cgi METHOD=POST>
In the template profile_form.template
, add a Membership Manager tag to automatically display membership form fields. The tag adds its own layout to the existing table, so it should go inside the <table>
tag, but outside any table rows.
# Prints descriptor and payment fields :::MEMBERSHIP:PAYMENTFIELD:1::: # Prints just descriptor fields :::MEMBERSHIP:PAYMENTFIELD:0::: # Same as above :::MEMBERSHIP:::
When finished, the bottom of profile_form.template
should look similar to this:
:::MEMBERSHIP:PAYMENTFIELD:1::: </TABLE>
For more flexible configurations, each field can be placed independently with a ::MEMBERSHIP_DESCRIPTOR:<descriptor>:: tag, which will resolve to the descriptors described in the local library (See below for more details on descriptors) as well as a few special descriptors.
Example: If there is a descriptor with the machine name "website" (as example below does) then the tag ::MEMBERSHIP_DESCRIPTOR:website::
will display that form field.
The special descriptors are payment and admin_fields. ::MEMBERSHIP_DESCRIPTOR:payment::
displays the payment options and ::MEMBERSHIP_DESCRIPTOR:admin_fields::
is where the admin only functions will appear if and admin is looking at the form.
Member descriptors are configured through a local library function, membership_manager_get_descriptors
. It returns an array of hashes, where the specific fields determine the behavior of the descriptor manager-wide.
sub membership_manager_get_descriptors { my ($FORM, %params) = @_; my (@descriptors); $descriptors[0] = {machine_name=>'website', user_name=>'Website', mandatory=>0, data_type=>'text' }; return @descriptors; }
0
if the descriptor is optional, or 1
if it is mandatory. Mandatory text and textareas cannot be left blank. Mandatory checkboxes cannot be left unchecked.'text'
(a single line of text),'textarea'
(multi-line text),'checkbox'
,'email'
,'date'
,'select'
(drop-down menu)
'select'
-type drop-down menus. Elements are hashes of a single machine_name => user_name
pair.'e.g. Mr. or Ms.'
).1
on a successful match, and takes as parameters member
, and term
. For date fields, this function should accept term_from
and term_to
.Membership Manager has an optional default membership fee. Membership fees are also configured in member types This is configurable in Map Manager.
Member types are configured much like member descriptors. They are set in a function called membershipmanager_member_types
in the site's local library. This function defines the levels of memberships and the fees for each level. An option of "admin_only" means that users cannot sign up for that membership level, and can only be configured by an admin user on the site.
Example:
sub membershipmanager_member_types { my ($FORM, %params) = @_; return ({machine_name=>'lvl_1', display_name=>'Basic Member', fee=>$FORM->{'map_LOCAL_MEMBERSHIPMANAGER_FEE'} }, {machine_name=>'lvl_2', display_name=>'Advanced Member', fee=>30 }, {machine_name=>'lvl_3', display_name=>'Complementary Member', admin_only=>1, fee=>0 } ); }
Membership Manager will send reminders to members who are approaching the end of their membership period to remind when they should pay for the next period, when their membership has expired and when they are past due on payments. The default configuration is to warn 30 and 60 days before the member's expiration day, on the day of their expiration, and then 30 and 60 days after. On the last day, the user is marked as not a member and their balance is zeroed out.
To configure dates other than default (which are geared towards an annual membership), add a function similar to the membership descriptors and member types functions called membershipmanager_renewal_notices
.
sub membershipmanager_renewal_notices { my ($FORM, %params) = @_; my ($query, $rv, $sth, $rowhash, @renewal_notices); $query = "SELECT DATE_FORMAT(NOW(), '%M %e, %Y') AS date_now, DATE_FORMAT(DATE_ADD(NOW(), INTERVAL 7 DAY), '%M %e, %Y') AS date_7, DATE_FORMAT(DATE_ADD(NOW(), INTERVAL -3 DAY), '%M %e, %Y') AS date_3_minus, DATE_FORMAT(DATE_ADD(NOW(), INTERVAL -7 DAY), '%M %e, %Y') AS date_7_minus"; ($rv, $sth) = &Library_global::do_standard_query($query, $Library_global::dbh); $rowhash = &Library_global::get_rowhash($sth); &Library_global::finish($sth); @renewal_notices = ({interval=>7, title=>'First Notice: 7 Days Before Expiration', custom_sentence=>"You have 14 days until your membership will expire on $rowhash->{'date_7'}!", charge_membership_fee=>1, individual_email=>1 }, {interval=>0, title=>'Second Notice: On Membership Expiration Day', custom_sentence=>"Your membership will expire <b><font color=red>TODAY</font></b> on $rowhash->{'date_now'}!", individual_email=>1 }, {interval=>-7, title=>'Third Notice: 14 Days After Expiration Day', credit_back_membership_fee=>1, disable_membership=>1, expiration_note_to_admin=>1 }, {interval=>-3, title=>'New Member Notice', custom_sentence=>"We received your membership registration on $rowhash->{'date_3_minus'}!", individual_email=>1, note_to_admin=>1, new_user_notice=>1 } ); }
To search for members by specific fields, click "Search Members" on the admin index page. For each field you want to search, check the "Search By" checkbox, and enter the value you would like to find. Custom search links at the top of the page can be used for preset searches, or more complex reporting logic.
Search results can be exported to CSV by clicking the "Export to CSV" button at the top of any search results page. Additionally, one can export all information for all users by clicking "Export all Member Data".
The search page can be customized in several ways.
LOCAL_MEMBERSHIPMANAGER_SEARCH_FIELDS
map to a comma-separated list of the descriptors you would like to be able to search by.LOCAL_MEMBERSHIPMANAGER_SEARCH_DISPLAY_COLUMNS
map to a comma-separated list of descriptors you would like shown in the search results. The search results always display a link to each user's profile, plus their username and full name.membership_manager_custom_searches
subroutine in your local library to return a hash of {user_name, data_type, search_func}
to search routines. A search_func
function pointer should return a hashref with two keys: {columns => array of column names, rows => 2D array of matching values accessed by $array->[$row]->[$column]}
.Membership Manager supports more complex search queries, in what is formally known as "disjunctive normal form". You can search for any query of the form (A and B and C) or (D and E) ...
. The terms (A and B and C)
and (D and E)
would be individual "clauses" of the full search query. Advanced searches are iterative. As you build up a full search, intermediate results are still shown.
To begin an advanced search, select "Advanced Search" from the member search page. From top to bottom, the elements of the page are: current search parameters, controls to add a search parameter, and current search results. To add a search parameter, select the column to search for, then select either "AND" or "OR". The "AND" button will add the search term to the current clause, and the "OR" button will start a new clause. In this way, you can build up a complex search query like (site member AND in Virginia AND request local newsletter) OR (site member AND request all newsletters)
from left to right. To see the results of your current search parameters at any time, select the "Search" button.
The template tag :::MEMBERSHIP_BALANCE:::
can be used to let members quickly view and pay off their balance. This tag is ideal for use in a javascript pop-up interstitial.
The map LOCAL_MEMBERSHIPMANGER_POST_EDIT_TEMPLATE
can be used to change the template seen by members after they sign up or edit their profile.
Membership Manager can take control of User Manager's Mailman integration, and add features above and beyond what would otherwise be possible. To enable the most basic level of functionality, set the LOCAL_MEMBERSHIPMANAGER_MAILMAN_LISTS
map to 1
. When this map is set, User Manager will no longer automatically subscribe new non-member users.
For more sophisticated and granular control, Membership Manager also provides per-member-type mailing lists that can be configured independently of the LOCAL_MEMBERSHIPMANAGER_MAILMAN_LISTS
map. In your local library, you can add a field mailing_lists=>[qw(list1 list2 ...)]
to a member type hash to specify a set of mailing lists. All members of that type will have those optional lists available to subscribe to. You may also add a field auto_subscribe_mailing_lists=>[qw(list1 list2 ...)]
. Members will automatically be subscribed to these lists when they become that type of member.
All members are users, but not all users are members. When a visitor signs up to become a member, they are given a user account at the same time. As such, almost all membership management administration takes place from the User Manager admin pages.
LunpaCMS has a relatively simple way of dealing with coupon codes. It will accept coupon codes that are then run as functions in the local library. i.e. If you want to have a user enter a BUY1GET1FREE coupon code, add a function called coupon_buy1get1free to the local library. This way, coupons are easily enabled and disabled by commenting out functions in the sites local library.
Use: :::COUPON_CODE:ARGS: input_size=15 :::
will place the coupon form with the action set to the correct submission script
Tag Options:
Example Coupon Function: This function checks some requirements and, if they are met, it credits back one of the items. Note: many of these kinds of situations should be dealt with by brute force.
sub coupon_buy1get1free { # CHECK FOR PARAMETERS OF if ( *dont_meet_requirements* ) { return (0, $error); } # CHECK IF IT HAS BEEN USED BEFORE if ( *used_before* ) { return (0, $error); } # IF HERE, ALL IS GOOD AND WE CAN CREDIT THEM THE MONEY &Library_membershipmanager::record_user_membership_transaction($FORM, transaction_memo=>$memo, transaction_amount=>-30, transaction_item_number=>$trans_num, updated_by=>'1', user_id=>$user_id); return 1; }
Membership Manager supports PayPal Subscriptions as an alternative to large up-front payments for many membership periods. To display a form to allow members to make recurring payments, use the tag :::RECURRING_PAYMENT_FORM:::
.
PayPal does not allow for changing the payment date on a subscription. This means it is possible for a member to set a subscription that always pays late. In this event, an admin will be notified by email. The recommended way of resolving this issue is to pay for an additional single period of membership. This will shift your subscription from being late for this period, to being early for the next period.
Membership Manager uses a double entry book keeping system which is a very easy system. It keeps track of charges for everything in one location, with positive numbers indicating charges to the user and negative numbers indicating payments from the user. Thus, a user at a balance of $0 will have paid off anything they have agreed to paid for, whether it be registering for an event, membership dues, or any other miscellanea payments. A positive balance indicates that the user still owes money and a negative balance indicates a credit to the account.
You can access a member report with much of the information pertaining to each user's membership status by going to the user manager admin page and clicking on "User/Member Reports." The report lists how many users, members, and members who are current on their membership payments there currently are.
Membership Manager includes a monthly transaction report. The report is a summary of all transactions processed in the past month, categorized and arranged for verification against another accounting system. The report separates credits and debits, and categorizes event registrations, membership payments, and donations. At the start of each month, the report will be emailed to your website's PayPal account email address.
Every day, when members are checked for renewal payment status, an email is sent summarizing members who have let their membership lapse, and members who cannot be contacted by email. If no members have lapsed, and all members were able to be emailed, this report will not be sent. This email is sent to your website's PayPal account email address.
Using Membership Manager to track membership dues allows you to have a rolling membership fee. That is, everyone receives an entire period starting on the day they pay instead of all members being charged on a single day. This avoids problems such as having, for instance, a yearly membership that dues are due on the 1st of January and one member paying on January 1st and another paying in December. Though the amount is the same, the member paying in December only receives membership for a month even though they pay the same amount as someone paying in January.
The way Membership Manager deals with this is by keeping track of 2 dates: The Membership Renewal Date and the Last Membership Charge date. The Membership Renewal Date is the date on which the member will be billed again, and the Last Membership Charge date was the date of the last charge. Once the Membership Renewal Date for any single member matches the current date, they are charged and their Last Membership Charge date is set to the current date. Therefore, if both of these dates are the same, the member is not currently paid up for their membership. Only when they pay does the Membership Renewal Date get pushed ahead for the amount of time they pay for and the cycle starts over again.
Here is a list of every instance in where an email is sent by the membership management system (the combined features of PayPal Manager, Membership Manager, and Registration Manager):
Adding a member is as simple as going to admin usermanager page, clicking on "Create a User," and entering any necessary information. To make them a member, select the type of member they are supposed to be in the Admin Only Fields, and set the dates accordingly. This will engage the automatic billing code and email reminders when they are applicable to the user. For more information about managing a users transactions, see the "Managing a User's Transaction" section.
To view and manage a user's transactions, go to the admin user manager page, find the user you want to edit and click "Edit" under actions. On the page where you edit their user information, there should be a link that says "View Transaction History" that will take you to their Transaction History. Once there, there are several options for managing the transactions:
If the membership for your website/organization is $20 a year. If a member sends a check for $25 (assuming the user has already been charged the $20 for membership, with $5 earmarked for donation), the procedure would be to enter:
Transaction Memo: User membership payment plus donation to organization.
Transaction Type: Credit
Membership Type: Mark user as appropriate membership level
Extend Current Membership Renewal Date by: 1 Year
Debit Account for Donation Received: $5
If you do not debit the account for the donation, the user's overall balance would be -$5.00.
The Membership Manager, along with Paypal Manager, can deal with delayed transactions, mostly in the form of PayPal echecks. How this works is that PayPal will send two messages to the system, one that informs it that it is processing and another to let it know that it has been completed. This can take a few days to a week or more. There is no special action needed on the part of the admin, other than verifying that the payment came through. The user's balance will not be altered until the second PayPal message is received, so the system will take the appropriate action should the payments not come through on time, whether that is to not mark the user as a member or to disable their membership.
Admins can manually add multiple payment periods to a user, should they so desire. The way to enter this would be to add the amount of periods the user wishes to pay multiplied by the price of a single period as a positive transaction in the users transaction history. The user can then be sent a notification email, or the admin can manually enter the payment if they have already payed by entering the payment as a negative value.
Membership Manager has the ability to add a discount to a user's membership dues. To turn on the ability set the map LOCAL_MEMBERSHIPMANAGER_ALLOW_MEMBER_DISCOUNTS to 1. The user can be given a discount up to and including the total fee for their membership in $5 increments. If a user is pending payment, a transaction will appear in their transaction history deducting the amount set for them to discount. Users with completely deducted dues will not receive notifications and will remain members until manually changed.
How to use: If the map is set, a drop down box will show up in the user's profile in the admin section. Select a discount for the user and save their account information.
The system will not send frivolous emails to admins. All warning emails are important and should be addressed as soon as possible. Warning emails should never be ignored. The reasons for a warning email to be sent to an admin include the following:
We do not provide any tools with assisting you with auditing and all payments recorded on the system should be checked against PayPal and other forms of payments received for any discrepancies.
Once a month an email will be sent with a transaction report that contains totals from all payments. This can be used to double check against your own records as an additional part of your own audits.
Membership Applications can be split into two pages, user profile and then membership applications if desired.
Setting up multiple application pages:
<input type='hidden' name='additional_member_template' value=1 >
:::MEMBERSHIP_DESCRIPTOR:::
tags should be placed<input type='hidden' name='member_form_only' value=1>
<input type=hidden name=edit_id value=:::edit_id:::>
:::MEMBERSHIP:::
tag in both the user and admin profile formsWhen a user is expired, there will be a link on the admin User/Membership index page that will resubscribe the user for a set number of days and allow them to easily pay for their membership. Note that this will reinstate the user to their full membership rights for the duration of the grace period, including adding them back to any mailing lists. If the user is within one period after their last membership due date, it will keep that same date and consider the next payment as a continuance of their regular membership, otherwise it will use the current date and will be as if they resubscribed today. For instance, if your membership period is one month and the user expired 5 days ago, if you use this feature it will use that same expiration date for the next month when they resubscribe, but if it is 35 days after the last expiration it will use the date you resubscribe them.
To set the number of days to allow this grace period, add or edit the map LOCAL_MEMBERSHIPMANAGER_RESUBSCRIBE_GRACE_PERIOD to the desired amount of days. The default for this map is 14 days.
Sometimes PayPal transactions are not automatically applied to a user for various reasons. To apply those transactions to proper users, refer Transactions Requiring Attention in LunpaCMS PayPal Manager documentation.
Copyright © 2025 Peregrine Computer Consultants Corp. All rights reserved.
About Lunpa, our mascot. Her mother was a hamster and her father was an ill-tempered Chilean M00se. Oddly, neither smelt of elderberries. The artist is Jennifer Lomax. |
![]() ![]() |
Add Your Comment