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.
Deep Links for Conversion
Campaign-Specific Upgrade Links
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(),
},
});
}
Handling Upgrade Deep Links
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,
});
}
Win-Back Deep Links
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.