Referred users already have two advantages over organic signups: they trust the person who referred them, and they often know what the app does. But most apps waste this advantage by sending referred users through the same generic onboarding as everyone else. The referrer's name never appears, the reward isn't mentioned until later, and the connection that drove the install is completely ignored.
For general onboarding personalization, see Personalized Onboarding Flows with Deep Link Data. For invite-specific flows, see Invite Link Onboarding: From Invitation to Active User. For referral program design, see Referral Deep Links: Complete Implementation Guide.
Why Referred Users Need Different Onboarding
Referred users differ from organic users in measurable ways:
| Characteristic | Organic User | Referred User |
|---|---|---|
| Trust level | Low (discovering the app) | Medium-high (friend endorsed it) |
| Product awareness | Variable | Usually knows the core value |
| Motivation | Curiosity, ad click | Social proof + reward |
| Expected friction tolerance | Medium | Low (expects a smooth experience) |
| Lifetime value (industry avg) | Baseline | 16-25% higher |
The onboarding flow should leverage these differences, not ignore them.
Capturing Referral Context
Deferred Deep Link Data
When a referred user installs and opens the app for the first time, the deferred deep link returns the referral context. For a detailed guide on how deferred deep linking works during onboarding, see Onboarding with Deferred Deep Linking.
async function checkReferralOnFirstLaunch() {
const deferred = await Tolinku.checkDeferredLink();
if (deferred === null) return null;
const params = deferred.params;
if (params.ref) {
return {
referrerId: params.ref,
referrerName: params.referrer_name,
rewardAmount: params.reward || '$10',
campaignId: params.campaign_id,
source: 'deep_link',
};
}
return null;
}
Fallback: Manual Referral Code Entry
For the 20-40% of users where deferred deep linking can't match the click to the install, provide a manual code entry option:
function ReferralCodeEntry({ onSubmit }) {
const [code, setCode] = useState('');
return (
<View>
<Text>Have a referral code? Enter it here.</Text>
<Input
placeholder="e.g., SARAH-2024"
value={code}
onChange={setCode}
/>
<Button onPress={() => onSubmit(code)}>Apply Code</Button>
<LinkButton onPress={() => navigation.navigate('DefaultOnboarding')}>
Skip
</LinkButton>
</View>
);
}
Place this on the first onboarding screen so users who weren't matched automatically can still get credit.
The Referred User Onboarding Flow
Step 1: Acknowledge the Referrer
The first screen should confirm the referral and set expectations:
function ReferralWelcome({ referral }) {
return (
<Screen>
<Avatar source={referral.referrerAvatar} />
<Heading>
{referral.referrerName} invited you to [App]
</Heading>
<RewardBadge amount={referral.rewardAmount} />
<Text>
Sign up and complete your first [action] to claim your
{' '}{referral.rewardAmount} reward.
</Text>
<Button onPress={() => navigation.navigate('QuickSignUp')}>
Get Started
</Button>
</Screen>
);
}
Key elements:
- Referrer's name (and avatar if available)
- The reward amount and how to claim it
- A clear CTA to start the signup
Step 2: Streamlined Account Creation
Referred users are motivated. Keep the signup form minimal:
function ReferralSignUp({ referral }) {
return (
<Form onSubmit={createAccount}>
<Input label="Email" autoFocus />
<Input label="Password" type="password" />
<RewardReminder>
{referral.rewardAmount} will be credited after your first [action].
</RewardReminder>
<Button type="submit">Create Account</Button>
<SocialSignUp>
<GoogleButton />
<AppleButton />
</SocialSignUp>
<Terms />
</Form>
);
}
What to skip for referred users:
- "How did you hear about us?" (you already know)
- Feature tours (the referrer already explained the app)
- Category/preference selection (show this later)
Step 3: Guide to the Qualifying Action
The referral reward depends on a qualifying action (first purchase, first deposit, first post). The onboarding should point directly to it:
function ReferralActivation({ referral, qualifyingAction }) {
return (
<Screen>
<ProgressIndicator
label={`Complete your first ${qualifyingAction.label} to earn ${referral.rewardAmount}`}
progress={0}
/>
<ActionCard
title={qualifyingAction.title}
description={qualifyingAction.description}
ctaText={qualifyingAction.ctaText}
onPress={() => navigation.navigate(qualifyingAction.screen)}
/>
<Text style={styles.secondary}>
Your reward will be credited within 24 hours of completing this step.
</Text>
</Screen>
);
}
Step 4: Reward Confirmation
After the qualifying action, confirm the reward immediately:
function RewardConfirmation({ referral, reward }) {
return (
<Screen>
<SuccessAnimation />
<Heading>You earned {reward.amount}!</Heading>
<Text>
Thanks to {referral.referrerName}'s referral, {reward.amount} has been
added to your account.
</Text>
<Text style={styles.secondary}>
{referral.referrerName} earned a reward too.
</Text>
<Button onPress={() => navigation.navigate('Home')}>
Start Exploring
</Button>
</Screen>
);
}
Reward Visibility Throughout Onboarding
The reward is the referred user's primary motivator. Keep it visible at every step:
Progress Indicators
function ReferralProgress({ currentStep, totalSteps, rewardAmount }) {
return (
<View style={styles.progressBar}>
<View style={styles.steps}>
{Array.from({ length: totalSteps }, (_, i) => (
<StepDot key={i} completed={i < currentStep} />
))}
</View>
<Text style={styles.rewardText}>
{currentStep < totalSteps
? `${rewardAmount} reward after signup`
: `${rewardAmount} earned!`}
</Text>
</View>
);
}
Persistent Banner
Show a subtle banner during onboarding that reminds the user about the reward:
function ReferralBanner({ referral, dismissed, onDismiss }) {
if (dismissed) return null;
return (
<Banner style={styles.referralBanner}>
<Text>{referral.rewardAmount} reward waiting for you</Text>
<CloseButton onPress={onDismiss} />
</Banner>
);
}
Handling Edge Cases
Referrer No Longer Active
The person who referred the user may have deleted their account or been suspended:
async function resolveReferrer(referrerId) {
const referrer = await getUser(referrerId);
if (referrer === null || referrer.status === 'suspended') {
return {
name: 'A friend',
avatar: null,
rewardStillValid: true, // Honor the reward regardless
};
}
return {
name: referrer.firstName,
avatar: referrer.avatarUrl,
rewardStillValid: true,
};
}
Always honor the reward even if the referrer's account is no longer active. The referred user shouldn't be penalized.
Existing User Taps Referral Link
A user who already has an account taps a referral link:
function handleReferralLinkForExistingUser(user, referralData) {
if (user.referredBy) {
// Already referred by someone
showToast('You already have an account with a referral applied.');
return;
}
// Allow applying referral to existing account (within grace period)
const accountAge = Date.now() - user.createdAt;
const GRACE_PERIOD = 7 * 24 * 60 * 60 * 1000; // 7 days
if (accountAge < GRACE_PERIOD) {
applyReferralToExistingAccount(user.id, referralData.referrerId);
showToast(`Referral from ${referralData.referrerName} applied!`);
} else {
showToast('Referral codes can only be applied to new accounts.');
}
}
Reward Program Has Changed
If the reward terms changed between when the link was shared and when the user signs up:
async function getApplicableReward(referralData) {
const linkReward = referralData.rewardAmount; // What was promised in the link
const currentReward = await getCurrentReferralReward(); // Current program terms
// Honor whichever is more favorable to the user
if (parseFloat(linkReward) > parseFloat(currentReward.amount)) {
return { amount: linkReward, source: 'link_promise' };
}
return { amount: currentReward.amount, source: 'current_program' };
}
Honoring the promised reward builds trust. If the program changed, the user should never get less than what was advertised in the link they clicked.
Referral Onboarding vs. Standard Onboarding
What to Keep
Even for referred users, some onboarding steps are still necessary:
- Account creation: Always required (but streamlined)
- Permissions: Push notifications, location (if needed for core features)
- Legal: Terms of service, privacy policy acceptance
- Core setup: Anything required for the app to function (e.g., connecting a bank account for a finance app)
What to Remove or Defer
| Standard Step | Referred User Treatment |
|---|---|
| Feature tour | Skip (referrer provided context) |
| "How did you hear about us?" | Skip (you know it was a referral) |
| Category/interest selection | Defer to settings |
| Promotional upsell | Skip (they just signed up) |
| Survey/feedback | Defer to day 7+ |
A/B Test the Difference
function getReferralOnboardingVariant(referralData) {
// Test abbreviated vs. standard for referred users
if (isInExperiment('referral_onboarding_v2', referralData.referrerId)) {
return 'abbreviated'; // 3-step flow
}
return 'standard'; // Full flow with referral context
}
Track completion rates, time-to-qualifying-action, and day-7 retention for each variant.
Notifying the Referrer
When the referred user completes onboarding, notify the person who referred them:
async function notifyReferrerOfSignup(referrerId, referredUser) {
await sendPushNotification(referrerId, {
title: `${referredUser.firstName} just joined!`,
body: `Your referral signed up. You'll both earn rewards when they complete their first [action].`,
data: {
type: 'referral_signup',
referredUserId: referredUser.id,
},
});
}
async function notifyReferrerOfReward(referrerId, referredUser, reward) {
await sendPushNotification(referrerId, {
title: `You earned ${reward.amount}!`,
body: `${referredUser.firstName} completed their first [action]. Check your rewards.`,
data: {
type: 'referral_reward',
screen: '/rewards',
},
});
}
These notifications serve two purposes: they reward the referrer with social validation, and they bring the referrer back into the app (increasing their engagement).
Measuring Referral Onboarding
Funnel Comparison
| Stage | Standard | Referred | Delta |
|---|---|---|---|
| Start onboarding | 100% | 100% | — |
| Complete signup | 55% | 75% | +36% |
| Complete qualifying action | 25% | 45% | +80% |
| Day 7 active | 20% | 35% | +75% |
Referred users should outperform organic users at every stage. If they don't, the referral onboarding flow needs work.
Analytics Events
// Track referral-specific onboarding events
analytics.track('referral_onboarding_start', {
referrerId: referral.referrerId,
rewardAmount: referral.rewardAmount,
matchMethod: referral.source, // 'deep_link' or 'manual_code'
});
analytics.track('referral_qualifying_action', {
referrerId: referral.referrerId,
action: 'first_purchase',
timeFromSignup: Date.now() - user.createdAt,
rewardStatus: 'pending',
});
For referral features, see Tolinku referrals. For referral program setup, see the referral docs. For onboarding use cases, see the onboarding documentation.
Get deep linking tips in your inbox
One email per week. No spam.