By the end of this lesson, you will be able to:
โน๏ธ Info Definition: Growth hacking combines marketing, analytics, and product development to rapidly scale user acquisition and retention. It's about finding creative, cost-effective ways to grow your app through systematic experimentation and data-driven optimization.
In the hyper-competitive app ecosystem, growth hacking is essential for survival:
Traditional Marketing | Growth Hacking |
---|---|
Large budgets required | Creativity over capital |
Brand awareness focused | Metrics and conversion focused |
Campaign-based | Continuous experimentation |
Marketing team only | Cross-functional approach |
Assumptions-driven | Data-driven hypotheses |
๐ก Growth Insight: The most successful apps don't just acquire users-they create experiences so compelling that users become organic growth engines themselves!
// services/GrowthEngine.ts
import AsyncStorage from '@react-native-async-storage/async-storage';
import OpenAI from 'openai';
import AnalyticsService from './AnalyticsService';
export interface GrowthExperiment {
id: string;
name: string;
hypothesis: string;
type: 'acquisition' | 'activation' | 'retention' | 'revenue' | 'referral';
status: 'draft' | 'running' | 'completed' | 'paused';
startDate: Date;
endDate?: Date;
targetMetric: string;
baselineValue: number;
targetValue: number;
actualValue?: number;
confidence: number; // 0-100
sampleSize: number;
variants: GrowthVariant[];
results?: ExperimentResults;
}
export interface GrowthVariant {
id: string;
name: string;
description: string;
allocation: number; // 0-100 percentage
conversions: number;
users: number;
conversionRate: number;
}
export interface ExperimentResults {
winner: string;
confidenceLevel: number;
improvement: number; // percentage
statistical_significance: boolean;
insights: string[];
recommendations: string[];
}
export interface UserCohort {
id: string;
name: string;
criteria: Record<string, any>;
size: number;
acquisitionDate: Date;
retention: {
day1: number;
day7: number;
day30: number;
day90: number;
};
ltv: number;
characteristics: string[];
}
class GrowthEngine {
private static instance: GrowthEngine;
private experiments: Map<string, GrowthExperiment> = new Map();
private cohorts: Map<string, UserCohort> = new Map();
private openai: OpenAI;
private analytics: AnalyticsService;
constructor(openaiApiKey: string) {
this.openai = new OpenAI({ apiKey: openaiApiKey });
this.analytics = AnalyticsService.getInstance();
}
static getInstance(openaiApiKey?: string): GrowthEngine {
if (!GrowthEngine.instance && openaiApiKey) {
GrowthEngine.instance = new GrowthEngine(openaiApiKey);
}
return GrowthEngine.instance;
}
async generateGrowthHypotheses(
currentMetrics: Record<string, number>,
targetGoals: Record<string, number>,
userFeedback: string[]
): Promise<{
hypotheses: Array<{
hypothesis: string;
type: string;
priority: 'high' | 'medium' | 'low';
expectedImpact: string;
effort: 'low' | 'medium' | 'high';
confidence: number;
testDesign: string;
}>;
quickWins: string[];
longTermStrategy: string[];
}> {
const prompt = `
Generate growth hypotheses based on current app performance:
Current Metrics:
${Object.entries(currentMetrics).map(([key, value]) => `- ${key}: ${value}`).join('\n')}
Target Goals:
${Object.entries(targetGoals).map(([key, value]) => `- ${key}: ${value}`).join('\n')}
User Feedback Themes:
${userFeedback.join('\n')}
Generate 5-8 growth hypotheses covering:
1. User acquisition improvements
2. Onboarding optimization
3. Feature adoption strategies
4. Retention mechanisms
5. Viral/referral opportunities
For each hypothesis, provide:
- Clear hypothesis statement
- Growth type (acquisition/activation/retention/revenue/referral)
- Priority level (high/medium/low)
- Expected impact description
- Implementation effort (low/medium/high)
- Confidence level (0-100)
- Basic test design
Also suggest quick wins and long-term strategy items.
Return as JSON.
`;
try {
const response = await this.openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: prompt }],
temperature: 0.4,
});
return JSON.parse(response.choices[0].message.content || '{}');
} catch (error) {
console.error('Growth hypotheses generation error:', error);
return {
hypotheses: [],
quickWins: [],
longTermStrategy: [],
};
}
}
async createExperiment(
name: string,
hypothesis: string,
type: GrowthExperiment['type'],
variants: Omit<GrowthVariant, 'conversions' | 'users' | 'conversionRate'>[],
targetMetric: string,
baselineValue: number,
targetValue: number
): Promise<string> {
const experimentId = `exp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
const experiment: GrowthExperiment = {
id: experimentId,
name,
hypothesis,
type,
status: 'draft',
startDate: new Date(),
targetMetric,
baselineValue,
targetValue,
confidence: 0,
sampleSize: 0,
variants: variants.map(v => ({
...v,
conversions: 0,
users: 0,
conversionRate: 0,
})),
};
this.experiments.set(experimentId, experiment);
await this.saveExperiment(experiment);
console.log(`Created experiment: ${name}`);
return experimentId;
}
async startExperiment(experimentId: string): Promise<void> {
const experiment = this.experiments.get(experimentId);
if (!experiment) {
throw new Error('Experiment not found');
}
experiment.status = 'running';
experiment.startDate = new Date();
await this.saveExperiment(experiment);
// Track experiment start
await this.analytics.trackEvent('experiment_started', {
experiment_id: experimentId,
experiment_name: experiment.name,
experiment_type: experiment.type,
variants_count: experiment.variants.length,
});
console.log(`Started experiment: ${experiment.name}`);
}
async recordExperimentEvent(
experimentId: string,
userId: string,
variantId: string,
eventType: 'view' | 'conversion'
): Promise<void> {
const experiment = this.experiments.get(experimentId);
if (!experiment || experiment.status !== 'running') {
return;
}
const variant = experiment.variants.find(v => v.id === variantId);
if (!variant) {
return;
}
if (eventType === 'view') {
variant.users++;
} else if (eventType === 'conversion') {
variant.conversions++;
}
// Recalculate conversion rate
variant.conversionRate = variant.users > 0 ? (variant.conversions / variant.users) * 100 : 0;
// Update sample size
experiment.sampleSize = experiment.variants.reduce((sum, v) => sum + v.users, 0);
await this.saveExperiment(experiment);
// Track event
await this.analytics.trackEvent('experiment_event', {
experiment_id: experimentId,
variant_id: variantId,
event_type: eventType,
user_id: userId,
});
}
async analyzeExperiment(experimentId: string): Promise<ExperimentResults | null> {
const experiment = this.experiments.get(experimentId);
if (!experiment) {
return null;
}
// Calculate statistical significance
const controlVariant = experiment.variants[0];
const testVariants = experiment.variants.slice(1);
let winnerVariant = controlVariant;
let maxConversionRate = controlVariant.conversionRate;
for (const variant of testVariants) {
if (variant.conversionRate > maxConversionRate) {
maxConversionRate = variant.conversionRate;
winnerVariant = variant;
}
}
// Simple statistical significance calculation (in real app, use proper statistical tests)
const improvement = ((winnerVariant.conversionRate - controlVariant.conversionRate) / controlVariant.conversionRate) * 100;
const confidenceLevel = this.calculateConfidence(controlVariant, winnerVariant);
const isStatisticallySignificant = confidenceLevel > 95 && experiment.sampleSize > 100;
// Generate AI insights
const insights = await this.generateExperimentInsights(experiment, winnerVariant, improvement);
const results: ExperimentResults = {
winner: winnerVariant.id,
confidenceLevel,
improvement,
statistical_significance: isStatisticallySignificant,
insights,
recommendations: await this.generateRecommendations(experiment, results),
};
experiment.results = results;
experiment.actualValue = winnerVariant.conversionRate;
await this.saveExperiment(experiment);
return results;
}
private calculateConfidence(control: GrowthVariant, test: GrowthVariant): number {
// Simplified confidence calculation - in production, use proper statistical tests
if (control.users < 30 || test.users < 30) return 0;
const pooledRate = (control.conversions + test.conversions) / (control.users + test.users);
const se = Math.sqrt(pooledRate * (1 - pooledRate) * ((1 / control.users) + (1 / test.users)));
if (se === 0) return 0;
const zScore = Math.abs((test.conversionRate / 100 - control.conversionRate / 100) / se);
// Convert z-score to confidence level (approximate)
if (zScore > 2.58) return 99;
if (zScore > 1.96) return 95;
if (zScore > 1.64) return 90;
if (zScore > 1.28) return 80;
return Math.round(zScore * 50);
}
private async generateExperimentInsights(
experiment: GrowthExperiment,
winner: GrowthVariant,
improvement: number
): Promise<string[]> {
const prompt = `
Analyze A/B test results and provide actionable insights:
Experiment: ${experiment.name}
Hypothesis: ${experiment.hypothesis}
Type: ${experiment.type}
Results:
- Winner: ${winner.name}
- Improvement: ${improvement.toFixed(2)}%
- Sample Size: ${experiment.sampleSize}
Variant Performance:
${experiment.variants.map(v =>
`- ${v.name}: ${v.conversionRate.toFixed(2)}% (${v.conversions}/${v.users})`
).join('\n')}
Provide 3-5 key insights about:
1. Why this variant won
2. User behavior implications
3. Broader growth opportunities
4. Potential risks or caveats
Return as array of insight strings.
`;
try {
const response = await this.openai.chat.completions.create({
model: 'gpt-3.5-turbo',
messages: [{ role: 'user', content: prompt }],
temperature: 0.3,
});
const result = JSON.parse(response.choices[0].message.content || '[]');
return Array.isArray(result) ? result : [];
} catch (error) {
console.error('Insight generation error:', error);
return ['Unable to generate detailed insights for this experiment'];
}
}
private async generateRecommendations(
experiment: GrowthExperiment,
results: ExperimentResults
): Promise<string[]> {
if (results.statistical_significance && results.improvement > 5) {
return [
`Implement the winning variant (${experiment.variants.find(v => v.id === results.winner)?.name}) globally`,
'Run follow-up experiments to optimize further',
'Apply learnings to similar features/flows',
];
} else if (results.improvement > 0 && results.improvement < 5) {
return [
'Results are promising but need larger sample size',
'Consider running the test longer',
'Test more dramatic changes for bigger impact',
];
} else {
return [
'No significant improvement detected',
'Analyze user feedback for alternative approaches',
'Consider testing completely different hypothesis',
];
}
}
async createUserCohort(
name: string,
criteria: Record<string, any>,
acquisitionDate: Date
): Promise<string> {
const cohortId = `cohort_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
// In a real app, this would query your user database
const mockCohort: UserCohort = {
id: cohortId,
name,
criteria,
size: Math.floor(Math.random() * 1000) + 100,
acquisitionDate,
retention: {
day1: 75 + Math.random() * 20,
day7: 35 + Math.random() * 15,
day30: 15 + Math.random() * 10,
day90: 8 + Math.random() * 5,
},
ltv: 25 + Math.random() * 50,
characteristics: [],
};
this.cohorts.set(cohortId, mockCohort);
await this.saveCohort(mockCohort);
return cohortId;
}
async analyzeCohortBehavior(cohortId: string): Promise<{
retentionTrends: Array<{ day: number; percentage: number }>;
behaviorPatterns: string[];
growthOpportunities: string[];
churnPredictors: string[];
}> {
const cohort = this.cohorts.get(cohortId);
if (!cohort) {
throw new Error('Cohort not found');
}
const prompt = `
Analyze user cohort behavior and identify growth opportunities:
Cohort: ${cohort.name}
Size: ${cohort.size} users
Acquisition Date: ${cohort.acquisitionDate.toDateString()}
Retention Metrics:
- Day 1: ${cohort.retention.day1.toFixed(1)}%
- Day 7: ${cohort.retention.day7.toFixed(1)}%
- Day 30: ${cohort.retention.day30.toFixed(1)}%
- Day 90: ${cohort.retention.day90.toFixed(1)}%
Average LTV: ${cohort.ltv.toFixed(2)}
Provide analysis on:
1. Key behavior patterns from retention data
2. Growth opportunities based on cohort performance
3. Potential churn predictors and early warning signs
Return as JSON with arrays for behaviorPatterns, growthOpportunities, and churnPredictors.
`;
try {
const response = await this.openai.chat.completions.create({
model: 'gpt-3.5-turbo',
messages: [{ role: 'user', content: prompt }],
temperature: 0.3,
});
const analysis = JSON.parse(response.choices[0].message.content || '{}');
const retentionTrends = [
{ day: 1, percentage: cohort.retention.day1 },
{ day: 7, percentage: cohort.retention.day7 },
{ day: 30, percentage: cohort.retention.day30 },
{ day: 90, percentage: cohort.retention.day90 },
];
return {
retentionTrends,
behaviorPatterns: analysis.behaviorPatterns || [],
growthOpportunities: analysis.growthOpportunities || [],
churnPredictors: analysis.churnPredictors || [],
};
} catch (error) {
console.error('Cohort analysis error:', error);
return {
retentionTrends: [],
behaviorPatterns: [],
growthOpportunities: [],
churnPredictors: [],
};
}
}
async predictUserChurn(userId: string, userActions: any[]): Promise<{
churnProbability: number;
riskLevel: 'low' | 'medium' | 'high';
riskFactors: string[];
interventions: string[];
}> {
// Simplified churn prediction - in production, use ML models
let churnScore = 0.1; // Base probability
const riskFactors: string[] = [];
const interventions: string[] = [];
// Analyze user behavior patterns
const recentActions = userActions.filter(action =>
new Date(action.timestamp).getTime() > Date.now() - 7 * 24 * 60 * 60 * 1000
);
if (recentActions.length < 3) {
churnScore += 0.4;
riskFactors.push('Low recent activity');
interventions.push('Send re-engagement notification');
}
if (recentActions.some(action => action.type === 'error')) {
churnScore += 0.2;
riskFactors.push('Recent app errors');
interventions.push('Provide technical support');
}
const sessionCount = recentActions.filter(a => a.type === 'session_start').length;
if (sessionCount < 2) {
churnScore += 0.3;
riskFactors.push('Infrequent app usage');
interventions.push('Offer value-driven content');
}
let riskLevel: 'low' | 'medium' | 'high' = 'low';
if (churnScore > 0.7) riskLevel = 'high';
else if (churnScore > 0.4) riskLevel = 'medium';
return {
churnProbability: Math.min(0.95, churnScore),
riskLevel,
riskFactors,
interventions,
};
}
private async saveExperiment(experiment: GrowthExperiment): Promise<void> {
try {
const experimentsData = await AsyncStorage.getItem('growth_experiments');
const experiments = experimentsData ? JSON.parse(experimentsData) : {};
experiments[experiment.id] = experiment;
await AsyncStorage.setItem('growth_experiments', JSON.stringify(experiments));
} catch (error) {
console.error('Error saving experiment:', error);
}
}
private async saveCohort(cohort: UserCohort): Promise<void> {
try {
const cohortsData = await AsyncStorage.getItem('user_cohorts');
const cohorts = cohortsData ? JSON.parse(cohortsData) : {};
cohorts[cohort.id] = cohort;
await AsyncStorage.setItem('user_cohorts', JSON.stringify(cohorts));
} catch (error) {
console.error('Error saving cohort:', error);
}
}
async getActiveExperiments(): Promise<GrowthExperiment[]> {
return Array.from(this.experiments.values()).filter(exp => exp.status === 'running');
}
async getExperimentResults(experimentId: string): Promise<ExperimentResults | null> {
const experiment = this.experiments.get(experimentId);
return experiment?.results || null;
}
async getCohorts(): Promise<UserCohort[]> {
return Array.from(this.cohorts.values());
}
}
export default GrowthEngine;
// services/ReferralService.ts
import AsyncStorage from '@react-native-async-storage/async-storage';
import { Share } from 'react-native';
import AnalyticsService from './AnalyticsService';
export interface ReferralProgram {
id: string;
name: string;
type: 'fixed' | 'percentage' | 'tiered';
reward: {
referrer: number | string;
referee: number | string;
};
conditions: {
minimumActions?: string[];
timeLimit?: number; // days
maximumRewards?: number;
};
active: boolean;
}
export interface ReferralLink {
id: string;
userId: string;
code: string;
url: string;
programId: string;
clicks: number;
conversions: number;
createdAt: Date;
expiresAt?: Date;
}
export interface ReferralReward {
id: string;
userId: string;
referralId: string;
type: 'credit' | 'discount' | 'premium' | 'physical';
value: number | string;
status: 'pending' | 'awarded' | 'redeemed';
awardedAt: Date;
redeemedAt?: Date;
}
class ReferralService {
private static instance: ReferralService;
private analytics: AnalyticsService;
private programs: Map<string, ReferralProgram> = new Map();
private links: Map<string, ReferralLink> = new Map();
private rewards: Map<string, ReferralReward> = new Map();
constructor() {
this.analytics = AnalyticsService.getInstance();
this.loadStoredData();
}
static getInstance(): ReferralService {
if (!ReferralService.instance) {
ReferralService.instance = new ReferralService();
}
return ReferralService.instance;
}
private async loadStoredData(): Promise<void> {
try {
const [programs, links, rewards] = await Promise.all([
AsyncStorage.getItem('referral_programs'),
AsyncStorage.getItem('referral_links'),
AsyncStorage.getItem('referral_rewards'),
]);
if (programs) {
const programsData = JSON.parse(programs);
Object.entries(programsData).forEach(([id, program]: [string, any]) => {
this.programs.set(id, program);
});
}
if (links) {
const linksData = JSON.parse(links);
Object.entries(linksData).forEach(([id, link]: [string, any]) => {
this.links.set(id, {
...link,
createdAt: new Date(link.createdAt),
expiresAt: link.expiresAt ? new Date(link.expiresAt) : undefined,
});
});
}
if (rewards) {
const rewardsData = JSON.parse(rewards);
Object.entries(rewardsData).forEach(([id, reward]: [string, any]) => {
this.rewards.set(id, {
...reward,
awardedAt: new Date(reward.awardedAt),
redeemedAt: reward.redeemedAt ? new Date(reward.redeemedAt) : undefined,
});
});
}
} catch (error) {
console.error('Error loading referral data:', error);
}
}
async createReferralProgram(program: Omit<ReferralProgram, 'id'>): Promise<string> {
const programId = `prog_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
const newProgram: ReferralProgram = {
id: programId,
...program,
};
this.programs.set(programId, newProgram);
await this.savePrograms();
await this.analytics.trackEvent('referral_program_created', {
program_id: programId,
program_name: program.name,
program_type: program.type,
});
return programId;
}
async generateReferralLink(userId: string, programId: string): Promise<ReferralLink> {
const program = this.programs.get(programId);
if (!program || !program.active) {
throw new Error('Referral program not found or inactive');
}
const linkId = `link_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
const referralCode = `${userId.substr(0, 4).toUpperCase()}${Math.random().toString(36).substr(2, 6).toUpperCase()}`;
const referralLink: ReferralLink = {
id: linkId,
userId,
code: referralCode,
url: `https://yourapp.com/invite/${referralCode}`,
programId,
clicks: 0,
conversions: 0,
createdAt: new Date(),
expiresAt: program.conditions.timeLimit ?
new Date(Date.now() + program.conditions.timeLimit * 24 * 60 * 60 * 1000) :
undefined,
};
this.links.set(linkId, referralLink);
await this.saveLinks();
await this.analytics.trackEvent('referral_link_generated', {
link_id: linkId,
user_id: userId,
program_id: programId,
referral_code: referralCode,
});
return referralLink;
}
async trackReferralClick(referralCode: string): Promise<void> {
const link = Array.from(this.links.values()).find(l => l.code === referralCode);
if (!link) {
console.warn('Referral link not found:', referralCode);
return;
}
// Check if link is expired
if (link.expiresAt && link.expiresAt < new Date()) {
console.warn('Referral link expired:', referralCode);
return;
}
link.clicks++;
await this.saveLinks();
await this.analytics.trackEvent('referral_click', {
referral_code: referralCode,
link_id: link.id,
referrer_id: link.userId,
});
}
async processReferralConversion(
referralCode: string,
newUserId: string,
conversionAction: string = 'signup'
): Promise<{
success: boolean;
rewards: ReferralReward[];
error?: string;
}> {
const link = Array.from(this.links.values()).find(l => l.code === referralCode);
if (!link) {
return { success: false, rewards: [], error: 'Invalid referral code' };
}
const program = this.programs.get(link.programId);
if (!program || !program.active) {
return { success: false, rewards: [], error: 'Referral program inactive' };
}
// Check if user is trying to refer themselves
if (link.userId === newUserId) {
return { success: false, rewards: [], error: 'Cannot refer yourself' };
}
// Check conditions
if (program.conditions.timeLimit && link.expiresAt && link.expiresAt < new Date()) {
return { success: false, rewards: [], error: 'Referral link expired' };
}
// Check maximum rewards
if (program.conditions.maximumRewards) {
const userRewards = Array.from(this.rewards.values()).filter(
r => r.userId === link.userId && r.status !== 'pending'
);
if (userRewards.length >= program.conditions.maximumRewards) {
return { success: false, rewards: [], error: 'Maximum rewards reached' };
}
}
// Create rewards
const rewards: ReferralReward[] = [];
// Referrer reward
if (program.reward.referrer) {
const referrerReward: ReferralReward = {
id: `reward_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
userId: link.userId,
referralId: link.id,
type: 'credit',
value: program.reward.referrer,
status: 'pending',
awardedAt: new Date(),
};
this.rewards.set(referrerReward.id, referrerReward);
rewards.push(referrerReward);
}
// Referee reward
if (program.reward.referee) {
const refereeReward: ReferralReward = {
id: `reward_${Date.now() + 1}_${Math.random().toString(36).substr(2, 9)}`,
userId: newUserId,
referralId: link.id,
type: 'credit',
value: program.reward.referee,
status: 'pending',
awardedAt: new Date(),
};
this.rewards.set(refereeReward.id, refereeReward);
rewards.push(refereeReward);
}
// Update link conversion count
link.conversions++;
await Promise.all([
this.saveRewards(),
this.saveLinks(),
]);
// Track conversion
await this.analytics.trackEvent('referral_conversion', {
referral_code: referralCode,
referrer_id: link.userId,
referee_id: newUserId,
program_id: link.programId,
conversion_action: conversionAction,
rewards_count: rewards.length,
});
return { success: true, rewards };
}
async awardPendingRewards(userId: string, completedAction: string): Promise<ReferralReward[]> {
const pendingRewards = Array.from(this.rewards.values()).filter(
r => r.userId === userId && r.status === 'pending'
);
const awardedRewards: ReferralReward[] = [];
for (const reward of pendingRewards) {
const link = this.links.get(reward.referralId);
const program = link ? this.programs.get(link.programId) : null;
if (!program) continue;
// Check if conditions are met
const conditionsMet = !program.conditions.minimumActions ||
program.conditions.minimumActions.includes(completedAction);
if (conditionsMet) {
reward.status = 'awarded';
awardedRewards.push(reward);
await this.analytics.trackEvent('referral_reward_awarded', {
reward_id: reward.id,
user_id: userId,
reward_type: reward.type,
reward_value: reward.value,
trigger_action: completedAction,
});
}
}
if (awardedRewards.length > 0) {
await this.saveRewards();
}
return awardedRewards;
}
async shareReferralLink(referralLink: ReferralLink, customMessage?: string): Promise<boolean> {
try {
const defaultMessage = `Hey! I've been using this awesome app and thought you'd love it too. Join me and we both get rewards! ${referralLink.url}`;
const message = customMessage || defaultMessage;
const result = await Share.share({
message,
url: referralLink.url,
title: 'Join me on this amazing app!',
});
if (result.action === Share.sharedAction) {
await this.analytics.trackEvent('referral_shared', {
link_id: referralLink.id,
user_id: referralLink.userId,
share_method: result.activityType || 'unknown',
});
return true;
}
return false;
} catch (error) {
console.error('Share error:', error);
return false;
}
}
async getReferralStats(userId: string): Promise<{
totalRewards: number;
pendingRewards: number;
totalReferrals: number;
successfulReferrals: number;
clickThrough: number;
conversionRate: number;
}> {
const userLinks = Array.from(this.links.values()).filter(l => l.userId === userId);
const userRewards = Array.from(this.rewards.values()).filter(r => r.userId === userId);
const totalClicks = userLinks.reduce((sum, link) => sum + link.clicks, 0);
const totalConversions = userLinks.reduce((sum, link) => sum + link.conversions, 0);
return {
totalRewards: userRewards.filter(r => r.status === 'awarded').length,
pendingRewards: userRewards.filter(r => r.status === 'pending').length,
totalReferrals: totalClicks,
successfulReferrals: totalConversions,
clickThrough: totalClicks,
conversionRate: totalClicks > 0 ? (totalConversions / totalClicks) * 100 : 0,
};
}
private async savePrograms(): Promise<void> {
try {
const programsData = Object.fromEntries(this.programs.entries());
await AsyncStorage.setItem('referral_programs', JSON.stringify(programsData));
} catch (error) {
console.error('Error saving referral programs:', error);
}
}
private async saveLinks(): Promise<void> {
try {
const linksData = Object.fromEntries(this.links.entries());
await AsyncStorage.setItem('referral_links', JSON.stringify(linksData));
} catch (error) {
console.error('Error saving referral links:', error);
}
}
private async saveRewards(): Promise<void> {
try {
const rewardsData = Object.fromEntries(this.rewards.entries());
await AsyncStorage.setItem('referral_rewards', JSON.stringify(rewardsData));
} catch (error) {
console.error('Error saving referral rewards:', error);
}
}
async generateViralContent(contentType: 'achievement' | 'milestone' | 'score', data: any): Promise<{
title: string;
message: string;
imageUrl?: string;
hashtags: string[];
shareUrl: string;
}> {
// Generate shareable content based on user achievements
const shareId = `share_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
let title = '';
let message = '';
let hashtags: string[] = [];
switch (contentType) {
case 'achievement':
title = `๐ I just unlocked ${data.achievementName}!`;
message = `Just achieved ${data.achievementName} in the app! ${data.description}`;
hashtags = ['#Achievement', '#Success', '#AppName'];
break;
case 'milestone':
title = `๐ Milestone reached: ${data.milestone}!`;
message = `I've reached ${data.milestone} ${data.metric}! Join me on this journey.`;
hashtags = ['#Milestone', '#Progress', '#AppName'];
break;
case 'score':
title = `๐ New high score: ${data.score}!`;
message = `Just scored ${data.score} points! Think you can beat it?`;
hashtags = ['#HighScore', '#Challenge', '#AppName'];
break;
}
return {
title,
message,
imageUrl: `https://yourapp.com/share/${shareId}.png`,
hashtags,
shareUrl: `https://yourapp.com/share/${shareId}`,
};
}
}
export default ReferralService;
In this lesson, you learned:
Code with AI: Try building these advanced growth features.
Prompts to try:
Growth hacking is about creating systematic, repeatable processes that turn every user into a potential growth engine. Focus on providing genuine value, and the growth will follow naturally!
๐ Congratulations! You've completed all 20 lessons of the M1-Mobile Apps I Love course. You now have the complete toolkit to build, launch, and scale mobile apps that users genuinely love. From rapid prototyping to growth hacking, you've learned the entire journey of creating successful mobile applications with AI-powered development workflows.
Remember: The best apps aren't just technically excellent-they solve real problems, provide genuine value, and create experiences that users can't help but share with others. Now go build something amazing!