Implement user segmentation in FlutterFlow by storing segment labels on each user's Firestore document, updated by a nightly Cloud Function that analyzes behavior data. Combine with explicit onboarding segments from user-selected preferences. Show or hide content blocks using FlutterFlow's Conditional Visibility bound to the current user's segment field. Never run segmentation logic on the client — segments must be authoritative server-side values.
Two Types of Segments: Explicit and Behavioral
User segmentation splits your audience into groups so each group sees content, offers, or features relevant to them. In FlutterFlow you work with two segment types. Explicit segments come from onboarding: the user tells you they are a 'freelancer' or interested in 'fitness.' Behavioral segments come from what the user does: opened the app 10+ times last month, made a purchase, or reached a milestone. Both types are stored as fields on the user's Firestore document. Explicit segments are written at onboarding. Behavioral segments are recalculated by a Cloud Function on a schedule, analyzing activity documents and updating segment labels. FlutterFlow widgets then read these fields and apply Conditional Visibility to show the right content block for each segment.
Prerequisites
- FlutterFlow project with Firebase Authentication and Firestore connected
- A users Firestore collection with documents scoped to each authenticated user
- Basic understanding of FlutterFlow's Conditional Visibility panel
- Firebase Blaze plan for scheduled Cloud Functions
Step-by-step guide
Add segment fields to your Firestore user document
Add segment fields to your Firestore user document
Open FlutterFlow's Firestore panel and add the following fields to your users collection schema: explicitSegment (String — set during onboarding, e.g., 'freelancer', 'student', 'enterprise'), behaviorSegment (String — set by Cloud Function, e.g., 'power_user', 'at_risk', 'new_user'), abGroup (String — static assignment, e.g., 'A' or 'B'), interests (String Array — user-selected topics), and segmentUpdatedAt (Timestamp). Having separate explicit and behavior fields lets you combine them for targeting logic: show a feature to users who are both 'enterprise' segment AND 'power_user' behavior.
Expected result: User documents in Firestore have segment fields ready to be populated from onboarding and Cloud Functions.
Collect explicit segments during onboarding
Collect explicit segments during onboarding
Build an onboarding flow in FlutterFlow with 2-3 screens that ask the user about their role and interests. Use a single-select Button Group for role ('Freelancer', 'Startup', 'Enterprise', 'Student') and a multi-select chip grid for interests ('Marketing', 'Development', 'Design', 'Finance'). Store selections in page state variables. On the final onboarding step, use FlutterFlow's Update Document action to write explicitSegment and interests to the user's Firestore document. This runs once at account creation — users can update it from a Profile > Preferences screen later.
Expected result: After onboarding, the user's Firestore document has an explicitSegment string and an interests array reflecting their choices.
Run a nightly Cloud Function to assign behavioral segments
Run a nightly Cloud Function to assign behavioral segments
Create a scheduled Cloud Function that runs every night, reads user activity for the past 30 days, and assigns a behaviorSegment label. Define your segment criteria: 'power_user' = opened app 20+ times and has non-zero purchases; 'at_risk' = was active 60 days ago but has not opened app in 14+ days; 'new_user' = created account in the last 7 days; 'engaged' = everything else. The function queries your activity or sessions collection, evaluates each user against the criteria in priority order, and batch-updates the behaviorSegment field. This function runs server-side so the logic is consistent and cannot be spoofed by clients.
1// functions/updateSegments.js2const { onSchedule } = require('firebase-functions/v2/scheduler');3const { getFirestore, Timestamp } = require('firebase-admin/firestore');4const { initializeApp } = require('firebase-admin/app');56initializeApp();78exports.updateSegments = onSchedule('every day 02:00', async () => {9 const db = getFirestore();10 const now = new Date();11 const day14 = new Date(now - 14 * 86400000);12 const day7 = new Date(now - 7 * 86400000);13 const day30 = new Date(now - 30 * 86400000);14 const day60 = new Date(now - 60 * 86400000);1516 const usersSnap = await db.collection('users').get();17 const batch = db.batch();1819 for (const userDoc of usersSnap.docs) {20 const user = userDoc.data();21 const createdAt = user.createdAt?.toDate() || new Date(0);22 const lastSeen = user.lastSeen?.toDate() || new Date(0);2324 // Count sessions in last 30 days25 const sessionsSnap = await db.collection('sessions')26 .where('userId', '==', userDoc.id)27 .where('createdAt', '>=', Timestamp.fromDate(day30)).get();28 const sessionCount = sessionsSnap.size;2930 let segment = 'engaged';31 if (createdAt >= day7) {32 segment = 'new_user';33 } else if (lastSeen < day14) {34 segment = 'at_risk';35 } else if (sessionCount >= 20) {36 segment = 'power_user';37 }3839 batch.update(userDoc.ref, {40 behaviorSegment: segment,41 segmentUpdatedAt: Timestamp.fromDate(now),42 });43 }44 await batch.commit();45});Expected result: Every user document has an up-to-date behaviorSegment field after each nightly run.
Show targeted content blocks using Conditional Visibility
Show targeted content blocks using Conditional Visibility
In FlutterFlow add content blocks to your home or feed page for each segment variant. For example: a 'Power User' tips banner, an 'At Risk' re-engagement offer card, and a 'New User' onboarding checklist. Stack all variants in the same Column or Stack widget, then configure each block's Conditional Visibility. Click the visibility eye icon > Set Condition. Bind the condition to the authenticated user's behaviorSegment field from Firestore (use the 'Authenticated User > behaviorSegment' path). Set the condition: value == 'power_user' for the tips banner, value == 'at_risk' for the offer card. Only one block will be visible at a time.
Expected result: Each user sees only the content block matching their segment. Switching the behaviorSegment field in Firestore immediately changes what the user sees on next page load.
Assign A/B test groups at account creation
Assign A/B test groups at account creation
For A/B testing, assign users to a static experiment group when their account is created so the group never changes mid-test. In your FlutterFlow account creation flow, after the Create Document action that creates the user profile, add a Custom Function called assignAbGroup that generates either 'A' or 'B' with a 50/50 random split. Write this value to the abGroup field. Because abGroup is assigned once and never updated by the nightly segmentation function, users stay in the same group for the duration of your experiment. Track conversion events in Firebase Analytics using the abGroup value as a user property so you can compare groups in Analytics reports.
1// Custom Function: assignAbGroup.dart2String assignAbGroup() {3 final random = DateTime.now().millisecondsSinceEpoch % 2;4 return random == 0 ? 'A' : 'B';5}Expected result: Each new user is assigned to group A or B. The assignment persists across app sessions and is never overwritten by segmentation updates.
Complete working example
1const { onSchedule } = require('firebase-functions/v2/scheduler');2const { getFirestore, Timestamp } = require('firebase-admin/firestore');3const { initializeApp } = require('firebase-admin/app');45initializeApp();67exports.updateSegments = onSchedule('every day 02:00', async () => {8 const db = getFirestore();9 const now = new Date();10 const msDay = 86400000;11 const ts = (daysAgo) => Timestamp.fromDate(new Date(now - daysAgo * msDay));1213 let lastDoc = null;14 let processed = 0;1516 while (true) {17 let query = db.collection('users').limit(500);18 if (lastDoc) query = query.startAfter(lastDoc);19 const snap = await query.get();20 if (snap.empty) break;2122 const batch = db.batch();23 for (const userDoc of snap.docs) {24 const user = userDoc.data();25 const createdAt = user.createdAt?.toDate() || new Date(0);26 const lastSeen = user.lastSeen?.toDate() || new Date(0);2728 const sessionsSnap = await db.collection('sessions')29 .where('userId', '==', userDoc.id)30 .where('createdAt', '>=', ts(30)).get();3132 let segment = 'engaged';33 if (createdAt >= new Date(now - 7 * msDay)) {34 segment = 'new_user';35 } else if (lastSeen < new Date(now - 14 * msDay)) {36 segment = 'at_risk';37 } else if (sessionsSnap.size >= 20) {38 segment = 'power_user';39 }4041 batch.update(userDoc.ref, {42 behaviorSegment: segment,43 segmentUpdatedAt: Timestamp.fromDate(now),44 });45 }46 await batch.commit();47 processed += snap.size;48 lastDoc = snap.docs[snap.docs.length - 1];49 }50 console.log(`Segmentation complete. Processed: ${processed}`);51});Common mistakes
Why it's a problem: Running segmentation logic on the client and storing it in App State
How to avoid: Calculate all segment assignments in a Cloud Function and store them in the user's Firestore document. The client only reads the stored segment — it never calculates it.
Why it's a problem: Using the same field for both explicit and behavioral segments
How to avoid: Use separate fields: explicitSegment (written at onboarding, never touched by automation) and behaviorSegment (updated nightly by Cloud Function). Combine them in visibility conditions.
Why it's a problem: Adding all segment content blocks to every page
How to avoid: Use FlutterFlow's conditional widget rendering (Set Visibility > Only When) which removes the widget from the tree entirely, or load segment-specific content via a backend query that filters by segment.
Best practices
- Keep segment names consistent across your codebase using a Firestore option set or a constants file — typos in segment strings cause silent failures.
- Log a Firebase Analytics event whenever a user is re-assigned to a new segment so you can track segment migration over time.
- Paginate the nightly segmentation function for user bases over 1,000 to avoid Cloud Function memory limits and timeouts.
- Give users the ability to see and update their explicit segment from a profile screen — transparency builds trust.
- Validate segment strings in Firestore security rules using the in operator to prevent invalid values from being written.
- Document your segment definitions in a Firestore document (e.g., config/segments) so your team knows exactly what criteria each label represents.
- Start with just 2-3 segments and add more only when you have enough users in each group for statistical significance.
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I'm building a FlutterFlow app and want to show personalized content to different user segments. Explain how to design a Firestore data model for user segmentation, how to run a nightly Cloud Function that assigns behavioral segments based on activity data, and how to use FlutterFlow's Conditional Visibility to display segment-specific content.
Write a Firebase Cloud Function in Node.js that runs nightly, reads each user's session count from the last 30 days, and assigns one of four behaviorSegment labels (new_user, power_user, at_risk, engaged) to the user's Firestore document. Handle large user bases by paginating with startAfter.
Frequently asked questions
How many segments should I start with?
Start with 3-4 segments maximum. Each additional segment requires separate content, testing, and measurement. With fewer than a few hundred users per segment, behavioral differences are too small to act on.
Can I segment users without writing Cloud Functions?
Yes, for explicit segments only. Onboarding answers can be stored directly from FlutterFlow's Update Document action without any Cloud Function. Behavioral segmentation based on activity data requires server-side processing.
How do I handle users who fit multiple segment criteria?
Evaluate criteria in priority order in your Cloud Function and assign the first matching label. Define a priority hierarchy (e.g., 'new_user' always takes precedence over 'at_risk'). Store only the highest-priority match so Conditional Visibility logic stays simple.
Will the UI update immediately when a user's segment changes?
In FlutterFlow, widgets bound to Firestore listen in real time by default. If the user is on the app when the nightly function runs and updates their segment, the UI will refresh within seconds. On next login, the latest segment is fetched immediately.
How do I measure whether my targeted content is working?
Log a Firebase Analytics event with the segment label as a parameter whenever a user interacts with segmented content. Use Firebase Analytics' audience reports to compare conversion rates between segments. For A/B tests, compare the abGroup property in Analytics.
Can I use segmentation to restrict features, not just show content?
Yes. Use the same Conditional Visibility mechanism to show or hide entire features, navigation items, or action buttons based on segment or plan tier. For security-sensitive restrictions, also enforce the check in Firestore security rules — client-side hiding alone is not sufficient.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation