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

Onboarding for Freemium Apps: Free to Paid Journey

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

Freemium onboarding has a dual goal: get the user to experience enough value to stay (activation) and expose them to premium features that make upgrading appealing (conversion). Push the upgrade too early and users churn before they understand the product. Wait too long and users get comfortable with the free tier and never see a reason to pay.

For improving completion rates, see Improving Onboarding Completion Rates. For marketplace app onboarding, see Onboarding for Marketplace Apps: Two-Sided Approach. For general onboarding principles, see Onboarding Best Practices for Mobile Apps in 2026.

The Freemium Onboarding Spectrum

Different freemium models require different onboarding approaches:

Model Free Tier Premium Tier Onboarding Goal
Feature-gated Core features free Advanced features paid Show core value, tease advanced
Usage-limited 5 projects, 100MB Unlimited Let them hit the limit naturally
Time-limited trial All features for 14 days Same features, paid Maximize feature exposure in trial
Ad-supported Full features with ads Ad-free Let ads create natural upgrade motivation
Tiered service Basic quality Premium quality Show the quality difference

Onboarding Flow Design

Phase 1: Value First (Sessions 1-3)

The first few sessions should focus entirely on getting the user to experience core value. No upgrade prompts, no premium teasers, no pricing pages.

function FreeOnboarding({ user }) {
  return (
    <View>
      <WelcomeScreen
        headline="Welcome to [App]"
        // No mention of premium or pricing
      />

      <CoreFeatureSetup />

      <FirstActionPrompt
        title="Create your first project"
        description="Start with a template or create from scratch."
      />
    </View>
  );
}

Why: Users who activate on the free tier convert at 3-5x the rate of users who see a paywall before experiencing value. Let them fall in love with the product first. For subscription-specific conversion tactics, see Onboarding for Subscription Apps.

Phase 2: Premium Awareness (Sessions 4-7)

After the user has experienced core value, start showing what premium offers:

function PremiumAwarenessPrompts({ user }) {
  // Only show after activation
  if (user.hasActivated === false) return null;

  // Show when the user naturally encounters a premium boundary
  return (
    <PremiumBadge
      feature="advanced_analytics"
      text="Upgrade to see detailed analytics"
      onLearnMore={() => navigation.navigate('PremiumInfo')}
    />
  );
}

Phase 3: Conversion Opportunity (Sessions 8+)

Present the upgrade as a solution to a problem the user now has:

function UpgradePrompt({ user, trigger }) {
  const prompts = {
    storage_limit: {
      title: 'You are running out of space',
      body: `You've used ${user.storageUsed} of ${user.storageLimit}. Upgrade for unlimited storage.`,
    },
    feature_attempt: {
      title: 'This is a Premium feature',
      body: 'Unlock advanced analytics, team collaboration, and more.',
    },
    usage_limit: {
      title: `You've created ${user.projectCount} of ${user.projectLimit} projects`,
      body: 'Upgrade to create unlimited projects.',
    },
  };

  const prompt = prompts[trigger];

  return (
    <UpgradeCard>
      <Heading>{prompt.title}</Heading>
      <Text>{prompt.body}</Text>
      <Button onPress={() => navigation.navigate('Pricing')}>
        See Plans
      </Button>
      <LinkButton onPress={dismiss}>Not Now</LinkButton>
    </UpgradeCard>
  );
}

Premium Feature Exposure

The "Taste" Pattern

Let free users try premium features briefly so they understand the value:

const PREMIUM_TASTES = {
  advanced_analytics: {
    freeUsesAllowed: 3,
    message: 'You have 2 free views of Advanced Analytics remaining.',
    upgradeMessage: 'You have used all free views. Upgrade to access anytime.',
  },
  export_pdf: {
    freeUsesAllowed: 1,
    message: 'Try exporting as PDF. This is a Premium feature.',
    upgradeMessage: 'PDF export is a Premium feature. Upgrade to export unlimited PDFs.',
  },
  ai_suggestions: {
    freeUsesAllowed: 5,
    message: 'AI Suggestions: 4 free uses remaining this month.',
    upgradeMessage: 'Upgrade for unlimited AI suggestions.',
  },
};

async function checkPremiumAccess(userId, feature) {
  const user = await getUser(userId);

  if (user.isPremium) return { allowed: true };

  const taste = PREMIUM_TASTES[feature];
  if (taste === undefined) return { allowed: false, reason: 'premium_only' };

  const usesThisMonth = await getPremiumFeatureUses(userId, feature);

  if (usesThisMonth < taste.freeUsesAllowed) {
    return {
      allowed: true,
      message: taste.message.replace(
        /\d+ free/,
        `${taste.freeUsesAllowed - usesThisMonth - 1} free`
      ),
      remaining: taste.freeUsesAllowed - usesThisMonth - 1,
    };
  }

  return {
    allowed: false,
    message: taste.upgradeMessage,
    reason: 'taste_exhausted',
  };
}

Visual Premium Indicators

Mark premium features clearly but not intrusively:

function FeatureItem({ feature, isPremium, isUnlocked }) {
  return (
    <Row>
      <Icon name={feature.icon} />
      <Text>{feature.name}</Text>
      {isPremium && isUnlocked === false && (
        <PremiumBadge size="small" />
      )}
    </Row>
  );
}

Premium features should be visible in navigation and feature lists. Users should know what they're missing without feeling locked out. For techniques on introducing features gradually rather than all at once, see Progressive Onboarding: Gradual Feature Introduction.

Use deep links in emails and push notifications to drive upgrades:

async function sendUpgradeEmail(userId, trigger) {
  const deepLink = await Tolinku.createLink({
    path: '/upgrade',
    params: {
      source: 'email',
      trigger: trigger,
      promo: getActivePromo(),
    },
  });

  await sendEmail(userId, {
    template: 'upgrade_prompt',
    data: {
      trigger,
      deepLink: deepLink.url,
      promoCode: getActivePromo(),
    },
  });
}
function handleUpgradeDeepLink(params) {
  analytics.track('upgrade_deep_link_opened', {
    source: params.source,
    trigger: params.trigger,
    promo: params.promo,
  });

  navigation.navigate('Pricing', {
    highlightPlan: 'premium',
    promoCode: params.promo,
    returnScreen: params.return_to,
  });
}

For users who tried premium features and didn't upgrade:

async function sendWinBackPush(userId) {
  const mostUsedPremiumFeature = await getMostUsedPremiumTaste(userId);

  await sendPush(userId, {
    title: `Miss ${mostUsedPremiumFeature.name}?`,
    body: 'Upgrade today and get your first month at 50% off.',
    data: {
      deepLink: `/upgrade?promo=WINBACK50&feature=${mostUsedPremiumFeature.id}`,
    },
  });
}

Trial Onboarding

Starting a Trial

If your freemium model includes a free trial:

function TrialOnboarding({ trialDays }) {
  return (
    <View>
      <WelcomeScreen
        headline={`Your ${trialDays}-day free trial starts now`}
        subtext="All Premium features are unlocked. No credit card needed."
      />

      <TrialChecklist
        items={[
          { label: 'Try Advanced Analytics', screen: '/analytics' },
          { label: 'Export a PDF report', screen: '/export' },
          { label: 'Invite a team member', screen: '/team/invite' },
          { label: 'Set up automations', screen: '/automations' },
        ]}
      />

      <AccountCreation />
    </View>
  );
}

Trial Countdown Notifications

const trialNotifications = [
  {
    daysRemaining: 7,
    title: '7 days left in your trial',
    body: 'Have you tried [feature]? It is one of our most popular Premium features.',
    deepLink: '/feature/popular',
  },
  {
    daysRemaining: 3,
    title: '3 days left',
    body: 'Upgrade now to keep all your Premium features.',
    deepLink: '/upgrade',
  },
  {
    daysRemaining: 1,
    title: 'Trial ends tomorrow',
    body: 'Upgrade to Premium to keep your advanced features and data.',
    deepLink: '/upgrade?urgency=high',
  },
  {
    daysRemaining: 0,
    title: 'Your trial has ended',
    body: 'Upgrade anytime to restore your Premium features.',
    deepLink: '/upgrade?post_trial=true',
  },
];

Measuring Freemium Onboarding

Conversion Funnel

Stage Metric Benchmark
Install to activation Free user completes first action 40-60%
Activation to premium awareness Free user encounters premium feature 60-80%
Premium awareness to trial/upgrade Free user starts trial or views pricing 10-20%
Trial to paid Trial user converts to paid 15-30%
Free to paid (overall) Install to paid conversion 2-5%

Time-Based Analysis

async function conversionTimingAnalysis() {
  const conversions = await getPaidConversions({ last: '90_days' });

  const timings = conversions.map(c => ({
    daysToConvert: daysBetween(c.signupDate, c.conversionDate),
    trigger: c.conversionTrigger,
    tastes: c.premiumTastesUsed,
  }));

  console.log('Median days to convert:', median(timings.map(t => t.daysToConvert)));
  console.log('Most common trigger:', mode(timings.map(t => t.trigger)));
  console.log('Avg premium tastes before converting:', average(timings.map(t => t.tastes)));
}

Key Insights to Track

  • Taste-to-convert rate: Users who tried premium features are X% more likely to upgrade
  • Optimal taste count: How many premium feature uses before conversion peaks
  • Trigger analysis: Which limit/feature drives the most conversions
  • Trial extension impact: Does offering an extended trial increase or decrease conversions

For deep linking features, see Tolinku deep linking. 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.