Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Implement Sentiment Analysis on User Feedback in FlutterFlow

Sentiment analysis automatically scores user feedback as positive, negative, or neutral so you can prioritize what to fix. Connect a Cloud Function to Google Cloud Natural Language API's analyzeSentiment endpoint, store the score and magnitude in Firestore, then display trend charts in an admin dashboard. Set up alerts when the average sentiment score drops below a threshold.

What you'll learn

  • How Google Cloud Natural Language API scores text sentiment
  • Building a Cloud Function to analyze feedback and write results to Firestore
  • Displaying sentiment trends with FlutterFlow charts
  • Triggering email alerts when negative feedback volume spikes
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner10 min read40-55 minFlutterFlow Pro+ (code export required for custom functions)March 2026RapidDev Engineering Team
TL;DR

Sentiment analysis automatically scores user feedback as positive, negative, or neutral so you can prioritize what to fix. Connect a Cloud Function to Google Cloud Natural Language API's analyzeSentiment endpoint, store the score and magnitude in Firestore, then display trend charts in an admin dashboard. Set up alerts when the average sentiment score drops below a threshold.

From raw feedback to actionable sentiment data

Star ratings tell you how happy users are in aggregate, but they don't tell you why. A 3-star review with 'checkout was confusing but products are great' contains two distinct signals. Google Cloud Natural Language API's analyzeSentiment endpoint returns a score (–1.0 to +1.0) and a magnitude (0 to infinity). Score indicates polarity; magnitude indicates how strongly the text expresses that emotion. A score of –0.8 with high magnitude means strongly negative and confident. By storing these values in Firestore alongside every feedback submission, you build a queryable sentiment history that powers admin charts, product prioritization, and automated alerts. The Cloud Function pattern keeps your API key server-side and adds analysis without changing your existing feedback submission flow.

Prerequisites

  • FlutterFlow project connected to Firebase with Firestore enabled
  • Google Cloud project with Natural Language API enabled and a service account key
  • Firebase Cloud Functions set up (firebase init functions in your project)
  • An existing feedback collection in Firestore or a form to create one
  • Basic familiarity with FlutterFlow Action Flows

Step-by-step guide

1

Enable Google Cloud Natural Language API and get credentials

Go to console.cloud.google.com and select your project. In the search bar type 'Natural Language API' and click Enable. Next, go to APIs & Services → Credentials → Create Credentials → API Key. Copy the key. For production, restrict the key to the Natural Language API only by clicking Edit on the key and setting API restrictions. Store this key as a Firebase environment variable: in your terminal run 'firebase functions:config:set nlp.key=YOUR_API_KEY'. This keeps the key off the client and out of your codebase.

Expected result: Natural Language API shows as 'Enabled' in your Google Cloud console. API key is stored as a Firebase config variable.

2

Write a Cloud Function that analyzes sentiment and updates Firestore

Create a new Cloud Function that triggers when a document is written to your feedback collection. It reads the comment text, calls the Natural Language API, extracts the score and magnitude, then writes those values back to the same Firestore document. This is a Firestore onWrite trigger — it fires automatically every time a feedback document is created or updated, so you never need to call it manually from your app. Deploy with 'firebase deploy --only functions'.

functions/index.js
1// functions/index.js
2const functions = require('firebase-functions');
3const admin = require('firebase-admin');
4const axios = require('axios');
5
6admin.initializeApp();
7
8exports.analyzeFeedbackSentiment = functions.firestore
9 .document('feedback/{feedbackId}')
10 .onCreate(async (snap, context) => {
11 const data = snap.data();
12 const text = data.comment;
13 if (!text || text.trim().length === 0) return null;
14
15 const apiKey = functions.config().nlp.key;
16 const url = `https://language.googleapis.com/v1/documents:analyzeSentiment?key=${apiKey}`;
17
18 try {
19 const response = await axios.post(url, {
20 document: { type: 'PLAIN_TEXT', content: text },
21 encodingType: 'UTF8',
22 });
23
24 const sentiment = response.data.documentSentiment;
25 const score = sentiment.score; // -1.0 to +1.0
26 const magnitude = sentiment.magnitude; // 0 to infinity
27
28 // Classify for easy filtering
29 let label = 'neutral';
30 if (score >= 0.25) label = 'positive';
31 if (score <= -0.25) label = 'negative';
32
33 await snap.ref.update({
34 sentiment_score: score,
35 sentiment_magnitude: magnitude,
36 sentiment_label: label,
37 analyzed_at: admin.firestore.FieldValue.serverTimestamp(),
38 });
39
40 console.log(`Feedback ${context.params.feedbackId}: ${label} (${score})`);
41 return null;
42 } catch (error) {
43 console.error('Sentiment analysis failed:', error.message);
44 return null;
45 }
46 });

Expected result: After deploying, submit a test feedback document in Firestore. Within 5-10 seconds it should gain sentiment_score, sentiment_magnitude, sentiment_label, and analyzed_at fields.

3

Update the FlutterFlow feedback form to write to Firestore

In FlutterFlow, open your feedback page. Make sure it has a TextField for the comment and a Button to submit. In the Button's Action Flow, add a Firestore Create Document action targeting your 'feedback' collection. Map the TextField value to the 'comment' field. Also store the current user's UID (from Authenticated User → uid) and a timestamp (from Set from Variable → Current Time). You do NOT need to include sentiment fields — the Cloud Function populates those automatically after the document is created. Add a SnackBar action after the create action to show 'Thanks for your feedback!'.

Expected result: Submitting the form creates a new document in the feedback collection. The Cloud Function enriches it with sentiment data within seconds.

4

Build the admin sentiment dashboard with charts

Create a new page called 'Admin Dashboard' in FlutterFlow. Add a Backend Query at the page level that fetches all documents from the feedback collection, ordered by analyzed_at descending. Add three Count widgets showing the number of documents where sentiment_label equals 'positive', 'negative', and 'neutral' respectively — use Firestore Query conditions to filter. Add a Bar Chart widget: set the X axis to the submission date (grouped by day) and the Y axis to the average sentiment_score. Finally, add a ListView below the chart showing recent feedback cards with the comment text and a color-coded sentiment badge (green, red, neutral).

Expected result: Admin dashboard shows live counts of positive/negative/neutral feedback and a chart of sentiment over time, updating as new feedback arrives.

5

Add automated alerts when negative feedback spikes

Extend your Cloud Function to send an alert email when the rolling negative sentiment ratio exceeds a threshold. After writing the sentiment data back to Firestore, query the last 50 feedback documents and calculate the percentage that are 'negative'. If it exceeds 30%, send an alert using the Firebase Transactional Email extension or a simple SendGrid API call. Add a cooldown check by storing the last alert time in a Firestore config document so you don't flood your inbox.

functions/index.js (addition)
1// Add inside analyzeFeedbackSentiment, after the snap.ref.update() call:
2const db = admin.firestore();
3const recentDocs = await db.collection('feedback')
4 .orderBy('analyzed_at', 'desc')
5 .limit(50)
6 .get();
7
8const analyzed = recentDocs.docs.filter(d => d.data().sentiment_label);
9const negCount = analyzed.filter(d => d.data().sentiment_label === 'negative').length;
10const negRatio = negCount / analyzed.length;
11
12if (negRatio > 0.30) {
13 const configRef = db.doc('config/sentiment_alerts');
14 const config = await configRef.get();
15 const lastAlert = config.data()?.last_alert_at?.toMillis() || 0;
16 const oneHour = 60 * 60 * 1000;
17
18 if (Date.now() - lastAlert > oneHour) {
19 // Send alert via your preferred email service
20 console.warn(`ALERT: ${Math.round(negRatio * 100)}% negative sentiment in last 50 reviews`);
21 await configRef.set({ last_alert_at: admin.firestore.FieldValue.serverTimestamp() }, { merge: true });
22 }
23}

Expected result: When 30%+ of recent feedback is negative, an alert is logged (or emailed) and a cooldown prevents repeated alerts within one hour.

Complete working example

functions/index.js
1// Firebase Cloud Function: Sentiment Analysis on User Feedback
2// Deploy: firebase deploy --only functions
3// Config: firebase functions:config:set nlp.key=YOUR_GOOGLE_NLP_API_KEY
4
5const functions = require('firebase-functions');
6const admin = require('firebase-admin');
7const axios = require('axios');
8
9admin.initializeApp();
10
11exports.analyzeFeedbackSentiment = functions.firestore
12 .document('feedback/{feedbackId}')
13 .onCreate(async (snap, context) => {
14 const data = snap.data();
15 const text = data.comment;
16
17 if (!text || text.trim().length < 3) return null;
18
19 const apiKey = functions.config().nlp.key;
20 const url =
21 `https://language.googleapis.com/v1/documents:analyzeSentiment?key=${apiKey}`;
22
23 try {
24 const response = await axios.post(url, {
25 document: { type: 'PLAIN_TEXT', content: text },
26 encodingType: 'UTF8',
27 });
28
29 const { score, magnitude } = response.data.documentSentiment;
30
31 let label = 'neutral';
32 if (score >= 0.25) label = 'positive';
33 if (score <= -0.25) label = 'negative';
34
35 await snap.ref.update({
36 sentiment_score: score,
37 sentiment_magnitude: magnitude,
38 sentiment_label: label,
39 analyzed_at: admin.firestore.FieldValue.serverTimestamp(),
40 });
41
42 // Check for negative spike alert
43 const db = admin.firestore();
44 const recentDocs = await db.collection('feedback')
45 .orderBy('analyzed_at', 'desc')
46 .limit(50)
47 .get();
48
49 const analyzed = recentDocs.docs.filter(d => d.data().sentiment_label);
50 if (analyzed.length >= 10) {
51 const negCount = analyzed.filter(
52 d => d.data().sentiment_label === 'negative'
53 ).length;
54 const negRatio = negCount / analyzed.length;
55
56 if (negRatio > 0.30) {
57 const configRef = db.doc('config/sentiment_alerts');
58 const config = await configRef.get();
59 const lastAlert = config.data()?.last_alert_at?.toMillis() || 0;
60 const oneHour = 60 * 60 * 1000;
61
62 if (Date.now() - lastAlert > oneHour) {
63 console.warn(
64 `SENTIMENT ALERT: ${Math.round(negRatio * 100)}% negative in last ${analyzed.length} reviews`
65 );
66 await configRef.set(
67 { last_alert_at: admin.firestore.FieldValue.serverTimestamp() },
68 { merge: true }
69 );
70 }
71 }
72 }
73
74 return null;
75 } catch (err) {
76 console.error('Sentiment analysis error:', err.message);
77 return null;
78 }
79 });

Common mistakes

Why it's a problem: Using only star rating and ignoring text comment sentiment

How to avoid: Store and analyze both. Show star rating for quick trend, but surface low-magnitude high-score anomalies (e.g., sarcastic 5-star reviews) using the NLP score.

Why it's a problem: Calling the Natural Language API directly from the Flutter client

How to avoid: Always call the NLP API from a Cloud Function. The Cloud Function has the key stored in firebase functions:config, which is never exposed to clients.

Why it's a problem: Not handling empty or very short feedback text

How to avoid: Check text length before calling the API. If the comment is fewer than 3 words, set sentiment_label to 'insufficient_data' and skip the API call.

Why it's a problem: Building the admin dashboard with a large unindexed Firestore query

How to avoid: Create composite indexes in the Firebase console for the fields you filter and sort on (sentiment_label + analyzed_at). Use pagination with a 50-item limit per page.

Best practices

  • Analyze sentiment asynchronously via Cloud Function trigger — never block the user's form submission waiting for NLP results
  • Store raw score and magnitude alongside the label so you can adjust thresholds later without re-analyzing
  • Segment sentiment by user cohort, feature area, or app version to identify which parts of your product drive negative feedback
  • Use magnitude to filter out noise — a score of –0.1 with magnitude 0.2 is nearly neutral, not a real complaint
  • Combine sentiment with session data (screens visited before submitting) to correlate UX pain points with negative text
  • Review and re-label a sample of 50 results manually each month to verify the API's accuracy for your domain
  • Set budget alerts on the Google Cloud Natural Language API — costs are $1 per 1,000 calls beyond the free tier

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I'm building a FlutterFlow app with Firebase. I want a Cloud Function (Node.js) that triggers on Firestore onCreate for the 'feedback' collection, calls Google Cloud Natural Language API analyzeSentiment on the document's 'comment' field, and writes back sentiment_score, sentiment_magnitude, and sentiment_label ('positive', 'negative', 'neutral') to the document. Also add logic to check if more than 30% of the last 50 analyzed documents are negative and log a warning if so.

FlutterFlow Prompt

In FlutterFlow, I have a feedback page with a TextField and a Submit button. Describe step by step how to set up the Action Flow on the Submit button to create a Firestore document in the 'feedback' collection with the comment text, user ID from Authenticated User, and a server timestamp — without including any sentiment fields (those are added by a Cloud Function after creation).

Frequently asked questions

How accurate is Google Cloud Natural Language API for sentiment analysis?

It's highly accurate for standard English text — typically 80-90% agreement with human raters on clear positive/negative content. Accuracy drops for short texts (under 10 words), industry-specific jargon, or sarcasm. Review a sample of your own data to confirm accuracy for your use case.

What does 'magnitude' mean and when should I use it?

Magnitude measures how strongly sentiment is expressed, regardless of direction. Score of –0.9 with magnitude 3.0 means strongly and confidently negative. Score of –0.3 with magnitude 0.2 means slightly negative but the text is mostly factual. Use magnitude to filter out weak signals — only alert on high magnitude negative feedback.

Can I use OpenAI instead of Google Cloud NLP for sentiment?

Yes. Send the feedback text to GPT-4 with a prompt like 'Classify this as positive, negative, or neutral and give a confidence score 0-1'. OpenAI gives more nuanced output but costs more per call and has higher latency. Google NLP is faster and cheaper for bulk sentiment classification.

Does this work with non-English feedback?

Google Cloud Natural Language API supports 700+ languages for sentiment analysis. Pass the language code in the document object (e.g., language: 'es' for Spanish) or let the API auto-detect it. Auto-detection is reliable for texts over 20 words.

How do I display a sentiment chart in FlutterFlow?

FlutterFlow has a built-in Chart widget. Add a Backend Query at the page level loading feedback documents grouped by day. Use a Bar Chart with the date on the X axis and average sentiment_score on the Y axis. For the color fill, set positive values to green and negative to red using conditional chart styling.

What does it cost to analyze 1,000 feedback submissions per month?

Google Cloud Natural Language API has a free tier of 5,000 units per month. Beyond that, sentiment analysis is $1 per 1,000 records (each record up to 1,000 characters). 1,000 submissions per month falls within the free tier. 10,000 submissions would cost about $5/month.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.