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
- The snippet runs just before the plugin creates the advocate’s coupon.
- If the advocate already has an unused
RAF-…coupon of the same type, it adds the new reward to that coupon’s amount. - It then cancels the new coupon for this one reward. The friend’s Post-First Purchase Coupon is still created.
- 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
- Complete two test referrals for the same advocate.
- Under Marketing → Coupons, there should be one
RAF-…coupon for that advocate, with an amount equal to both rewards together.