# How to Use Machine Learning for Predictive Analytics in FlutterFlow

- Tool: FlutterFlow
- Difficulty: Beginner
- Time required: 60-90 min
- Compatibility: FlutterFlow Pro+ (Cloud Functions required)
- Last updated: March 2026

## TL;DR

Add machine learning predictive analytics to your FlutterFlow app by extracting behavioral features from Firestore events, calling an ML model endpoint (BigQuery ML or Cloud AI Platform) via a Cloud Function, and storing churn scores and purchase probabilities back in Firestore user documents. Trigger automated re-engagement flows when scores cross thresholds. Never train a churn model on only churned users — you need both churned and retained users.

## Predictive Analytics Without a Data Science Team

Machine learning for predictive analytics sounds daunting, but BigQuery ML lets you train and deploy a logistic regression or gradient boosted trees model using SQL syntax — no Python or ML frameworks required. The data comes from behavioral events you are already logging in Firestore (or can start logging today): session count, screens visited, feature usage, and last active date. A Cloud Function extracts these features, calls the BigQuery ML prediction endpoint, and writes the score back to Firestore. FlutterFlow reads the score from the user document to personalize the UI — showing win-back offers to high-churn-risk users or upsell prompts to high-purchase-probability users. The whole pipeline runs on Google Cloud with no external ML infrastructure.

## Before you start

- FlutterFlow project with Firebase Firestore and user behavioral event logging
- Google Cloud project with BigQuery enabled (linked to your Firebase project)
- A minimum of 500 labeled training examples (churned and retained users) for meaningful model accuracy
- FlutterFlow Pro plan for Cloud Functions

## Step-by-step guide

### 1. Define and log the behavioral features you will use for prediction

Machine learning models are only as good as their input features. Before thinking about models, decide what user behavior predicts churn or purchase in your app. Common high-signal features: `daysSinceLastActive` (most predictive for churn), `totalSessionsLast30Days`, `featureUsageCount` (how many distinct features used), `profileCompletionPercent`, `notificationOptIn` (boolean), `purchaseCount`, `averageSessionDurationSeconds`. Ensure these are being logged to Firestore. If they are not, add On Page Load tracking (see the navigation patterns tutorial) and aggregate them daily into a `userStats` document per user. The `userStats` collection should have one document per user, keyed by UID, with all computed features as numeric fields.

**Expected result:** A `userStats` collection exists in Firestore with one document per user containing numeric feature fields updated daily.

### 2. Export Firestore features to BigQuery for model training

Firebase has a native BigQuery export integration. In the Firebase console, go to Project Settings > Integrations > BigQuery > Link. This exports Firebase Analytics events to BigQuery automatically. For your Firestore `userStats` features, set up a scheduled Cloud Function that exports the collection to a BigQuery table using the BigQuery client library. Create a BigQuery table named `user_features` with columns matching your `userStats` fields plus a `churned` column (1 if the user has not been active in 30 days, 0 if active). This labeled dataset is what you will train the model on.

```
const { onSchedule } = require('firebase-functions/v2/scheduler');
const { initializeApp } = require('firebase-admin/app');
const { getFirestore } = require('firebase-admin/firestore');
const { BigQuery } = require('@google-cloud/bigquery');

initializeApp();

exports.exportUserStatsToBigQuery = onSchedule('every 24 hours', async () => {
  const db = getFirestore();
  const bq = new BigQuery();
  const dataset = bq.dataset('analytics');
  const table = dataset.table('user_features');

  const snapshot = await db.collection('userStats').get();
  const rows = [];
  const now = Date.now();

  snapshot.forEach((doc) => {
    const d = doc.data();
    const lastActive = d.lastActiveAt?.toDate()?.getTime() || 0;
    const daysSinceLastActive = Math.floor((now - lastActive) / 86400000);
    rows.push({
      userId: doc.id,
      daysSinceLastActive,
      totalSessionsLast30Days: d.totalSessionsLast30Days || 0,
      featureUsageCount: d.featureUsageCount || 0,
      purchaseCount: d.purchaseCount || 0,
      profileCompletionPercent: d.profileCompletionPercent || 0,
      churned: daysSinceLastActive > 30 ? 1 : 0,
      exportedAt: new Date().toISOString(),
    });
  });

  if (rows.length > 0) {
    await table.insert(rows);
  }
  console.log(`Exported ${rows.length} user stats to BigQuery`);
});
```

**Expected result:** A BigQuery table `analytics.user_features` is populated with user feature rows daily.

### 3. Train a churn prediction model in BigQuery ML

In the BigQuery console, run the CREATE MODEL SQL statement to train a logistic regression classifier. Use the `user_features` table with `churned` as the label column. BigQuery ML handles feature scaling and training automatically. After training, evaluate the model using the ML.EVALUATE function — look for an AUC-ROC above 0.75 as a baseline. If accuracy is low, check your feature quality and ensure both churned and retained users are represented in roughly equal proportions in the training data. Once the model is trained, it stays in BigQuery and you call it via SQL from your Cloud Function.

```
-- Run in BigQuery console
CREATE OR REPLACE MODEL `your_project.analytics.churn_model`
OPTIONS(
  model_type = 'logistic_reg',
  input_label_cols = ['churned'],
  auto_class_weights = TRUE
) AS
SELECT
  daysSinceLastActive,
  totalSessionsLast30Days,
  featureUsageCount,
  purchaseCount,
  profileCompletionPercent,
  churned
FROM `your_project.analytics.user_features`
WHERE exportedAt < TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY);

-- Evaluate the model
SELECT *
FROM ML.EVALUATE(
  MODEL `your_project.analytics.churn_model`,
  (SELECT * FROM `your_project.analytics.user_features`
   WHERE exportedAt >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY))
);
```

**Expected result:** The BigQuery console shows the trained model in the `analytics` dataset with AUC-ROC and accuracy metrics.

### 4. Create a Cloud Function that scores users and writes results to Firestore

Create a Cloud Function named `scoreUserChurnRisk`. It runs daily via Cloud Scheduler. The function queries the current `userStats` for all active users, calls BigQuery ML's `ML.PREDICT` via a SQL query to get a churn probability for each user, and writes the score back to each user's document in Firestore as a `churnScore` (float, 0-1) and `churnScoreUpdatedAt` timestamp. Also compute a `purchaseProbability` field if you have a purchase prediction model. In FlutterFlow, read these fields from the user document to personalize the UI — show win-back offers when `churnScore > 0.7`, upsell prompts when `purchaseProbability > 0.6`.

```
const { onSchedule } = require('firebase-functions/v2/scheduler');
const { getFirestore } = require('firebase-admin/firestore');
const { BigQuery } = require('@google-cloud/bigquery');

exports.scoreUserChurnRisk = onSchedule('every 24 hours', async () => {
  const db = getFirestore();
  const bq = new BigQuery();

  const query = `
    SELECT
      userId,
      predicted_churned_probs[OFFSET(1)].prob AS churnProbability
    FROM ML.PREDICT(
      MODEL \`your_project.analytics.churn_model\`,
      (
        SELECT
          userId,
          daysSinceLastActive,
          totalSessionsLast30Days,
          featureUsageCount,
          purchaseCount,
          profileCompletionPercent
        FROM \`your_project.analytics.user_features\`
        WHERE exportedAt >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 DAY)
      )
    )
  `;

  const [rows] = await bq.query(query);
  const batch = db.batch();

  rows.forEach((row) => {
    const ref = db.collection('users').doc(row.userId);
    batch.update(ref, {
      churnScore: row.churnProbability,
      churnScoreUpdatedAt: new Date(),
    });
  });

  await batch.commit();
  console.log(`Scored ${rows.length} users`);
});
```

**Expected result:** The `users` Firestore collection shows `churnScore` and `churnScoreUpdatedAt` fields updated daily for all active users.

### 5. Trigger automated re-engagement flows based on churn score

Create a Firestore onUpdate Cloud Function triggered when a user document's `churnScore` changes. If the new score exceeds 0.7 (configurable) and the previous score was below that threshold, trigger a re-engagement action: send a push notification via Firebase Cloud Messaging (or email via SendGrid), create a Firestore document in a `reEngagementQueue` collection, or update a `showWinBackOffer` boolean on the user document. In FlutterFlow, read `showWinBackOffer` on app launch and conditionally display a personalized win-back offer screen or banner. This makes the ML predictions actionable in real time rather than just interesting numbers.

**Expected result:** Users crossing the 0.7 churn threshold receive a re-engagement notification. The FlutterFlow app shows a win-back offer on their next session.

## Complete code example

File: `bigquery_model.sql`

```text
-- Step 1: Create training dataset with churned label
CREATE OR REPLACE TABLE `your_project.analytics.training_data` AS
SELECT
  userId,
  daysSinceLastActive,
  totalSessionsLast30Days,
  featureUsageCount,
  purchaseCount,
  profileCompletionPercent,
  CASE WHEN daysSinceLastActive > 30 THEN 1 ELSE 0 END AS churned
FROM `your_project.analytics.user_features`
WHERE exportedAt < TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY);

-- Step 2: Check class balance
SELECT churned, COUNT(*) as count
FROM `your_project.analytics.training_data`
GROUP BY churned;

-- Step 3: Train churn model
CREATE OR REPLACE MODEL `your_project.analytics.churn_model`
OPTIONS(
  model_type = 'logistic_reg',
  input_label_cols = ['churned'],
  auto_class_weights = TRUE,
  max_iterations = 50
) AS
SELECT
  daysSinceLastActive,
  totalSessionsLast30Days,
  featureUsageCount,
  purchaseCount,
  profileCompletionPercent,
  churned
FROM `your_project.analytics.training_data`;

-- Step 4: Evaluate model performance
SELECT
  precision,
  recall,
  f1_score,
  roc_auc,
  log_loss
FROM ML.EVALUATE(
  MODEL `your_project.analytics.churn_model`,
  (
    SELECT * FROM `your_project.analytics.training_data`
    WHERE MOD(ABS(FARM_FINGERPRINT(userId)), 5) = 0
  )
);

-- Step 5: Get feature importance
SELECT *
FROM ML.FEATURE_IMPORTANCE(MODEL `your_project.analytics.churn_model`)
ORDER BY importance_weight DESC;

-- Step 6: Predict churn probability for current users
SELECT
  userId,
  predicted_churned_probs[OFFSET(1)].prob AS churnProbability,
  CASE
    WHEN predicted_churned_probs[OFFSET(1)].prob > 0.7 THEN 'high'
    WHEN predicted_churned_probs[OFFSET(1)].prob > 0.4 THEN 'medium'
    ELSE 'low'
  END AS churnRisk
FROM ML.PREDICT(
  MODEL `your_project.analytics.churn_model`,
  (
    SELECT
      userId,
      daysSinceLastActive,
      totalSessionsLast30Days,
      featureUsageCount,
      purchaseCount,
      profileCompletionPercent
    FROM `your_project.analytics.user_features`
    WHERE exportedAt >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 DAY)
  )
)
ORDER BY churnProbability DESC;
```

## Common mistakes

- **Training the churn model on only churned users without including retained users** — A supervised classification model needs examples of both classes — churned (label 1) and retained (label 0). If you only include churned users, the model has no way to learn what distinguishes a churned user from an active one. It will predict 'churned' for everyone. Fix: Export all users — active and churned — to the BigQuery training table. Use `auto_class_weights = TRUE` to handle any imbalance between the two classes. Aim for at least 200 examples of each class before training.
- **Running ML prediction queries client-side or exposing the BigQuery dataset to the Flutter app directly** — BigQuery queries cannot be run client-side from a Flutter app. Embedding service account credentials in a mobile app to access BigQuery directly is a critical security vulnerability — anyone can extract those credentials from the app binary. Fix: Always call BigQuery from a Cloud Function. The Cloud Function uses the Firebase project's default service account, which can be granted BigQuery Data Viewer access from the Google Cloud IAM console without any credentials in the app.
- **Scoring all users every hour instead of daily** — User behavioral features like daysSinceLastActive and sessionCount change slowly. Hourly scoring generates unnecessary BigQuery compute costs and Firestore write charges without meaningfully improving prediction freshness. Fix: Run the scoring Cloud Function once per day via Cloud Scheduler. This matches the natural granularity of daily behavioral features and keeps BigQuery costs minimal.

## Best practices

- Use `auto_class_weights = TRUE` in BigQuery ML to handle class imbalance between churned and retained users.
- Start with 5 high-signal features rather than 50 — daysSinceLastActive alone explains most churn variance.
- Evaluate model performance with AUC-ROC, not just accuracy — a model that predicts everyone as retained looks 90% accurate if 90% of users are retained.
- Store ML scores in the user's Firestore document so FlutterFlow can read them like any other field without extra API calls.
- Add a rate-limit on re-engagement triggers — never send two win-back messages within 14 days to the same user.
- Monitor model drift monthly — retrain the model every 4 weeks as user behavior patterns change.
- Log when a user who received a re-engagement message returns to the app, so you can measure the campaign's conversion rate.

## Frequently asked questions

### How many users do I need before machine learning churn prediction is useful?

You need at least 500 users with known outcomes (churned or retained) for a statistically meaningful model. With fewer than 200 examples per class, the model will overfit and its predictions on new users will be unreliable. For early-stage apps, use simpler rules (e.g., send a re-engagement email if a user has not opened the app in 14 days) until you have enough data for ML.

### What is the difference between BigQuery ML and calling OpenAI or Anthropic for predictions?

BigQuery ML trains a custom statistical model on your own user data. It learns from your specific app's behavior patterns. Large language models like GPT-4 are general-purpose text AI — they cannot predict your users' churn without being shown your historical data. For tabular predictions (numbers like session counts and days since last active), BigQuery ML or Vertex AI AutoML are the right tools, not LLMs.

### How much does BigQuery ML cost to train and run predictions?

BigQuery ML training uses the same pricing as BigQuery queries — $5 per TB processed. A table with 10,000 users and 10 features is tiny (under 10MB) — training costs pennies. Daily predictions for 10,000 users also cost under $0.01. The main cost driver is the daily Firestore batch write to update user documents — at $0.18 per 100,000 writes, 10,000 users costs $0.018/day.

### Can I use ML to predict what feature a user will want next, not just churn?

Yes. This is next-action prediction. Train a multi-class classification model where the label is the next feature the user engaged with (e.g., 'settings', 'upload', 'share'). Use recent navigation history as features. The model output is a probability distribution over possible next actions. Use the highest-probability prediction to surface contextual prompts or reorder navigation elements.

### What if my model's churn predictions are wrong for a specific user segment?

This is called model bias or segmentation error. Investigate by breaking down model performance by user cohort (new vs. old users, paid vs. free, mobile vs. web). If accuracy is low for a specific segment, train a separate model for that segment or add segment-specific features. You can also use the ML.FEATURE_IMPORTANCE function to identify which features drive predictions for different user groups.

### Do I need to retrain the model after new users join the app?

Not immediately. A model trained on existing users can score new users from day one. However, retrain monthly to incorporate the behavior patterns of newer user cohorts, which may differ from early users. If you launch a new major feature or change your onboarding, retrain immediately since user behavior will shift significantly.

---

Source: https://www.rapidevelopers.com/flutterflow-tutorials/how-to-use-machine-learning-for-predictive-analytics-in-flutterflow
© RapidDev — https://www.rapidevelopers.com/flutterflow-tutorials/how-to-use-machine-learning-for-predictive-analytics-in-flutterflow
