Coupon Codes

With the release of Commerce 4.5, Lite and Pro editions have been merged! Features described in this article are now available to all Commerce installations—existing Lite licenses have been upgraded, automatically.

Coupon codes are unique strings customers may enter for an order to receive a discount.

Craft Commerce treats coupon codes as conditions within a discount promotion. Go to CommercePromotionsDiscounts, select an existing promotion or press + New discount to start a new one, and select to the “Coupons” tab:

Screenshot of a new discount’s settings with its “Coupons” tab selected, displaying a “Generate” button and a separate “Add a coupon button”

There are no coupon codes by default, meaning no coupon code is necessary for the discount to work.

# Adding Coupon Codes

You can click + Add a coupon to create them one at a time, where each one needs a Code and optional Max Uses. Individual code uses will be updated automatically in the Uses column each time an order is completed using that code for a matching discount:

Screenshot of a row in the Coupons table, with three columns: “Code”, “Uses”, and “Max Uses”

Store managers can edit a coupon code’s Uses for flexibility, so that number may be different from counting rows in a database query.

Press Generate if you’d like to create codes in bulk:

Screenshot of the “Generate” HUD, with a “Number of Coupons” field and a “Generated Coupon Format” field

Set the number of coupons you’d like to generate along with a desired format, where pound signs (#) will be replaced with random letters. Press Submit and they’ll be generated and added to the set.

To make a coupon code no longer available for use, you can either delete it from the table or set its Max Uses to 0.

# Using a Coupon Code

To add a coupon to the cart, a customer submits the couponCode parameter using the commerce/cart/update-cart form action:

<form method="post">
  {{ csrfInput() }}
  {{ actionInput('commerce/cart/update-cart') }}
  {{ hiddenInput('successMessage', 'Added coupon code.'|hash) }}
  {{ redirectInput('shop/cart') }}

  <input type="text"
    name="couponCode"
    value="{{ cart.couponCode }}"
    placeholder="{{ "Coupon Code"|t }}"
  >

  <button>Update Cart</button>
</form>

Only one coupon code can exist on the cart at a time, accessible via {{ cart.couponCode }}.

If the customer submits an invalid code, Commerce may update the cart but adds an order notice:







 
 







 






<form method="post">
  {{ csrfInput() }}
  {{ actionInput('commerce/cart/update-cart') }}
  {{ hiddenInput('successMessage', 'Added coupon code.'|hash) }}
  {{ redirectInput('shop/cart') }}

  {# Get the first notice for the `couponCode` attribute, if we have one #}
  {% set couponCodeNotice = cart.getFirstNotice(null, 'couponCode') %}

  {# Get any lower-level coupon code errors just in case #}
  {% set couponCodeError = cart.getFirstError('couponCode') %}

  <input type="text"
    name="couponCode"
    value="{{ cart.couponCode }}"
    class="{% if couponCodeNotice or couponCodeError %}has-error{% endif %}"
    placeholder="{{ "Coupon Code"|t }}"
  >

  <button>Update Cart</button>
</form>

The example above includes cart.getFirstError('couponCode') as a precaution. Commerce won’t throw any coupon errors, but another plugin or custom module could.

You can retrieve the discount associated with the coupon code using craft.commerce.discounts.getDiscountByCode():

{# @var discount craft\commerce\models\Discount #}
{% set discount = craft.commerce.discounts.getDiscountByCode(cart.couponCode) %}
{% if discount %}
  {{ discount.name }} - {{ discount.description }}
{% endif %}