Setup and context: The Reality of Indie App Monetization
If you've started building apps with Rork and are now thinking about monetization, you're at an exciting inflection point. Turning an app into a meaningful revenue stream is entirely achievable as an indie developer — but it doesn't happen by accident.
The common mistake is to build the app first and bolt on monetization later. The most successful indie apps treat revenue generation as a first-class design concern from the very beginning. This guide walks you through exactly how to do that with Rork.
The author has been building apps independently since 2014 and has achieved AdMob revenue exceeding ¥1.5 million per month at its peak. The strategies in this guide are grounded in real-world experience.
Choosing Your Revenue Model: Three Core Patterns
Before writing a line of code, you need to choose a monetization model that fits your app. Each pattern has distinct trade-offs.
Model 1: Ad Revenue (AdMob)
How it works: Offer the app free; earn revenue through ad impressions and clicks.
Best for:
- Habit and utility apps used daily (trackers, notes, converters)
- Casual games, especially hypercasual
- Tool apps (calculators, weather, file utilities)
Typical eCPM benchmarks (Japan / iOS):
- Banner ads: ¥100–¥400
- Interstitial ads: ¥500–¥2,000
- Rewarded ads: ¥1,000–¥5,000
Design principle: Place ads at natural "pause points" in the user flow. Interrupting active tasks causes churn.
Model 2: Subscriptions
How it works: Charge a recurring monthly or annual fee for premium access.
Best for:
- Apps with continuously updated content (news, learning, fitness)
- Apps offering cloud sync or backup
- Apps with tiered feature access
Typical pricing (Japan market):
- Monthly: ¥150–¥600
- Annual: ¥1,200–¥3,000 (priced as a discount vs. monthly)
Design principle: A free trial (7–14 days) and a prominent annual plan significantly improve conversion rates.
Model 3: One-Time In-App Purchases
How it works: Users pay once to unlock specific features or content.
Best for:
- Feature unlocks (ad removal, additional themes)
- Digital content packs (wallpapers, stickers, fonts)
- Game items and level packs
Design principle: Simple, clear value propositions convert best. "Remove ads for ¥250" outperforms complex feature bundles.
Designing for Monetization in Rork: Architecture First
The most critical insight is this: build monetization into your architecture from the start. Retrofitting it later is significantly more painful.
Prompting Rork for Monetization-Ready Architecture
Here's how to prompt Rork to generate a monetization-ready app skeleton:
Build a wallpaper app with the following monetization structure:
[Feature Design]
- Free users: Download wallpapers after watching a rewarded ad
- Premium users (¥200/month): No ads, all categories unlocked, high-res downloads
[AdMob Configuration]
- Banner ad: Persistent at the bottom of the home screen
- Interstitial ad: Show once every 5 downloads
- Rewarded ad: "Watch ad to download free" button
[Subscription Flow]
- RevenueCat SDK for App Store / Google Play subscriptions
- 7-day free trial
- Push notification reminder before trial ends
Tech stack: React Native + Expo, AdMob, RevenueCat
Integrating RevenueCat for Subscription Management
RevenueCat is the best choice for subscription management in React Native apps. It handles both App Store and Google Play, provides a clean analytics dashboard, and integrates cleanly with Rork-generated code.
// Initialize RevenueCat (App.tsx)
import Purchases from "react-native-purchases";
export default function App() {
useEffect(() => {
const apiKey = Platform.OS === "ios"
? "YOUR_REVENUECAT_IOS_KEY"
: "YOUR_REVENUECAT_ANDROID_KEY";
Purchases.configure({ apiKey });
}, []);
}// Subscription purchase flow
async function purchaseSubscription() {
try {
const offerings = await Purchases.getOfferings();
const monthly = offerings.current?.monthly;
if (!monthly) throw new Error("No plan available");
const { customerInfo } = await Purchases.purchasePackage(monthly);
if (customerInfo.activeSubscriptions.length > 0) {
setPremiumUser(true);
}
} catch (error) {
if (!error.userCancelled) {
Alert.alert("Purchase Error", error.message);
}
}
}Adding AdMob to Rork-Generated Code
// Banner ad component
import { BannerAd, BannerAdSize } from "react-native-google-mobile-ads";
function BottomBannerAd({ isPremium }: { isPremium: boolean }) {
if (isPremium) return null; // Hide for paying users
return (
<BannerAd
unitId="ca-app-pub-XXXXXXXXXXXXXXXX/XXXXXXXXXX"
size={BannerAdSize.ANCHORED_ADAPTIVE_BANNER}
requestOptions={{ requestNonPersonalizedAdsOnly: false }}
/>
);
}// Rewarded ad (watch to unlock download)
import { RewardedAd, RewardedAdEventType } from "react-native-google-mobile-ads";
async function watchAdAndDownload(wallpaperId: string) {
const rewarded = RewardedAd.createForAdRequest(
"ca-app-pub-XXXXXXXXXXXXXXXX/XXXXXXXXXX"
);
return new Promise<void>((resolve, reject) => {
rewarded.addAdEventListener(RewardedAdEventType.LOADED, () => {
rewarded.show();
});
rewarded.addAdEventListener(RewardedAdEventType.EARNED_REWARD, (reward) => {
console.log(`Reward earned: ${reward.amount} ${reward.type}`);
resolve();
});
rewarded.addAdEventListener(RewardedAdEventType.CLOSED, () => {
reject(new Error("ad_closed_without_reward"));
});
rewarded.load();
});
}Maximizing AdMob Revenue: Design Strategies
The Golden Rules of Ad Placement
Rule 1: Place ads at natural task completion moments
The best time to show an ad is immediately after the user completes an action:
- After app launch (startup interstitial)
- After downloading or saving content
- After clearing a game stage
- After applying a settings change
Rule 2: Apply the "Rule of 5" for interstitials
Show interstitial (full-screen) ads approximately once every 5 user actions. Higher frequency drives uninstalls.
const AD_FREQUENCY = 5;
let actionCount = 0;
function onUserAction() {
actionCount++;
if (actionCount % AD_FREQUENCY === 0) {
showInterstitialAd();
}
}Rule 3: Frame rewarded ads as a choice
Always offer two paths: "Watch an ad to use for free" vs. "Upgrade to remove all ads." Giving users agency reduces resistance to ads and builds goodwill toward the premium upgrade.
Boosting eCPM
Practical tactics for improving your cost-per-thousand rate:
- Enable mediation: AdMob's mediation feature pits multiple ad networks against each other in real time. Teams that enable it typically see 20–40% eCPM improvement.
- A/B test ad formats: Experiment with different ad formats (interstitial vs. rewarded, different banner sizes) to find what earns most with the least user friction.
- Segment your audience: High-value users (long session length, high engagement) respond better to interactive and video ad formats.
Improving Subscription Conversion Rates
Three Principles for Paywall Design
Principle 1: Deliver real free value first, then ask
The subscription pitch works best after users have experienced enough of the app to care about keeping it. Don't interrupt first-time users with a paywall before they've understood the app's value.
Principle 2: Make the annual plan the hero
Price your annual plan at 30–50% less per month than the monthly plan, and make it visually prominent in your UI. Annual subscribers churn far less frequently and have dramatically higher lifetime value.
Principle 3: Be specific about benefits
"Upgrade to Premium" is abstract and easy to dismiss. "Remove all ads, download in 4K resolution, and access 500+ wallpapers across all categories" is concrete and compelling.
function PaywallScreen({ onDismiss, onPurchase }) {
return (
<View style={styles.container}>
<Text style={styles.title}>Upgrade Your Experience</Text>
<View style={styles.benefits}>
{[
{ icon: "🚫", text: "Remove all ads" },
{ icon: "📱", text: "4K high-resolution downloads" },
{ icon: "🖼️", text: "500+ wallpapers across all categories" },
{ icon: "☁️", text: "Cloud sync & backup" },
].map((benefit) => (
<BenefitRow key={benefit.text} {...benefit} />
))}
</View>
{/* Lead with annual plan */}
<PlanCard
title="Annual Plan — ¥1,200/year"
subtitle="¥100/month — Save 40%"
badge="Best Value"
onPress={() => onPurchase("annual")}
highlighted
/>
<PlanCard
title="Monthly Plan — ¥200/month"
onPress={() => onPurchase("monthly")}
/>
<Text style={styles.footer}>
7-day free trial. Cancel anytime.
</Text>
<TouchableOpacity onPress={onDismiss}>
<Text style={styles.dismissText}>Maybe later</Text>
</TouchableOpacity>
</View>
);
}Trial Reminder Notifications
Well-timed reminders before a trial ends are one of the highest-leverage conversion tactics available:
const trialNotifications = [
{
daysBeforeEnd: 3,
title: "Your Premium trial ends in 3 days",
body: "Enjoying the experience? Keep it going with a subscription.",
},
{
daysBeforeEnd: 1,
title: "Last day of your free trial",
body: "Upgrade now to keep access at ¥1,200/year.",
},
];Analytics-Driven Improvement
KPIs to Track
- DAU (Daily Active Users): Your core growth metric
- ARPDAU (Avg Revenue Per Daily Active User): Revenue efficiency per engaged user
- Ad eCPM: Revenue per 1,000 impressions
- Subscription conversion rate: Free trial starts → paying subscribers
- Monthly churn rate: Percentage of subscribers cancelling each month
- LTV (Lifetime Value): Expected total revenue per subscriber
Firebase Analytics Integration
import analytics from "@react-native-firebase/analytics";
async function logAdView(adType: "banner" | "interstitial" | "rewarded") {
await analytics().logEvent("ad_impression", {
ad_type: adType,
screen: currentScreen,
});
}
async function logPurchase(plan: "monthly" | "annual", price: number) {
await analytics().logPurchase({
currency: "JPY",
value: price,
items: [{ item_id: `subscription_${plan}`, item_name: `${plan} subscription` }],
});
}Troubleshooting Common Issues
Issue 1: AdMob Ads Not Showing
Symptom: No ads appear in the production app
Fix: Verify you've replaced test ad unit IDs with production IDs. Check that googleMobileAdsAppId is correctly set in app.json. Note that ads can be restricted for up to 24–72 hours after initial App Store / Google Play approval.
Issue 2: RevenueCat Purchase Not Unlocking Features
Symptom: Payment completes successfully but premium features don't unlock
Fix: Confirm Purchases.restorePurchases() is implemented. Check that your sandbox and production API keys are configured correctly. Verify that the Entitlement ID in customerInfo.entitlements.active exactly matches what's configured in your RevenueCat dashboard.
Issue 3: Subscription Review Rejection
Symptom: App Store review rejects your subscription implementation
Fix: Ensure your app includes clear cancellation instructions in-app and in metadata. Implement the "Restore Purchases" button — Apple requires it. Include links to Terms of Service and Privacy Policy on your paywall screen.
Conclusion
Here are the core principles for monetizing Rork apps effectively:
- Design for monetization from the start: Build your revenue architecture into the initial structure, not as an afterthought
- Place AdMob ads at natural task completion moments: Respect user flow to minimize churn from ad friction
- Lead with your annual subscription plan: Higher LTV, lower churn — the annual plan is your most valuable subscription tier
- Use RevenueCat for unified purchase management: Cross-platform, analytics-ready, and the industry standard for indie developers
- Track KPIs and improve continuously: DAU, ARPDAU, conversion rate — let the data drive your decisions
Consistent, meaningful revenue from indie apps is achievable. Rork dramatically compresses the development timeline, which means you can reach monetization testing much faster than traditional development. Use that advantage to run experiments, iterate on your paywall design, and compound improvements over time.