DEV Community

疏影
疏影

Posted on

5 retries + 1 success: a referral-invite timing pattern that actually worked

For my $5.50 lifetime ScsDriver WebDAV mount tool, I have a 7-day trial extendable via successful invite activations. For 8 months I've been tuning the timing of when reward emails go out.

Here are 5 things I tried, and the one pattern that actually moved retention metrics.

Retry 1: Send invite reward instantly on activation

Send the +14-day reward to the inviter the moment the invitee activates.

Result: 31% of rewards went to fake accounts (grinders, link-clickers, single-use emails). Real users churned from the noise.

Verdict: too eager.

Retry 2: Send reward after 24h

Wait 24h after activation to confirm the invitee is still around.

Result: fake rate dropped to 18%. Better. But real users got +14d on their 25th day after activation — by then they had forgotten why.

Verdict: better, but timing still off.

Retry 3: Send reward after 7 days

Wait 7 days. By then, real invitees are still using the product (activation score > 3).

Result: fake rate dropped to 4%. Real-user reward satisfaction jumped because they got the bonus right when they were thinking about renewal.

Verdict: huge improvement. This became my default.

Retry 4: Multi-stage cooldown (3d, 7d, 14d)

I tried splitting the +14d into 3d + 4d + 7d, distributed at 3, 7, 14 days.

Result: perceived as gimmicky. Users said it "felt like watching paint dry" and a few support emails complained about "where's my reward?". The extra tracking complexity also created more bugs.

Verdict: too clever. Stick with single-shot.

Retry 5: Personalized cooldown based on activation score

For invitees with activation_score >= 6, send reward at day 7. For score 3-5, send at day 14. For score < 3, no reward.

Result: this is the one that worked. Fake rate hit 1.8% (down from 4% with single 7-day). Real-user reward satisfaction went from 60% to 84% in survey. Activation score is doing the discrimination work; cooldown timing is doing the user-experience work.

Verdict: this is what I shipped.

The pattern that actually worked

def send_invite_reward(inviter, invitee):
    score = compute_activation_score(invitee)
    if score < 3:
        return  # fake, no reward

    delay_days = 14 if score < 6 else 7

    schedule_email(
        to=inviter.email,
        template='referral_thanks',
        delay=delay_days,
        params={'name': inviter.name, 'days': 14}
    )
Enter fullscreen mode Exit fullscreen mode

Two factors:

  1. Activation score gates reward eligibility (catches fake)
  2. Cooldown days are personalized by score (catches bad UX timing)

Why personalization mattered

Real users with high activation scores don't need 14 days to "confirm" — they're clearly invested by day 7. Real users with mid scores (3-5) benefit from longer confirmation. Splitting them by signal improves both groups' experience.

Fake accounts almost never reach score 3 — they install-and-leave without using the feature surface.

What I learned

  • Reward timing matters as much as reward size. Users notice when they get something.
  • Splitting a single reward into multi-stage adds perceived complexity without actual benefit.
  • Personalization based on real signals (activation) > rule-of-thumb heuristics.
  • The boring answer — wait 7 days — got me most of the way. Personalization added the last 20%.

For ScsDriver's referral program, this combination has held up over 8 months with minimal iteration. The activation-score signal does the heavy lifting; timing personalization is the user-experience polish on top.

Top comments (0)