Subscription Templates

Once you’ve familiarized yourself with how subscriptions work and set up your subscription plans, you’re ready to write some subscription templates.

Each gateway provides a default template for subscription actions. If you’d prefer to handle templating yourself, you’ll have to reference the gateway plugin’s documentation to see what parameters are available.

These examples are intended to get you started toward working subscriptions and specify the correct endpoints for subscription actions.

# Subscribing

For starting a subscription, the following example is a good start.

Gateways handle subscription payment sources differently, which might impact what’s needed for your template.

This example creates a form for each available plan, posting the selection to the commerce/subscriptions/subscribe form action:

{% set plans = craft.commerce.getPlans().getAllPlans() %}

{% for plan in plans %}
  <form method="post">
    {{ csrfInput() }}
    {{ actionInput('commerce/subscriptions/subscribe') }}
    {{ hiddenInput('planUid', plan.uid|hash) }}

    <h4>{{ plan.name }}</h4>

    {% set paymentSources = craft.commerce.
      getPaymentSources().
      getAllGatewayPaymentSourcesByCustomerId(
        plan.getGateway().id,
        currentUser.id ?? null
      )
    %}

    {# If we don’t have a saved payment soruce, collect details for the gateway #}
    {% if not paymentSources|length %}
      <div class="paymentForm">
        {% namespace plan.getGateway().handle|commercePaymentFormNamespace %}
          {{ plan.getGateway().getPaymentFormHtml({})|raw }}
        {% endnamespace %}
      </div>
    {% endif %}

    <button>{{ "Subscribe"|t }}</button>
  </form>
{% endfor %}

There are several things to note:

  • Subscribing a user to a plan requires the user to have a stored payment source. If a user doesn’t have one, you can add it by displaying the payment form with {{ plan.getGateway().getPaymentFormHtml({})|raw }}.
  • If you wish to set subscription parameters, such as amount of trial days, it is strongly recommended to make use of subscription events instead of POST data.
  • When using Stripe, it’s not possible to choose which payment source to use if more than one is saved. Stripe will use the default payment source associated with that customer.

# Canceling the subscription

To cancel a subscription you can use the following template. It assumes the subscription variable is available and set to an instance of craft\commerce\elements\Subscription, and posts to the commerce/subscriptions/cancel form action:

<form method="post">
  {{ csrfInput() }}
  {{ actionInput('commerce/subscriptions/cancel') }}
  {{ hiddenInput('subscriptionUid', subscription.uid|hash) }}
  {{ redirectInput('shop/services') }}

  {% namespace subscription.getGateway().handle|commercePaymentFormNamespace %}
    {{ subscription.plan.getGateway().getCancelSubscriptionFormHtml()|raw }}
  {% endnamespace %}

  <button>Unsubscribe</button>
</form>

If you wish to set cancellation parameters, it is strongly recommended to make use of subscription events instead of POST data.

# Switching the subscription plan

To switch a subscription plan you can use the following template. It assumes that subscription variable is available and set to an instance of craft\commerce\elements\Subscription, and posts to the commerce/subscriptions/switch form action:

{% for plan in subscription.alternativePlans %}
  <strong>Switch to {{ plan.name }}</strong>
  <form method="post">
    {{ csrfInput() }}
    {{ actionInput('commerce/subscriptions/switch') }}
    {{ hiddenInput('subscriptionUid', subscription.uid|hash) }}
    {{ hiddenInput('planUid', plan.uid|hash) }}

    {{ plan.getGateway().getSwitchPlansFormHtml(subscription.plan, plan)|raw }}

    <button class="button link">Switch</button>
  </form>
  <hr />
{% endfor %}

If you wish to set parameters for switching the subscription plan, it is strongly recommended to make use of subscription events instead of POST data.

# Reactivating a canceled subscription

To reactivate a subscription plan you can use the following template. It assumes the subscription variable is available and set to an instance of craft\commerce\elements\Subscription, and posts to the commerce/subscriptions/reactivate form action.

{% if subscription.canReactivate() %}
  <form method="post">
    {{ csrfInput() }}
    {{ actionInput('commerce/subscriptions/reactivate') }}
    {{ hiddenInput('subscriptionUid', subscription.uid|hash) }}

    <button class="button link">Reactivate</button>
  </form>
{% endif %}

Not all canceled subscriptions might be available for reactivation, so make sure to check for that using subscription.canReactivate().