Season Memberships

A recurring plan bills on each member’s own anniversary. That is the wrong shape for an organisation whose membership year is a fixed calendar window — a club running July to June, where everyone should expire together on 30 June no matter when they joined. A fixed season plan is that shape.

Creating a Season Plan

Under Headcount → Plans, set Term Type to Fixed season. The billing interval fields are replaced by the season window:

FieldWhat it does
Season StartsThe first day of the membership year.
Season EndsThe last day. Members keep access through this day — a season ending 30 June is still valid at 6pm on 30 June — then expire together.
Repeats Every YearOn by default. The window rolls forward a year on its own once the season finishes, so next season sells itself without anyone editing the plan.
Pro-rata Mid-season JoinsOff by default. When on, scales the price by how much of the season is left.

A repeating season must be shorter than a year, otherwise it would overlap its own next occurrence and “which season is this member in” would stop having one answer. Turn Repeats Every Year off for a one-off season, which simply stops selling once it ends.

Pro-rata Pricing

Two bases, both counting the join month or day itself — somebody joining on the 20th still gets the rest of that month:

BasisExample on a £120 July–June season
Whole months remaining (default)Joining in October leaves nine months of twelve — £90. Familiar, and it is what most clubs mean by “half a season”.
Days remainingJoining on 1 January leaves 181 days of 365 — £59.51. Exact, but produces prices nobody would print on a form.

Anyone buying before the season opens pays full price and their membership starts on the first day of the season, not on the day they paid.

How Payment Works

A season membership is a one-off Stripe payment, not a subscription — there is no billing cycle and nothing renews. Two consequences worth knowing before you build a pricing page:

  • Season plans have no stored Stripe Price. A pro-rata plan charges a different amount to everybody who joins on a different day, and a stored Price can only hold one number, so the line item is built per checkout. headcount/sync/plans skips season plans.
  • PayPal cannot be used. Its Subscriptions API only bills on a cycle. Checkout refuses a PayPal season purchase rather than quietly signing the member up to something recurring — offer card payment for these plans.

Coupons and Stripe promotion codes work as normal.

Expiry

Nothing expires on its own. Run the expiry command daily — it retires finished season terms as expired and removes members from the plan’s user group, while a membership the member actually cancelled becomes canceled:

# Daily
php craft headcount/subscriptions/expire

# Daily — warns members before their season runs out
php craft headcount/subscriptions/remind

The reminder is worth setting up for season plans in particular: nothing renews automatically, so that email is the only thing between a member and quietly losing access on 1 July. Set how far ahead it goes out under Headcount → Settings → Emails.

In Templates

A season plan exposes its current window and the price a member would pay if they joined right now:

{% set plan = craft.headcount.plan('club-membership') %}

{% if plan.isFixedTerm() %}
  {% set window = plan.getSeasonWindow() %}
  <h3>{{ plan.name }}</h3>
  <p>Season: {{ window.start|date('j M Y') }} to {{ window.end|date('j M Y') }}</p>

  {# What this visitor would actually be charged today #}
  <p>{{ plan.currency|upper }} {{ plan.getProratedPrice()|number_format(2) }}</p>

  {% if plan.getProratedPrice() < plan.price %}
    <p class="note">Reduced — the season is already under way.</p>
  {% endif %}
{% endif %}

The same fields are on the REST API’s plans endpoint as termType, seasonStart, seasonEnd and currentPrice.

Season Cards

Season memberships pair naturally with wallet cards: the card carries the season’s end date, so it greys out on the member’s phone on 1 July whether or not their phone has spoken to your site since.

More in Site Features

Pairs well with Headcount

The bigger pieces a client asks for by name. Events, bookings, memberships, courses, reviews, a support desk, job listings and the rest.