By default, Paid Memberships Pro grants every new member a full membership term starting on their checkout date. That works well for memberships that begin whenever a member is ready, but it does not fit sites that sell access tied to a fixed external cycle, such as a school semester, a sports season, or a calendar quarter.
This code recipe lets members tell you at checkout how far into the current term they already are, then automatically shortens their expiration date to match the time remaining in that term. A member who joins three months into a ten-month season is given seven months of access, not a full term.
Do You Need This Recipe?
This recipe is useful if any of the following apply to your site:
- You sell membership access tied to a fixed term that everyone shares, such as a school year, a season, or a calendar quarter.
- You want every member’s access to end on the same date, regardless of when they joined.
- You want to give members a way to indicate where they are in the cycle at checkout, rather than charging the same price for less time without acknowledgement.
If your memberships always run for a full term from the checkout date, or you handle prorating with a discount code rather than a shorter expiration, this recipe is not the right fit.
About the Code Recipe
The recipe does two things. First, it adds a How far into the term are you? select field to the membership checkout page for the levels you specify. The field offers values from 1 month to 9 months. Second, it filters the $level object during checkout, reads the value the member chose, and sets the expiration date to the remaining time in a 10-month term.
For example, if a member selects 2 Months, the recipe sets their expiration to 8 months from the checkout date. The total term length and the option list are easy to change for your own cycle.
Understanding the pmpro_checkout_level Filter
The pmpro_checkout_level filter runs during membership checkout after the form is submitted, but before the level is applied to the member’s account. It passes the $level object that Paid Memberships Pro is about to use to create the membership, and your callback returns it (modified or not).
This is the right hook for adjusting expiration dates because anything you change on the level object, including expiration_number and expiration_period, is applied to that one member without affecting the level’s defaults in the WordPress admin.
The Code Recipe
Adding the Recipe to Your Website
You can add this recipe to your site by creating a custom plugin or using the Code Snippets plugin available for free in the WordPress repository. Read this companion article for step-by-step directions on either method.
How to Customize This Code Recipe
Change Which Levels Show the Term Field
The recipe shows the term field on level IDs 1 and 2 by default in the PMPro_Field definition. To change which levels show the field, update the levels array on line 31. You can find your level IDs in Memberships > Settings > Levels in the WordPress admin. The ID appears in the URL when you click Edit next to a level.
Change the Total Term Length
The recipe assumes a 10-month term and offers options from 1 to 9 months. To use a different length, do two things in the snippet:
- Update the
optionsarray passed into thePMPro_Fielddefinition on line 33 so the dropdown lists the months that apply to your cycle. - Update the
$total_monthsvariable inmy_pmpro_checkout_level_set_expiration_from_term()on line 66 to match the full length of your cycle.
For example, for a 4-month semester, set $total_months to 4 and offer options from 1 to 3 months in the dropdown.
Create the Field in the User Fields UI Instead
If you would rather manage the term-progress field through the User Fields settings page instead of in code, you can build the same select field there and remove the my_pmpro_add_term_user_field() function from the snippet. Keep the my_pmpro_checkout_level_set_expiration_from_term() function. The expiration logic does not depend on how the field was created, only on the terms field name being submitted with the checkout form.


