07967 325669 info@mootpoint.org

I recently had to modify a WooCommerce installation to accept gift cards by entering the gift card as a WooCommerce coupon. The gift card validity had to be checked via a SOAP call to an external API, in other words the coupons did not exist in WooCommerce. So I needed to hook into the point the coupon is added in the cart or checkout. There is a woocommerce_coupon_is_valid filter but it only runs after checking if the coupon exists in WooCommerce, and so will never run in our case.

By looking through the codex, I found a little known filter woocommerce_get_shop_coupon_data which allows developers to bypass the retrieval of the coupon from the database and create one programmatically. If our hook code returns an array with the coupon properties, WooCommerce will apply the coupon to the cart and calculate the correct discounts.

For some scenarios, we don’t need to create the coupon in the WordPress database at all. However, if we need to check usage limits we will need to create a database record so that WooCommerce can keep track of how many times it has been used. Since the woocommerce_get_shop_coupon_data is triggered several times in the cart, we need to first check if we’ve already created the coupon:

add_filter ( 'woocommerce_get_shop_coupon_data', 'mp_create_coupon', 10, 2  );

function mp_create_coupon( $data, $code ) {
	// Check if the coupon has already been created in the database
	global $wpdb;
	$sql = $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' ORDER BY post_date DESC LIMIT 1;", $code );
	$coupon_id = $wpdb->get_var( $sql );
	if ( empty( $coupon_id ) ) {
		// Create a coupon with the properties you need
		$data = array(
			'discount_type'              => 'fixed_cart',
			'coupon_amount'              => 100, // value
			'individual_use'             => 'no',
			'product_ids'                => array(),
			'exclude_product_ids'        => array(),
			'usage_limit'                => '',
			'usage_limit_per_user'       => '1',
			'limit_usage_to_x_items'     => '',
			'usage_count'                => '',
			'expiry_date'                => '2018-09-01', // YYYY-MM-DD
			'free_shipping'              => 'no',
			'product_categories'         => array(),
			'exclude_product_categories' => array(),
			'exclude_sale_items'         => 'no',
			'minimum_amount'             => '',
			'maximum_amount'             => '',
			'customer_email'             => array()
		// Save the coupon in the database
		$coupon = array(
			'post_title' => $code,
			'post_content' => '',
			'post_status' => 'publish',
			'post_author' => 1,
			'post_type' => 'shop_coupon'
		$new_coupon_id = wp_insert_post( $coupon );
		// Write the $data values into postmeta table
		foreach ($data as $key => $value) {
			update_post_meta( $new_coupon_id, $key, $value );
	return $data;