Skip to content
Tolinku
Tolinku
Sign In Start Free
Use Cases · · 7 min read

Onboarding Referred Users: Best Practices

By Tolinku Staff
|
Tolinku fintech deep linking dashboard screenshot for use cases blog posts

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

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.

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.

Ready to add deep linking to your app?

Set up Universal Links, App Links, deferred deep linking, and analytics in minutes. Free to start.