◉RORK LABJP
●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SDK 58 — Beta since 09/15 with no stable date yet; running projects in Expo Go has required login since 09/03●WIDGET — A write-up traces an iOS widget that renders black only in production builds●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SDK 58 — Beta since 09/15 with no stable date yet; running projects in Expo Go has required login since 09/03●WIDGET — A write-up traces an iOS widget that renders black only in production builds●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…
Articles/Business
⟐ Business/2026-03-22Advanced

Automate In-App Recommendation Revenue with Rork × AI Agents — Personalized Billing Strategy Guide

Build an AI-powered recommendation engine for your Rork app that automatically generates personalized billing offers per user. Includes behavior tracking, Gemini-based agent logic, and React Native implementation.

Rork585AI agents5recommendationsauto-monetizationpersonalizationStripe18app revenue

Recommendations × AI Agents = Automated Revenue Maximization

In app monetization, showing "the right offer to the right user at the right time" is both the most important and most challenging problem. Traditional rule-based approaches (showing everyone the same ad, sending a discount after 7 days) can't adapt to diverse user behavior patterns.

AI agents change this equation. They analyze user behavior data in real time and automatically generate individualized billing offers. This article details the design and implementation of a personalized recommendation revenue engine for Rork apps.

How the Personalized Revenue Engine Works

Three Core Components

  1. Behavior Analysis Engine — Tracks and scores in-app user behavior
  2. Recommendation AI Agent — Generates optimal offers based on behavior data
  3. Billing Execution Layer — Integrates with Stripe to present offers and process payments

Data Flow

User behavior → Analysis → AI agent decision → Recommendation displayed
     ↑                                              ↓
     └────────── Result feedback ←──── Purchase/dismiss outcome

Implementing the Behavior Analysis Engine

// services/behavior-tracker.ts
// User behavior analysis engine
interface UserBehavior {
  userId: string;
  sessionCount: number;
  avgSessionDuration: number;        // seconds
  featuresUsed: string[];
  lastActiveAt: Date;
  purchaseHistory: {
    amount: number;
    date: Date;
    product: string;
  }[];
  premiumFeatureAttempts: number;     // premium feature tap count
  referralCount: number;
}
 
interface EngagementScore {
  overall: number;          // 0-100
  purchaseIntent: number;   // 0-100
  churnRisk: number;        // 0-100
  optimalTiming: string;    // best moment to show recommendation
}
 
function calculateEngagementScore(
  behavior: UserBehavior
): EngagementScore {
  // Calculate engagement score
  const sessionScore = Math.min(behavior.sessionCount * 2, 30);
  const durationScore = Math.min(behavior.avgSessionDuration / 60 * 5, 20);
  const featureScore = Math.min(behavior.featuresUsed.length * 3, 20);
  const premiumScore = Math.min(behavior.premiumFeatureAttempts * 10, 30);
 
  const overall = sessionScore + durationScore + featureScore + premiumScore;
 
  // Purchase intent (higher with more premium feature taps)
  const purchaseIntent = Math.min(
    behavior.premiumFeatureAttempts * 15 +
    (behavior.sessionCount > 10 ? 20 : 0) +
    (behavior.avgSessionDuration > 300 ? 15 : 0),
    100
  );
 
  // Churn risk (based on days since last activity)
  const daysSinceActive = Math.floor(
    (Date.now() - behavior.lastActiveAt.getTime()) / 86400000
  );
  const churnRisk = Math.min(daysSinceActive * 10, 100);
 
  // Optimal timing
  let optimalTiming = "session_end";  // default
  if (purchaseIntent > 70) {
    optimalTiming = "premium_feature_tap";  // high intent → offer immediately
  } else if (purchaseIntent > 40) {
    optimalTiming = "session_mid";  // moderate → mid-session
  }
 
  return { overall, purchaseIntent, churnRisk, optimalTiming };
}
 
// Usage example
const score = calculateEngagementScore({
  userId: "user_123",
  sessionCount: 15,
  avgSessionDuration: 420,
  featuresUsed: ["search", "favorites", "share", "compare"],
  lastActiveAt: new Date(),
  purchaseHistory: [],
  premiumFeatureAttempts: 5,
  referralCount: 2
});
console.log(score);
// Expected output:
// {
//   overall: 82,
//   purchaseIntent: 75,
//   churnRisk: 0,
//   optimalTiming: "premium_feature_tap"
// }

AI Agent Recommendation Generation

// services/recommendation-agent.ts
// AI agent for personalized recommendations
import { GoogleGenerativeAI } from "@google/generative-ai";
 
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY!);
const model = genAI.getGenerativeModel({ model: "gemini-2.5-pro" });
 
interface Recommendation {
  type: "subscription" | "one_time" | "upgrade" | "retention";
  plan: string;
  message_ja: string;
  message_en: string;
  discount?: number;
  urgency: "low" | "medium" | "high";
  displayTiming: string;
}
 
async function generateRecommendation(
  behavior: UserBehavior,
  score: EngagementScore
): Promise<Recommendation> {
  const prompt = `You are a mobile app revenue optimization agent.
Generate the optimal billing recommendation based on this user data.
 
User data:
- Sessions: ${behavior.sessionCount}
- Avg session duration: ${behavior.avgSessionDuration}s
- Features used: ${behavior.featuresUsed.join(", ")}
- Premium feature taps: ${behavior.premiumFeatureAttempts}
- Purchase history: ${behavior.purchaseHistory.length} items
- Referrals: ${behavior.referralCount}
 
Scores:
- Engagement: ${score.overall}/100
- Purchase intent: ${score.purchaseIntent}/100
- Churn risk: ${score.churnRisk}/100
- Optimal timing: ${score.optimalTiming}
 
Available plans:
- Tip: $1.50 (one-time)
- Pro monthly: $3
- Premium lifetime: $10
 
Respond in this JSON format:
{
  "type": "subscription" | "one_time" | "upgrade" | "retention",
  "plan": "plan name",
  "message_ja": "Japanese recommendation (under 50 chars)",
  "message_en": "English recommendation (under 50 words)",
  "discount": 0-30,
  "urgency": "low" | "medium" | "high",
  "displayTiming": "when to show"
}`;
 
  const response = await model.generateContent(prompt);
  const text = response.response.text();
 
  const jsonMatch = text.match(/\{[\s\S]*\}/);
  if (!jsonMatch) throw new Error("Failed to parse recommendation");
  return JSON.parse(jsonMatch[0]);
}
 
// Expected output:
// {
//   "type": "subscription",
//   "plan": "Pro monthly",
//   "message_en": "Unlock unlimited favorites with Pro — 20% off today",
//   "message_ja": "お気に入り機能を無制限で使えるProプラン、今なら20%オフ",
//   "discount": 20,
//   "urgency": "high",
//   "displayTiming": "premium_feature_tap"
// }

Displaying Recommendations in the Rork App

// components/SmartOffer.tsx
// AI-generated recommendation display component
import React, { useEffect, useState } from 'react';
import {
  View, Text, TouchableOpacity,
  Animated, StyleSheet
} from 'react-native';
 
interface OfferProps {
  userId: string;
  currentScreen: string;
  trigger: "session_end" | "premium_feature_tap" | "session_mid";
}
 
export default function SmartOffer({
  userId, currentScreen, trigger
}: OfferProps) {
  const [offer, setOffer] = useState<any>(null);
  const [visible, setVisible] = useState(false);
  const fadeAnim = useState(new Animated.Value(0))[0];
 
  useEffect(() => {
    fetchOffer();
  }, [trigger]);
 
  const fetchOffer = async () => {
    try {
      const res = await fetch(
        'https://api.your-app.com/recommendations',
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer TOKEN'
          },
          body: JSON.stringify({ userId, currentScreen, trigger }),
        }
      );
      const data = await res.json();
      if (data.recommendation) {
        setOffer(data.recommendation);
        setVisible(true);
        Animated.timing(fadeAnim, {
          toValue: 1,
          duration: 300,
          useNativeDriver: true,
        }).start();
      }
    } catch (e) {
      // Silent fail — don't disrupt UX for recommendation errors
    }
  };
 
  if (!visible || !offer) return null;
 
  return (
    <Animated.View style={[styles.container, { opacity: fadeAnim }]}>
      <Text style={styles.title}>{offer.message_en}</Text>
      {offer.discount > 0 && (
        <Text style={styles.discount}>{offer.discount}% OFF</Text>
      )}
      <TouchableOpacity
        style={styles.button}
        onPress={() => {
          // Navigate to Stripe Checkout
          // handlePurchase(offer.plan, offer.discount);
        }}
      >
        <Text style={styles.buttonText}>Learn More</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={() => setVisible(false)}>
        <Text style={styles.dismiss}>Maybe Later</Text>
      </TouchableOpacity>
    </Animated.View>
  );
}
 
const styles = StyleSheet.create({
  container: {
    position: 'absolute', bottom: 20, left: 16, right: 16,
    backgroundColor: '#FFF', borderRadius: 16, padding: 20,
    shadowColor: '#000', shadowOpacity: 0.15, shadowRadius: 10,
    elevation: 5,
  },
  title: { fontSize: 16, fontWeight: '600', marginBottom: 8 },
  discount: {
    fontSize: 24, fontWeight: 'bold', color: '#E91E63',
    marginBottom: 12
  },
  button: {
    backgroundColor: '#2196F3', padding: 14, borderRadius: 10,
    alignItems: 'center',
  },
  buttonText: { color: '#FFF', fontSize: 16, fontWeight: '600' },
  dismiss: {
    textAlign: 'center', color: '#999', marginTop: 12, fontSize: 14,
  },
});

Measurement and Feedback Loops

To continuously improve recommendations, feed outcome data back to the AI agent. Track click-through rates, purchase rates, and dismissal rates for every offer. Include this history in the next recommendation prompt, allowing the agent to learn patterns like "this user type responds better to feature highlights than discounts."

Wrapping Up — Revenue Without the Hard Sell

The essence of AI-powered recommendation monetization is maximizing revenue without degrading user experience. Presenting truly valuable offers at exactly the moment users need them — this "no hard sell" approach is the foundation of a sustainable business model.

Start with simple behavior scoring, then gradually introduce AI agent personalization as your data grows.

For more on app monetization, check out our Rork Subscription Revenue Model Design and Rork Monetization Masterplan.

Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

⟐ Business2026-04-22
Launching a Branded Video Streaming App with Rork as a Solo Developer — HLS Delivery, Stripe Subscriptions, Offline Playback, and Revoking Access on Cancellation
A realistic blueprint for shipping a membership video app with Rork — how to pick an HLS backend, keep Stripe subscription state in sync with playback permission, handle offline viewing securely, and decide whether DRM is actually worth the cost.
⟐ Business2026-10-16
Your First Year With Rork: The Order Your Bills Actually Arrive In
Starting on Rork's free tier doesn't mean the only money moving is Rork's. I lined up the official pricing pages for Rork Pro, Apple, Google Play, EAS and Supabase to show what gets billed when in year one, and what simply stops working instead.
⟐ Business2026-10-08
Before You Build a Client's App in Rork, Decide Who Owns the Store Account
When you hand a Rork-built app to someone else, the first decision is which developer account publishes it. A walk through Apple's and Google's official transfer rules: what must be true before a transfer, what carries over, what disappears, plus a small script that lists the settings in your project tied to your own name.