# How to Create a Rewards System Based on User Engagement in FlutterFlow

- Tool: FlutterFlow
- Difficulty: Beginner
- Time required: 25-35 min
- Compatibility: FlutterFlow Free+
- Last updated: March 2026

## TL;DR

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.

## Before you start

- 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

### 1. 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.

### 2. 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.

```
// Cloud Function: awardPoints
const admin = require('firebase-admin');
const db = admin.firestore();

exports.awardPoints = async (req, res) => {
  const { userId, event } = req.body;
  const ruleSnap = await db.collection('engagement_rules')
    .where('event', '==', event).limit(1).get();
  if (ruleSnap.empty) return res.json({ awarded: false });

  const rule = ruleSnap.docs[0].data();
  const historyRef = db.collection(`users/${userId}/point_history`);

  if (rule.cooldown === 'daily') {
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const existing = await historyRef
      .where('event', '==', event)
      .where('timestamp', '>=', today).limit(1).get();
    if (!existing.empty) return res.json({ awarded: false });
  }

  await historyRef.add({
    event, points: rule.points,
    timestamp: admin.firestore.FieldValue.serverTimestamp(),
  });

  const userRef = db.doc(`users/${userId}`);
  await userRef.update({
    totalPoints: admin.firestore.FieldValue.increment(rule.points),
  });

  const user = (await userRef.get()).data();
  const tier = user.totalPoints > 2000 ? 'gold'
    : user.totalPoints > 500 ? 'silver' : 'bronze';
  await userRef.update({ currentTier: tier });

  res.json({ awarded: true, points: rule.points, tier });
};
```

**Expected result:** Points are awarded only when cooldown rules allow, preventing abuse while rewarding genuine engagement.

### 3. 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.

### 4. 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.

### 5. 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 code example

File: `FlutterFlow Engagement Rewards Setup`

```text
FIRESTORE DATA MODEL:
  users/{uid}
    totalPoints: Integer (default 0)
    currentTier: "bronze" | "silver" | "gold"
    streakDays: Integer (default 0)
    └── point_history/{docId}
          event: String
          points: Integer
          timestamp: Timestamp
    └── daily_activity/{YYYY-MM-DD}
          isActive: Boolean

  engagement_rules/{ruleId}
    event: "app_open" | "content_view" | "comment" | "share" | "streak_7days"
    points: Integer
    cooldown: "daily" | "once" | "unlimited"
    description: String

TIER THRESHOLDS:
  Bronze: 0 - 500 points
  Silver: 501 - 2000 points
  Gold: 2001+ points

REWARDS DASHBOARD PAGE:
  Column
    ├── Container (tier badge: icon + name + gradient bg)
    ├── CircularPercentIndicator (progress to next tier)
    ├── Row
    │     ├── Text (totalPoints, headlineLarge)
    │     └── Container (streakDays + flame icon)
    └── ListView (recent point_history, limit 20)
          └── Row
                ├── Icon (per event type)
                ├── Column
                │     ├── Text (event description)
                │     └── Text (timestamp, small)
                └── Text ("+X pts", green)

ACTION FLOW INTEGRATION:
  On App Load:
    1. Create daily_activity doc for today
    2. API Call: awardPoints(userId, 'app_open')

  On Content View:
    1. Navigate to content page
    2. API Call: awardPoints(userId, 'content_view')

  On Comment:
    1. Create Document: comment
    2. API Call: awardPoints(userId, 'comment')
    3. Show Snackbar if awarded
```

## Common mistakes

- **Awarding app_open points without a daily cooldown** — Users can force-close and reopen the app repeatedly to earn unlimited points, completely undermining the rewards system. Fix: 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.
- **Calculating points and tier on the client side** — Users can manipulate client-side logic to award themselves arbitrary points. Client-calculated totals can also drift from the true Firestore values. Fix: All point calculations and tier updates must happen in Cloud Functions. The client only calls the function and displays the server-confirmed result.
- **Not using atomic operations for point increments** — If two actions trigger simultaneously and both read the same totalPoints value before writing, one increment is lost. Fix: 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

## 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.

---

Source: https://www.rapidevelopers.com/flutterflow-tutorials/how-to-create-a-rewards-system-based-on-user-engagement-in-flutterflow
© RapidDev — https://www.rapidevelopers.com/flutterflow-tutorials/how-to-create-a-rewards-system-based-on-user-engagement-in-flutterflow
