Create an engagement rewards system that awards points for in-app actions like opening the app, viewing content, commenting, and sharing. Store engagement rules in Firestore with per-rule cooldowns to prevent abuse. A Cloud Function validates actions and awards points, while a daily_activity subcollection tracks streaks. Display tier progress (Bronze, Silver, Gold) with a CircularPercentIndicator and recent earnings in a ListView. Consistent daily use unlocks streak bonuses that multiply point rewards.
Building an Engagement-Based Rewards System in FlutterFlow
Engagement rewards keep users coming back by rewarding daily usage, content interaction, and social actions with points and tier progression. This tutorial builds a complete system with configurable rules, cooldown enforcement, streak tracking, and a rewards dashboard showing tier progress. Everything uses Firestore and Cloud Functions with the FlutterFlow visual builder.
Prerequisites
- A FlutterFlow project with Firestore and Firebase Authentication configured
- Cloud Functions enabled for server-side point validation
- A users collection with existing user documents
- Basic familiarity with FlutterFlow App State and Backend Queries
Step-by-step guide
Set up the Firestore data model for engagement rules and points
Set up the Firestore data model for engagement rules and points
Add to users collection: totalPoints (Integer, default 0), currentTier (String: 'bronze', 'silver', 'gold'), streakDays (Integer, default 0). Create an engagement_rules collection with documents for each action: event (String: 'app_open', 'content_view', 'comment', 'share', 'streak_7days'), points (Integer), cooldown (String: 'daily', 'once', 'unlimited'), description (String). Create a users/{uid}/point_history subcollection: event (String), points (Integer), timestamp (Timestamp). Create a users/{uid}/daily_activity subcollection: date (String, format YYYY-MM-DD), isActive (Boolean).
Expected result: Firestore has engagement rules, user points fields, point history, and daily activity tracking ready.
Create the Cloud Function for validating and awarding points
Create the Cloud Function for validating and awarding points
Write a Cloud Function awardPoints that receives userId and event. It reads the matching engagement_rule document to get points and cooldown. For 'daily' cooldown: check if a point_history document exists for this event today (query where event == event AND timestamp >= startOfToday). For 'once' cooldown: check if any point_history document exists for this event. If the cooldown check passes, create a point_history document and increment the user totalPoints using FieldValue.increment(). Also update currentTier based on new totalPoints (0-500: bronze, 501-2000: silver, 2001+: gold). Call this function from FlutterFlow Action Flows after each significant user action.
1// Cloud Function: awardPoints2const admin = require('firebase-admin');3const db = admin.firestore();45exports.awardPoints = async (req, res) => {6 const { userId, event } = req.body;7 const ruleSnap = await db.collection('engagement_rules')8 .where('event', '==', event).limit(1).get();9 if (ruleSnap.empty) return res.json({ awarded: false });1011 const rule = ruleSnap.docs[0].data();12 const historyRef = db.collection(`users/${userId}/point_history`);1314 if (rule.cooldown === 'daily') {15 const today = new Date();16 today.setHours(0, 0, 0, 0);17 const existing = await historyRef18 .where('event', '==', event)19 .where('timestamp', '>=', today).limit(1).get();20 if (!existing.empty) return res.json({ awarded: false });21 }2223 await historyRef.add({24 event, points: rule.points,25 timestamp: admin.firestore.FieldValue.serverTimestamp(),26 });2728 const userRef = db.doc(`users/${userId}`);29 await userRef.update({30 totalPoints: admin.firestore.FieldValue.increment(rule.points),31 });3233 const user = (await userRef.get()).data();34 const tier = user.totalPoints > 2000 ? 'gold'35 : user.totalPoints > 500 ? 'silver' : 'bronze';36 await userRef.update({ currentTier: tier });3738 res.json({ awarded: true, points: rule.points, tier });39};Expected result: Points are awarded only when cooldown rules allow, preventing abuse while rewarding genuine engagement.
Implement daily activity tracking and streak calculation
Implement daily activity tracking and streak calculation
On App Load, add a Custom Action that creates or updates a daily_activity document for today (document ID: today date string YYYY-MM-DD, isActive: true). Then call the awardPoints Cloud Function with event 'app_open'. For streak calculation, create a Cloud Function calculateStreak triggered on daily_activity document creation. It queries the last 30 daily_activity documents ordered by date descending, counts consecutive days without gaps, and updates the user streakDays field. When streakDays reaches 7, 14, or 30, award bonus points using the 'streak_7days' engagement rule.
Expected result: Daily app opens are tracked, streaks are calculated server-side, and streak milestones award bonus points.
Build the rewards dashboard with tier progression and history
Build the rewards dashboard with tier progression and history
Create a RewardsDashboard page. At the top, add a Container with the current tier badge: icon (bronze shield, silver star, gold crown) and tier name Text with color matching the tier. Next, add a CircularPercentIndicator showing progress to the next tier (e.g., 750/2000 for silver-to-gold). Below, display totalPoints in large headlineLarge Text and streakDays with a flame icon. Add a 'Recent Earnings' ListView with a Backend Query on point_history subcollection ordered by timestamp descending, limited to 20. Each row shows an icon per event type, event description, points earned (green Text), and timestamp.
Expected result: A rewards dashboard showing the current tier, progress to next tier, streak count, and recent point earnings.
Integrate point awarding into existing Action Flows
Integrate point awarding into existing Action Flows
For each significant action in your app, add the awardPoints API Call at the end of the Action Flow. On content view: after navigating to the content detail page, call awardPoints with event 'content_view'. On comment creation: after the Create Document action for a comment, call awardPoints with event 'comment'. On share: after the Share action, call awardPoints with event 'share'. Show a brief snackbar notification when points are awarded: 'You earned +10 points!' using the response from the Cloud Function. Use Conditional Visibility to only show the snackbar when the response awarded field is true.
Expected result: Points are automatically awarded for app opens, content views, comments, and shares with snackbar feedback.
Complete working example
1FIRESTORE DATA MODEL:2 users/{uid}3 totalPoints: Integer (default 0)4 currentTier: "bronze" | "silver" | "gold"5 streakDays: Integer (default 0)6 └── point_history/{docId}7 event: String8 points: Integer9 timestamp: Timestamp10 └── daily_activity/{YYYY-MM-DD}11 isActive: Boolean1213 engagement_rules/{ruleId}14 event: "app_open" | "content_view" | "comment" | "share" | "streak_7days"15 points: Integer16 cooldown: "daily" | "once" | "unlimited"17 description: String1819TIER THRESHOLDS:20 Bronze: 0 - 500 points21 Silver: 501 - 2000 points22 Gold: 2001+ points2324REWARDS DASHBOARD PAGE:25 Column26 ├── Container (tier badge: icon + name + gradient bg)27 ├── CircularPercentIndicator (progress to next tier)28 ├── Row29 │ ├── Text (totalPoints, headlineLarge)30 │ └── Container (streakDays + flame icon)31 └── ListView (recent point_history, limit 20)32 └── Row33 ├── Icon (per event type)34 ├── Column35 │ ├── Text (event description)36 │ └── Text (timestamp, small)37 └── Text ("+X pts", green)3839ACTION FLOW INTEGRATION:40 On App Load:41 1. Create daily_activity doc for today42 2. API Call: awardPoints(userId, 'app_open')4344 On Content View:45 1. Navigate to content page46 2. API Call: awardPoints(userId, 'content_view')4748 On Comment:49 1. Create Document: comment50 2. API Call: awardPoints(userId, 'comment')51 3. Show Snackbar if awardedCommon mistakes when creating a Rewards System Based on User Engagement in FlutterFlow
Why it's a problem: Awarding app_open points without a daily cooldown
How to avoid: Every engagement rule must have a cooldown. Use 'daily' for app_open so points are awarded only once per day regardless of how many times the user opens the app.
Why it's a problem: Calculating points and tier on the client side
How to avoid: All point calculations and tier updates must happen in Cloud Functions. The client only calls the function and displays the server-confirmed result.
Why it's a problem: Not using atomic operations for point increments
How to avoid: Use FieldValue.increment() in Cloud Functions for all point updates. This ensures atomic addition regardless of concurrent requests.
Best practices
- Enforce cooldowns server-side in Cloud Functions, never trust the client to self-limit
- Use FieldValue.increment() for atomic point updates to prevent race conditions
- Store engagement rules in Firestore so you can adjust point values without redeploying
- Track daily activity as a subcollection with date-based document IDs for easy streak calculation
- Show point-earned snackbar notifications to provide immediate feedback for engagement
- Limit point_history queries to the last 20-50 entries for dashboard performance
- Add streak milestone bonuses (7, 14, 30 days) to incentivize daily return visits
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I want to build an engagement rewards system in FlutterFlow. Show me the Firestore data model for engagement rules with cooldowns, a Cloud Function that validates and awards points, streak tracking with daily activity subcollection, tier progression (Bronze/Silver/Gold), and a rewards dashboard with CircularPercentIndicator and point history.
Create a rewards dashboard page with a tier badge at the top, a circular progress indicator showing points toward the next tier, the total points and streak count, and a scrollable list of recent point earnings below.
Frequently asked questions
Can I add different point values for different types of content views?
Yes. Extend the engagement_rules to include a resourceType field. When calling awardPoints, pass both the event and the resourceType. The Cloud Function matches both fields to find the correct rule and point value.
How do I prevent users from gaming the streak system?
The daily_activity document uses the date as the document ID, so only one entry per day is possible. The streak calculation runs server-side in a Cloud Function, so users cannot manipulate the streak count.
Can I add a leaderboard showing top point earners?
Yes. Query the users collection ordered by totalPoints descending, limited to the top 50. Display in a ListView with rank number, avatar, name, and point total. Update this leaderboard in real-time or cache it in a separate leaderboard document updated by a scheduled Cloud Function.
How do I handle tier downgrades if a user stops engaging?
Tiers based on total accumulated points never decrease since points are additive. If you want time-based tiers, add a scheduled Cloud Function that recalculates tiers monthly based on points earned in the last 30 days only.
Can I let users redeem points for rewards?
Yes. Create a rewards_catalog collection with items (title, pointCost, description). Add a Redeem action that checks the user has enough points, creates a redemption document, and decrements totalPoints using FieldValue.increment with a negative value.
Can RapidDev help build a complete gamification system?
Yes. RapidDev can implement a full gamification system including points, badges, leaderboards, streak bonuses, referral rewards, and a reward redemption marketplace.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation