The right referral incentive can multiply your viral coefficient. The wrong one wastes budget on low-quality users or fails to motivate sharing at all. A/B testing referral incentives tells you exactly which reward type, amount, and structure drives the most high-quality referrals for your app.
For referral reward fundamentals, see Referral Reward Strategies: Finding the Right Incentive. For A/B testing deep links, see A/B Testing Deep Links and Landing Pages.
The A/B test creation form with test type, goal metric, route picker, and variant builder.
What to Test
Incentive Variables
| Variable | Options | Impact |
|---|---|---|
| Reward type | Cash, credit, free month, feature unlock | High |
| Reward amount | $5 vs. $10 vs. $20 | High |
| Reward structure | Single-sided vs. double-sided | High |
| Reward timing | Immediate vs. after action | Medium |
| Reward visibility | Prominent vs. subtle | Medium |
| Referral limit | Unlimited vs. capped | Low |
| Expiration | None vs. 30 days vs. 7 days | Medium |
Test Priority
- Reward type: Cash vs. credit vs. feature unlock (biggest impact)
- Double-sided vs. single-sided: Does rewarding the invitee improve conversion?
- Reward amount: Find the minimum effective amount
- Timing: Immediate reward vs. after the invitee's first purchase
Reward Type Tests
Cash vs. Credit vs. Feature
const rewardTypeExperiment = {
id: 'referral_reward_type_v2',
variants: [
{
id: 'cash',
weight: 25,
config: {
referrerReward: { type: 'cash', amount: 10, currency: 'USD' },
inviteeReward: { type: 'cash', amount: 10, currency: 'USD' },
displayText: 'Give $10, Get $10',
},
},
{
id: 'credit',
weight: 25,
config: {
referrerReward: { type: 'credit', amount: 15, currency: 'USD' },
inviteeReward: { type: 'credit', amount: 15, currency: 'USD' },
displayText: 'Give $15, Get $15 in credit',
},
},
{
id: 'feature',
weight: 25,
config: {
referrerReward: { type: 'feature', feature: 'premium_month', value: 9.99 },
inviteeReward: { type: 'feature', feature: 'premium_month', value: 9.99 },
displayText: 'Give a free month, Get a free month',
},
},
{
id: 'points',
weight: 25,
config: {
referrerReward: { type: 'points', amount: 500, value: 5 },
inviteeReward: { type: 'points', amount: 500, value: 5 },
displayText: 'Give 500 points, Get 500 points',
},
},
],
primaryMetric: 'referral_sent',
secondaryMetrics: ['referral_converted', 'invitee_d30_retention', 'reward_cost_per_acquisition'],
};
Typical results by app type:
| App Type | Best Reward Type | Why |
|---|---|---|
| E-commerce | Cash or credit | Direct purchasing power |
| SaaS/Subscription | Free month | Aligns with the product |
| Gaming | In-game currency | Matches user motivation |
| Fintech | Cash | Users are money-motivated |
| Social | Feature unlock | Status/access is the currency |
Amount Sensitivity
const rewardAmountExperiment = {
id: 'referral_amount_v1',
variants: [
{
id: 'low',
weight: 33,
config: {
referrerReward: { type: 'credit', amount: 5 },
inviteeReward: { type: 'credit', amount: 5 },
displayText: 'Give $5, Get $5',
},
},
{
id: 'medium',
weight: 33,
config: {
referrerReward: { type: 'credit', amount: 10 },
inviteeReward: { type: 'credit', amount: 10 },
displayText: 'Give $10, Get $10',
},
},
{
id: 'high',
weight: 34,
config: {
referrerReward: { type: 'credit', amount: 20 },
inviteeReward: { type: 'credit', amount: 20 },
displayText: 'Give $20, Get $20',
},
},
],
primaryMetric: 'referral_converted',
secondaryMetrics: ['referral_sent', 'cost_per_acquisition', 'invitee_ltv'],
};
Important: Don't just look at referral volume. Calculate cost per acquired user:
function calculateReferralROI(variantResults) {
const { referralsSent, referralsConverted, rewardAmount, inviteeLTV } = variantResults;
const conversionRate = referralsConverted / referralsSent;
const totalRewardCost = referralsConverted * rewardAmount * 2; // Both sides
const costPerAcquisition = totalRewardCost / referralsConverted;
const roi = (inviteeLTV - costPerAcquisition) / costPerAcquisition;
return {
conversionRate: (conversionRate * 100).toFixed(1) + '%',
costPerAcquisition: '$' + costPerAcquisition.toFixed(2),
roi: (roi * 100).toFixed(0) + '%',
isPositiveROI: roi > 0,
};
}
Higher rewards increase volume but also increase cost. The optimal amount is the one that maximizes (referrals x LTV) - (referrals x reward cost).
Structure Tests
Double-Sided vs. Single-Sided
const structureExperiment = {
id: 'referral_structure_v1',
variants: [
{
id: 'referrer_only',
weight: 33,
config: {
referrerReward: { type: 'credit', amount: 10 },
inviteeReward: null,
displayText: 'Get $10 for every friend you invite',
shareMessage: 'Check out [App]!',
},
},
{
id: 'invitee_only',
weight: 33,
config: {
referrerReward: null,
inviteeReward: { type: 'credit', amount: 10 },
displayText: 'Give your friends $10 off',
shareMessage: 'Here\'s $10 off [App]!',
},
},
{
id: 'double_sided',
weight: 34,
config: {
referrerReward: { type: 'credit', amount: 10 },
inviteeReward: { type: 'credit', amount: 10 },
displayText: 'Give $10, Get $10',
shareMessage: 'We both get $10 when you join [App]!',
},
},
],
primaryMetric: 'referral_converted',
secondaryMetrics: ['referral_sent', 'invitee_d7_retention', 'cost_per_acquisition'],
};
Typical results:
| Structure | Referrals Sent | Conversion Rate | Best For |
|---|---|---|---|
| Referrer only | High | Lower | Driving volume |
| Invitee only | Lower | Higher | Quality conversions |
| Double-sided | Highest | Highest | Most apps (standard) |
Double-sided programs outperform single-sided by 25-40% on total conversions in most categories.
Asymmetric Rewards
const asymmetricExperiment = {
id: 'asymmetric_reward_v1',
variants: [
{
id: 'equal',
weight: 33,
config: {
referrerReward: 10,
inviteeReward: 10,
displayText: 'Give $10, Get $10',
},
},
{
id: 'referrer_more',
weight: 33,
config: {
referrerReward: 15,
inviteeReward: 5,
displayText: 'Earn $15 for each friend ($5 for them)',
},
},
{
id: 'invitee_more',
weight: 34,
config: {
referrerReward: 5,
inviteeReward: 15,
displayText: 'Give friends $15, you get $5',
},
},
],
primaryMetric: 'referral_converted',
};
Invitee-weighted rewards typically produce higher conversion rates (the invitee has more motivation to complete signup). Referrer-weighted rewards produce more shares (the referrer is more motivated to send). For most apps, equal rewards perform best overall.
Timing Tests
Immediate vs. Delayed Rewards
const timingExperiment = {
id: 'reward_timing_v1',
variants: [
{
id: 'immediate',
weight: 50,
config: {
referrerRewardTrigger: 'invitee_signup',
inviteeRewardTrigger: 'signup',
displayText: 'Get $10 instantly when your friend signs up',
},
},
{
id: 'after_action',
weight: 50,
config: {
referrerRewardTrigger: 'invitee_first_purchase',
inviteeRewardTrigger: 'first_purchase',
displayText: 'Get $10 when your friend makes their first purchase',
},
},
],
primaryMetric: 'referral_sent',
secondaryMetrics: ['referral_converted', 'invitee_first_purchase', 'fraud_rate'],
};
| Timing | Shares | Conversions | Fraud Risk | User Quality |
|---|---|---|---|---|
| Immediate (on signup) | Higher | Higher | Higher | Lower |
| Delayed (on first purchase) | Lower | Lower volume, higher quality | Lower | Higher |
Delayed rewards reduce fraud significantly but also reduce volume. For subscription apps, rewarding on "completed first billing cycle" produces the highest quality referrals.
Deep Link Configuration for Referral Tests
Referral Link with Experiment Data
async function generateReferralLink(referrerId, experimentId) {
const variant = assignVariant(referrerId, experimentId);
const deepLink = await createDeepLink({
path: '/referral',
params: {
ref: referrerId,
experimentId,
variantId: variant.id,
reward: JSON.stringify(variant.config.inviteeReward),
},
fallbackUrl: `https://example.com/invite?ref=${referrerId}`,
});
return {
url: deepLink,
shareMessage: variant.config.shareMessage.replace('[App]', 'AppName'),
displayText: variant.config.displayText,
};
}
Invitee Landing Page
function ReferralLandingPage({ params }) {
const variant = getVariantConfig(params.experimentId, params.variantId);
return (
<Page>
<Heading>
{params.referrerName} invited you to join
</Heading>
{variant.inviteeReward && (
<RewardBanner>
{formatReward(variant.inviteeReward)}
</RewardBanner>
)}
<CTAButton
href={appStoreLink}
onClick={() => trackReferralClick(params)}
>
{variant.ctaText || 'Get the App'}
</CTAButton>
</Page>
);
}
Tracking and Analysis
Event Schema
// Referral link shared
analytics.track('referral_shared', {
experimentId,
variantId,
referrerId,
shareMethod: 'whatsapp', // or 'sms', 'email', 'copy_link', 'twitter'
});
// Invitee clicked referral link
analytics.track('referral_clicked', {
experimentId,
variantId,
referrerId,
inviteeDevice: deviceType,
});
// Invitee signed up
analytics.track('referral_signup', {
experimentId,
variantId,
referrerId,
inviteeId,
timeFromClick: timeDeltaMs,
});
// Reward earned
analytics.track('referral_reward_earned', {
experimentId,
variantId,
userId, // Could be referrer or invitee
rewardType: 'credit',
rewardAmount: 10,
side: 'referrer', // or 'invitee'
});
Full Funnel Analysis
async function referralFunnelAnalysis(experimentId) {
for (const variant of getVariants(experimentId)) {
const eligible = await countUsers({ experimentId, variantId: variant.id });
const shared = await countEvents('referral_shared', { variantId: variant.id });
const clicked = await countEvents('referral_clicked', { variantId: variant.id });
const signedUp = await countEvents('referral_signup', { variantId: variant.id });
const purchased = await countEvents('referral_first_purchase', { variantId: variant.id });
const rewardCost = await sumField('referral_reward_earned', 'rewardAmount', { variantId: variant.id });
const inviteeLTV = await avgField('user_ltv', { referralVariant: variant.id });
console.log(variant.id, {
shareRate: (shared / eligible * 100).toFixed(1) + '%',
clickRate: (clicked / shared * 100).toFixed(1) + '%',
signupRate: (signedUp / clicked * 100).toFixed(1) + '%',
purchaseRate: (purchased / signedUp * 100).toFixed(1) + '%',
costPerAcquisition: '$' + (rewardCost / signedUp).toFixed(2),
avgInviteeLTV: '$' + inviteeLTV.toFixed(2),
roi: (((inviteeLTV * signedUp) - rewardCost) / rewardCost * 100).toFixed(0) + '%',
});
}
}
Common Pitfalls
1. Optimizing for Volume Instead of Quality
A $50 reward will generate more referrals than a $5 reward, but many of those referred users will only sign up for the reward and never return.
Track invitee D30 retention and LTV, not just signup count.
2. Ignoring Fraud
High-value rewards attract fraud (self-referrals, fake accounts):
function detectReferralFraud(referral) {
const signals = [];
// Same device fingerprint
if (referral.referrerDevice === referral.inviteeDevice) {
signals.push('same_device');
}
// Same IP address
if (referral.referrerIP === referral.inviteeIP) {
signals.push('same_ip');
}
// Rapid completion (clicked and signed up in < 30 seconds)
if (referral.timeToSignup < 30000) {
signals.push('too_fast');
}
// Referrer has many referrals with low retention
if (referral.referrerReferralCount > 10 && referral.referrerInviteeRetention < 0.1) {
signals.push('low_quality_referrer');
}
return {
isSuspicious: signals.length >= 2,
signals,
};
}
3. Not Testing the Share Message
The incentive matters, but so does how it's communicated:
const shareMessageTest = {
id: 'share_message_v1',
variants: [
{
id: 'generic',
shareMessage: 'Check out this app!',
},
{
id: 'reward_focused',
shareMessage: 'Use my link and we both get $10!',
},
{
id: 'personal',
shareMessage: 'I\'ve been using this app and thought you\'d like it. We both get $10 if you sign up.',
},
],
primaryMetric: 'referral_clicked',
};
Best Practices
- Test reward type before amount: Whether you offer cash, credit, or features matters more than the dollar value.
- Default to double-sided: Start with equal rewards for both sides unless you have data suggesting otherwise.
- Track LTV, not just signups: A $20 reward that attracts users with $100 LTV is better than a $5 reward that attracts users with $10 LTV.
- Delay rewards to reduce fraud: Rewarding on first purchase or first week of activity filters out low-quality referrals.
- Run for at least 30 days: Referral experiments need time for invitees to sign up, activate, and show retention patterns.
- Segment by referrer behavior: Power referrers (5+ referrals) may respond differently to incentive changes than casual sharers.
For A/B testing features, see Tolinku A/B testing. For referral setup, see the referral docs and the A/B testing docs.
Get deep linking tips in your inbox
One email per week. No spam.