Build a content recommendation engine by tracking user interactions (views, likes, saves, shares) in a Firestore user_interactions collection. A scheduled Cloud Function analyzes each user's interaction history, identifies preferred categories and content patterns, and writes personalized recommendations to a users/{uid}/recommendations subcollection. Display recommendations in a 'Recommended for You' horizontal ScrollView on the home page. Start with simple category-based filtering using arrayContainsAny matching the user's liked categories, then graduate to collaborative filtering with a Cloud Function for higher accuracy.
Building a Content Recommendation Engine in FlutterFlow
Content recommendations keep users engaged by surfacing relevant content based on their behavior. This tutorial builds a recommendation system starting with simple category-based filtering and progressing to a Cloud Function pipeline that pre-computes personalized recommendations. Everything is stored in Firestore and displayed with the FlutterFlow visual builder.
Prerequisites
- A FlutterFlow project with Firestore and Firebase Authentication configured
- A content collection with at least 20 documents with category and tags fields
- Cloud Functions enabled for the recommendation pipeline
- Basic familiarity with FlutterFlow Backend Queries and App State
Step-by-step guide
Set up user interaction tracking in Firestore
Set up user interaction tracking in Firestore
Create a user_interactions collection with fields: userId (String), contentId (String), type (String: 'view', 'like', 'save', 'share'), timestamp (Timestamp), contentCategory (String, denormalized for fast queries). Add interaction logging to your app: on content page load, create a 'view' interaction. On like button tap, create a 'like' interaction. On save/bookmark tap, create a 'save' interaction. On share action, create a 'share' interaction. Also update the user document with a likedCategories array field that tracks unique categories the user has interacted with (append on like, deduplicate).
Expected result: Every user interaction (view, like, save, share) is logged in Firestore with category information.
Implement simple category-based recommendations
Implement simple category-based recommendations
As a quick starting point before the Cloud Function pipeline, create a Backend Query on the content collection using arrayContainsAny with the current user's likedCategories array. Order by a popularity or recency field. Exclude content the user has already viewed by maintaining a viewedContentIds array in App State (populated on app load from recent user_interactions where type == 'view'). Display results in a 'Recommended for You' horizontal ListView on the home page. Each item is a ContentCard Component showing: thumbnail Image, title Text, category Badge, and a 'Recommended' label.
Expected result: Users see content recommendations based on their liked categories, with already-viewed content filtered out.
Build the Cloud Function recommendation pipeline
Build the Cloud Function recommendation pipeline
Create a scheduled Cloud Function generateRecommendations that runs daily. For each active user: 1) Query their user_interactions from the last 30 days. 2) Calculate a category preference score: likes=3 points, saves=2, shares=2, views=1 per interaction type. 3) Rank categories by score. 4) For the top 3 categories, query content the user has not yet viewed, ordered by popularity. 5) Score each content item: category match score + freshness bonus (newer = higher) + popularity factor. 6) Write the top 20 recommendations to users/{uid}/recommendations subcollection with: contentId, score, reason (e.g., 'Because you liked [category]'). Clear old recommendations before writing new ones.
1// Cloud Function: generateRecommendations (scheduled daily)2const admin = require('firebase-admin');3const db = admin.firestore();45exports.generateRecommendations = async () => {6 const thirtyDaysAgo = new Date();7 thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);89 const usersSnap = await db.collection('users').get();10 for (const userDoc of usersSnap.docs) {11 const userId = userDoc.id;12 const interactions = await db.collection('user_interactions')13 .where('userId', '==', userId)14 .where('timestamp', '>=', thirtyDaysAgo)15 .get();1617 const scores = {};18 const weights = { like: 3, save: 2, share: 2, view: 1 };19 const viewedIds = new Set();2021 interactions.docs.forEach(doc => {22 const d = doc.data();23 const cat = d.contentCategory;24 scores[cat] = (scores[cat] || 0) + (weights[d.type] || 1);25 if (d.type === 'view') viewedIds.add(d.contentId);26 });2728 const topCats = Object.entries(scores)29 .sort((a, b) => b[1] - a[1])30 .slice(0, 3)31 .map(e => e[0]);3233 const content = await db.collection('content')34 .where('category', 'in', topCats)35 .orderBy('popularity', 'desc')36 .limit(50)37 .get();3839 const recs = content.docs40 .filter(d => !viewedIds.has(d.id))41 .slice(0, 20)42 .map(d => ({43 contentId: d.id,44 score: scores[d.data().category] || 0,45 reason: `Because you liked ${d.data().category}`,46 }));4748 // Write recommendations49 const recsRef = db.collection(`users/${userId}/recommendations`);50 const batch = db.batch();51 const oldRecs = await recsRef.get();52 oldRecs.docs.forEach(d => batch.delete(d.ref));53 recs.forEach(r => batch.set(recsRef.doc(), r));54 await batch.commit();55 }56};Expected result: A daily Cloud Function computes personalized recommendations and stores them in each user's subcollection.
Display pre-computed recommendations on the home page
Display pre-computed recommendations on the home page
On your HomePage, add a 'Recommended for You' section. Use a horizontal ListView with a Backend Query on users/{currentUser.uid}/recommendations ordered by score descending. Each item queries the content document by contentId (using a second Backend Query or a Document Reference) to get the full content details. Display each as a ContentCard: thumbnail Image, title Text, category Badge Container, and a reason Text below (e.g., 'Because you liked Technology'). Add a 'See All' TextButton that navigates to a full recommendations page with a vertical ListView. If the recommendations subcollection is empty (new user), fall back to a 'Trending' query showing the most popular content.
Expected result: The home page shows a personalized recommendation carousel with content the user is likely to enjoy.
Add user preference controls and feedback loop
Add user preference controls and feedback loop
Create a PreferencesPage where users can explicitly set content preferences. Display all content categories as ChoiceChips. Pre-select categories from the user's likedCategories array. Let users add or remove categories. Save changes to the user document. Also add feedback to recommendations: on each recommended item, add 'Not Interested' and 'Show More Like This' options. 'Not Interested' creates a dismissed_recommendations document. 'Show More Like This' creates a 'like' interaction boosting that category. The Cloud Function reads dismissed_recommendations to exclude those items from future results.
Expected result: Users can tune their preferences and provide feedback on recommendations to improve future suggestions.
Complete working example
1FIRESTORE DATA MODEL:2 content/{contentId}3 title: String4 body: String5 thumbnailUrl: String6 category: String7 tags: [String]8 popularity: Integer9 createdAt: Timestamp1011 user_interactions/{docId}12 userId: String13 contentId: String14 type: "view" | "like" | "save" | "share"15 timestamp: Timestamp16 contentCategory: String (denormalized)1718 users/{uid}19 likedCategories: [String]20 └── recommendations/{docId}21 contentId: String22 score: Number23 reason: String24 └── dismissed_recommendations/{docId}25 contentId: String2627INTERACTION LOGGING:28 On Content Page Load:29 → Create user_interactions doc (type: 'view')30 On Like Button:31 → Create user_interactions doc (type: 'like')32 → Update user likedCategories array (add category)33 On Save/Share:34 → Create user_interactions doc (type: 'save'/'share')3536SIMPLE CATEGORY FILTER (immediate):37 content38 .where('category', 'in', currentUser.likedCategories[:3])39 .orderBy('popularity', 'desc')40 .limit(20)4142CLOUD FUNCTION PIPELINE (daily):43 For each user:44 1. Query 30-day interactions45 2. Score categories (like=3, save=2, share=2, view=1)46 3. Get top 3 categories47 4. Query unseen content in those categories48 5. Score and rank content49 6. Write top 20 to recommendations subcollection5051HOME PAGE:52 Column53 ├── Text ("Recommended for You")54 ├── ListView.horizontal55 │ Backend Query: recommendations, order by score desc56 │ └── ContentCard Component57 │ ├── Image (thumbnail)58 │ ├── Text (title)59 │ ├── Container (category badge)60 │ └── Text (reason, small italic)61 ├── Text ("Trending")62 └── ListView.horizontal63 Backend Query: content, order by popularity descCommon mistakes
Why it's a problem: Running the recommendation algorithm on the client side
How to avoid: Pre-compute recommendations in a scheduled Cloud Function and store results in a user subcollection. The client reads only 20 pre-computed recommendation documents.
Why it's a problem: Not excluding already-viewed content from recommendations
How to avoid: Track viewedContentIds from user_interactions and filter them out in both the Cloud Function pipeline and the simple category-based fallback query.
Why it's a problem: Only using view counts as the recommendation signal
How to avoid: Weight interaction types differently: likes and saves are 2-3x more valuable than views. Use the weighted scoring system in the Cloud Function.
Best practices
- Pre-compute recommendations in a scheduled Cloud Function, not on the client
- Weight interaction types: likes/saves > shares > views for better signal quality
- Denormalize content category on interaction documents for efficient Cloud Function queries
- Exclude already-viewed content from recommendation results
- Fall back to trending/popular content for new users with no interaction history
- Combine implicit signals (views, likes) with explicit preferences for best results
- Show the reason for each recommendation to build user trust and engagement
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I want to build a content recommendation system in FlutterFlow. Show me how to track user interactions in Firestore, implement category-based filtering, create a scheduled Cloud Function that computes personalized recommendations using weighted scoring, store pre-computed results in a user subcollection, and display them in a horizontal carousel.
Create a home page section titled Recommended for You with a horizontal scrollable list of content cards. Each card shows a thumbnail image, title, category tag, and a small text explaining why it was recommended.
Frequently asked questions
How many user interactions do I need before recommendations are useful?
Start showing category-based recommendations after 5-10 interactions. The Cloud Function pipeline becomes meaningful after 20-30 interactions per user. For brand new users, show trending or popular content as a cold-start fallback.
Can I use collaborative filtering instead of content-based filtering?
Yes. Collaborative filtering finds users with similar interaction patterns and recommends what those similar users liked. Implement this in the Cloud Function by computing user-user similarity scores based on shared likes, then recommending content liked by similar users that the target user has not seen.
How do I handle the cold-start problem for new content?
New content has no interaction data. Boost new content by adding a freshness factor to the scoring algorithm: content less than 7 days old gets a bonus score. Also, show new content in a dedicated 'New' section separate from personalized recommendations.
Will the daily Cloud Function be expensive at scale?
For up to 10,000 users, a daily Cloud Function runs within free-tier limits. For larger scale, process users in batches, only recompute for users active in the last 7 days, and use Firestore batch writes to minimize operations.
Can I add real-time recommendations that update as the user browses?
Yes. In addition to the daily pre-computed recommendations, add a lightweight real-time layer: after each interaction, immediately query content in the same category as the just-interacted content and show it in a 'More Like This' section.
Can RapidDev help build an advanced recommendation engine?
Yes. RapidDev can implement a full recommendation system including collaborative filtering, content-based filtering, hybrid approaches, A/B testing of algorithms, real-time updates, and integration with ML platforms for deep learning models.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation