Skip to main content
Lunar provides a flexible discount system supporting coupons, percentage and fixed reductions, and buy-x-get-y promotions.

Overview

Lunar provides a discount system that supports multiple discount types out of the box, including amount-off (percentage or fixed) and buy-x-get-y promotions. Discounts can be scoped to specific channels, customer groups, collections, brands, and individual products or variants.

Relationships

Scopes

Creating a Discount

Discount Status

The Discount model provides a status attribute that returns the current state of the discount based on its dates and usage.

Resetting the Discount Cache

For performance reasons, applicable discounts are cached per request. To reset this cache (for example, after adding a discount code to a cart), call resetDiscounts() on the Discounts facade:

Validating Coupons

The Discounts facade provides a method to validate whether a coupon code is valid:
The default coupon validator checks that the coupon exists on an active, usable discount. The validator class can be customized in the config/lunar/discounts.php configuration file:

Discountable

The Discountable model links products, product variants, or collections to a discount. Each entry has a type that determines its role.
The type field determines how the discountable relates to the discount:
  • condition — The product or variant must be in the cart for the discount to activate.
  • exclusion — The product or variant is excluded from the discount.
  • limitation — The discount only applies to these products or variants.
  • reward — These products or variants are given as the reward (used by BuyXGetY).

Relationships

Built-in Discount Types

Lunar ships with two discount types. Both extend Lunar\DiscountTypes\AbstractDiscountType.

AmountOff

Applies either a percentage or fixed amount discount to eligible cart lines. The data column stores the discount configuration: Percentage discount:
Fixed value discount:

BuyXGetY

Allows “buy X, get Y free” style promotions. Condition products are defined through the discountableConditions relationship, and reward products through the discountableRewards relationship. Both relationships accept products, product variants, or collections.
From Lunar 1.5, BuyXGetY also enforces the discount’s own conditions (minimum spend, customer restrictions, and max_uses_per_user) before awarding a reward, in the same way as Lunar\DiscountTypes\AmountOff. In earlier versions only min_qty gated the discount. See the upgrade guide.

Automatically adding rewards

When automatically_add_rewards is true, qualifying carts have the reward added as a cart line rather than requiring the customer to add it themselves.
  • Products, product variants, and collections are all supported as the automatically added reward.
  • A reward quantity greater than one produces a single cart line with that quantity, not one line per item.
  • Reward lines are stored using Lunar’s morph map, so purchasable_type matches any other line holding the same purchasable (for example product_variant). Queries that filter cart or order lines by morph type include reward lines.
  • Only rewards that can be fulfilled are selected, so a reward that is out of stock is skipped rather than raising an error when the line is added.

Collection conditions and rewards Added in 1.5

A BuyXGetY discount can match against an entire collection rather than listing every product or variant individually. The match logic walks each cart line’s product, checks the collections it belongs to, and compares those against the collections attached as conditions or rewards.
Conditions and rewards can mix product, variant, and collection discountables on the same discount.

Custom Discount Types

Custom discount types can be created by extending Lunar\DiscountTypes\AbstractDiscountType:
Register the custom type using the Discounts facade, typically in a service provider:

Discounts Facade

The Lunar\Facades\Discounts facade provides methods for managing and applying discounts: