Coupons
A coupon is a code the customer enters in the cart to get a discount. In the admin panel coupons are created in Marketing → Coupons, and in code a coupon is a WC_Coupon object. The code field appears in the cart if Enable the use of coupon codes is ticked in WooCommerce → Settings → General.
Where to write the code
Create the includes/coupons.php file and include it in acme-shop.php. One-off operations go into the scripts folder as before.
Reading a coupon
// wp-content/plugins/acme-shop/scripts/show-coupon.php
$coupon = new WC_Coupon('WELCOME10');
echo $coupon->get_id() . PHP_EOL;
echo $coupon->get_discount_type() . PHP_EOL;
echo $coupon->get_amount() . PHP_EOL;The constructor takes the coupon code. Create a WELCOME10 coupon in the admin panel and run the file with wp eval-file: the script prints the ID, the discount type and its amount. For a coupon that does not exist get_id() returns 0.
Discount types
| Value | Meaning |
|---|---|
percent | A percentage of the amount |
fixed_cart | A fixed amount off the whole cart |
fixed_product | A fixed amount off every matching product |
Creating in code
// wp-content/plugins/acme-shop/scripts/create-coupon.php
$coupon = new WC_Coupon();
$coupon->set_code('SPRING15');
$coupon->set_discount_type('percent');
$coupon->set_amount(15);
$coupon->set_minimum_amount('30');
$coupon->set_usage_limit(100);
$coupon->set_individual_use(true);
$coupon->set_date_expires(strtotime('+30 days'));
$coupon->save();The 15% coupon is valid for a month, at most a hundred times, for a cart of €30 or more, and cannot be combined with other coupons. After the run it appears in Marketing → Coupons and can be entered in the cart.
Applying in code
WooCommerce cannot apply a coupon from a link — let us add that:
// wp-content/plugins/acme-shop/includes/coupons.php
add_action('template_redirect', function () {
$code = sanitize_text_field(wp_unslash($_GET['acme_coupon'] ?? ''));
if ($code !== '' && WC()->cart && !WC()->cart->has_discount($code)) {
WC()->cart->apply_coupon($code);
}
});Open /cart/?acme_coupon=SPRING15 with products in the cart: the coupon is applied and a discount line appears in the totals. has_discount() prevents applying one code twice.
| Cart method | What it does |
|---|---|
apply_coupon($code) | Applies a coupon, returns true or false |
remove_coupon($code) | Removes a coupon |
get_applied_coupons() | An array of applied codes |
get_discount_total() | The coupon discount amount |
A custom condition
The standard restrictions — expiry, minimum amount, categories — are set in the admin panel. Your own condition is added with a filter:
// wp-content/plugins/acme-shop/includes/coupons.php
add_filter('woocommerce_coupon_is_valid', function (bool $valid, WC_Coupon $coupon): bool {
if ($coupon->get_code() !== 'welcome10') {
return $valid;
}
if (is_user_logged_in() && wc_get_customer_order_count(get_current_user_id()) > 0) {
throw new Exception('The coupon is valid for the first order only.');
}
return $valid;
}, 10, 2);The filter is called on every coupon check. The exception stops the coupon from being applied, and the customer sees its text as an error message. WooCommerce stores the coupon code in lower case — compare with welcome10, not WELCOME10.
Coupons in an order
foreach ($order->get_coupon_codes() as $code) {
echo $code;
}The method returns the codes of the coupons applied in a placed order.
Common mistake
A conditional discount is implemented as a coupon that the code applies to every cart, and then it is a surprise that the customer can remove it. A coupon is something the customer enters. An automatic discount is made with a negative fee through add_fee() from the lesson on fees.