Stack rewards into one coupon

Last updated

By default, every successful referral gives the advocate a new coupon. This snippet keeps one coupon per advocate instead and adds each new reward to its amount, so the advocate always redeems the same, growing coupon.

Before you start: read Add code snippets safely. Checked with version 4.4.12.

Which coupon types can stack

Advocate coupon type Stacks? Why
Fixed Cart Discount, Product Discount Yes Amounts add up, for example $5 + $8 = $13.
Percentage of Friend’s Order Yes The plugin turns it into a fixed amount for each order.
Percentage Discount and other percentage types No 10% + 10% isn’t a sensible reward. The advocate gets separate coupons as usual.

The snippet

add_action( 'gens_before_generate_user_coupon', function ( $user_id, $type, $order ) {
    // Only the advocate reward. Friend and registration coupons are unchanged.
    if ( 'referrer' !== $type || ! $order ) {
        return;
    }

    $discount_type = get_option( 'gens_raf_coupon_type' );
    $amount        = get_option( 'gens_raf_coupon_amount' );

    if ( 'order_percent' === $discount_type ) {
        $order_total = $order->get_total() - $order->get_total_tax();
        if ( get_option( 'gens_raf_subscription_exclude_shipping' ) ) {
            $order_total -= $order->get_total_shipping();
        }
        $discount_type = 'fixed_cart';
        $amount        = number_format( $order_total * ( $amount / 100 ), 2, '.', '' );
    }
    $amount = apply_filters( 'gens_raf_coupon_amount', $amount, $order->get_id() );

    if ( 'fixed_cart' !== $discount_type && 'fixed_product' !== $discount_type ) {
        return;
    }

    // Find the advocate's email.
    $email = '';
    if ( is_string( $user_id ) && strpos( $user_id, 'ref' ) === 0 ) {
        $db    = new WPGens_RAF_DB();
        $guest = $db->get_guest_referral_by_code( $user_id );
        if ( $guest ) {
            $email = $guest['email'];
        } elseif ( $numeric = WPGens_RAF_User::get_id_from_referral_code( $user_id ) ) {
            $u     = get_userdata( $numeric );
            $email = $u ? $u->user_email : '';
        }
    } elseif ( is_email( $user_id ) ) {
        $email = $user_id;
    } elseif ( $u = get_userdata( $user_id ) ) {
        $email = $u->user_email;
    }
    if ( ! $email ) {
        return;
    }

    // Find the advocate's oldest unused referral coupon of the same type.
    $existing = get_posts( array(
        'post_type'   => 'shop_coupon',
        'post_status' => 'publish',
        'numberposts' => -1,
        'orderby'     => 'date',
        'order'       => 'ASC',
        'meta_query'  => array(
            array( 'key' => 'customer_email', 'value' => strtolower( $email ) ),
            array( 'key' => 'discount_type', 'value' => $discount_type ),
        ),
    ) );

    $master = null;
    foreach ( $existing as $c ) {
        if ( strpos( $c->post_title, 'RAF-' ) !== 0 ) {
            continue;
        }
        $used  = (int) get_post_meta( $c->ID, 'usage_count', true );
        $limit = (int) get_post_meta( $c->ID, 'usage_limit', true );
        if ( $limit && $used >= $limit ) {
            continue;
        }
        $master = $c;
        break;
    }

    // First reward: let the plugin create the coupon as usual.
    if ( ! $master ) {
        return;
    }

    $current = (float) get_post_meta( $master->ID, 'coupon_amount', true );
    update_post_meta( $master->ID, 'coupon_amount', $current + (float) $amount );

    // Skip creating a new coupon this time only.
    $one_shot = function () use ( &$one_shot ) {
        remove_filter( 'gens_raf_generate_coupon', $one_shot );
        return false;
    };
    add_filter( 'gens_raf_generate_coupon', $one_shot );
}, 10, 3 );

How it works

  1. The snippet runs just before the plugin creates the advocate’s coupon.
  2. If the advocate already has an unused RAF-… coupon of the same type, it adds the new reward to that coupon’s amount.
  3. It then cancels the new coupon for this one reward. The friend’s Post-First Purchase Coupon is still created.
  4. The first time an advocate earns a reward, nothing is stacked and the coupon is created normally.

The growing amount shows in My Account → Refer a Friend, because that list reads the coupon’s current amount.

Emails

The advocate gets the coupon email the first time the coupon is created. Top-ups don’t send an email. Advocates see the new balance in My Account → Refer a Friend.

Check it worked

  1. Complete two test referrals for the same advocate.
  2. Under Marketing → Coupons, there should be one RAF-… coupon for that advocate, with an amount equal to both rewards together.

Related

Browse our plugins

Lightweight WooCommerce plugins built for speed. No bloat, no frameworks -- just clean code that works.

View all plugins
Stay in the loop

Get notified when we launch new plugins. No spam, just product updates.