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

How to Create a Custom Notification System with User Preferences in FlutterFlow

Build a notification preferences page with Switch toggles for each category (orders, messages, promotions, system) crossed with each channel (push, email, in-app). Store all preferences as a nested map in the user's Firestore document and save them in a single Update Document call. Register the FCM token on login and store it in the user document. Cloud Functions check the user's preferences map before sending any notification.

What you'll learn

  • How to structure a nested notificationPreferences map in the Firestore user document
  • How to build a preference toggle grid with Switch widgets for each category and channel
  • How to register the FCM push token on login and store it in the user document
  • How to write a Cloud Function that checks user preferences before sending notifications
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner7 min read25-35 minFlutterFlow Free+ (Cloud Functions require Firebase Blaze plan)March 2026RapidDev Engineering Team
TL;DR

Build a notification preferences page with Switch toggles for each category (orders, messages, promotions, system) crossed with each channel (push, email, in-app). Store all preferences as a nested map in the user's Firestore document and save them in a single Update Document call. Register the FCM token on login and store it in the user document. Cloud Functions check the user's preferences map before sending any notification.

Building Per-Category Per-Channel Notification Preferences in FlutterFlow

Users expect granular control over which notifications they receive and how. This tutorial builds a preferences page where users toggle push, email, and in-app notifications independently for each category, backed by Firestore and enforced by Cloud Functions.

Prerequisites

  • A FlutterFlow project with Firestore and Firebase Authentication configured
  • Firebase Cloud Messaging enabled in the Firebase console
  • A users collection with a document per authenticated user
  • Firebase Blaze plan for Cloud Functions deployment

Step-by-step guide

1

Add the notificationPreferences nested map structure to the Firestore user document

In the users collection, add a field notificationPreferences of type Map. The map has category keys (orders, messages, promotions, system), each containing a sub-map with channel keys (push, email, inApp) set to Boolean. Example: notificationPreferences.orders.push: true, notificationPreferences.orders.email: false, notificationPreferences.orders.inApp: true. Also add an fcmToken (String) field to the user document for push delivery. Set default values — all channels true for orders and messages, all false for promotions.

Expected result: Each user document has a notificationPreferences map with 12 boolean toggles (4 categories x 3 channels) and an fcmToken field.

2

Build the preferences page with section headers and Switch toggle rows

Create a NotificationPreferencesPage. Use a SingleChildScrollView containing a Column. For each category (Orders, Messages, Promotions, System), add a Text section header (titleMedium, bold, padding top 24). Below each header, add three Rows in the ListTile pattern: Row containing a Column (channel name Text + subtitle Text describing what it controls) and a trailing Switch widget. Create Page State booleans for all 12 toggles (e.g., ordersPush, ordersEmail, ordersInApp). Initialize them On Page Load from the current user's notificationPreferences map via a Backend Query on the user document.

Expected result: The page displays four sections with three toggles each, pre-populated with the user's current preference values.

3

Save all 12 preferences in a single Firestore Update Document call

Add a Save Preferences Button at the bottom. On tap, build the complete notificationPreferences map from the 12 Page State booleans: { 'orders': { 'push': ordersPush, 'email': ordersEmail, 'inApp': ordersInApp }, 'messages': { ... }, 'promotions': { ... }, 'system': { ... } }. Execute a single Update Document on the current user's document setting the notificationPreferences field to this map. Show a SnackBar 'Preferences saved' on success. Writing the entire map at once avoids 12 separate Firestore writes.

Expected result: Tapping Save writes all preferences to Firestore in one operation and shows a success confirmation.

4

Register the FCM push token on login and store it in the user document

In the On Page Load action of the home page (or post-login action flow), add a Custom Action that calls FirebaseMessaging.instance.getToken() to retrieve the device FCM token. Write this token to the user document's fcmToken field. Also listen for token refresh with FirebaseMessaging.instance.onTokenRefresh and update the document when the token changes. This ensures the server always has the current device token for push delivery.

Expected result: The user document contains the current device's FCM token, updated automatically on token refresh.

5

Write a Cloud Function that checks preferences before sending notifications

Deploy a Firebase Cloud Function sendNotification(userId, category, channel, title, body). The function reads the user document, checks notificationPreferences[category][channel]. If true and channel is 'push': send via admin.messaging().send({ token: user.fcmToken, notification: { title, body } }). If channel is 'email': send via a mail service. If channel is 'inApp': write to a notifications subcollection on the user document. If the preference is false, skip silently. Call this function from other Cloud Functions or Firestore triggers when events occur.

Expected result: Notifications are only delivered through channels the user has enabled for that specific category.

Complete working example

FlutterFlow Notification Preferences Setup
1FIRESTORE DATA MODEL:
2 users/{userId}
3 displayName: String
4 email: String
5 fcmToken: String
6 notificationPreferences: Map
7 orders:
8 push: true
9 email: true
10 inApp: true
11 messages:
12 push: true
13 email: false
14 inApp: true
15 promotions:
16 push: false
17 email: false
18 inApp: false
19 system:
20 push: true
21 email: true
22 inApp: true
23
24PAGE: NotificationPreferencesPage
25 Page State: ordersPush, ordersEmail, ordersInApp,
26 messagesPush, messagesEmail, messagesInApp,
27 promotionsPush, promotionsEmail, promotionsInApp,
28 systemPush, systemEmail, systemInApp (all Boolean)
29
30WIDGET TREE:
31 Scaffold
32 AppBar (title: "Notification Preferences")
33 SingleChildScrollView
34 Column (padding: 16)
35 Text "Orders" (titleMedium, bold)
36 _PrefRow("Push Notifications", "Order updates on your device", ordersPush)
37 _PrefRow("Email", "Order confirmations via email", ordersEmail)
38 _PrefRow("In-App", "Order updates in notification center", ordersInApp)
39 Divider
40 Text "Messages" (titleMedium, bold)
41 _PrefRow("Push", "New message alerts", messagesPush)
42 _PrefRow("Email", "Message digest emails", messagesEmail)
43 _PrefRow("In-App", "Messages in notification center", messagesInApp)
44 Divider
45 Text "Promotions" (titleMedium, bold)
46 _PrefRow("Push", "Sale and discount alerts", promotionsPush)
47 _PrefRow("Email", "Promotional emails", promotionsEmail)
48 _PrefRow("In-App", "Promo banners in app", promotionsInApp)
49 Divider
50 Text "System" (titleMedium, bold)
51 _PrefRow("Push", "Security and maintenance alerts", systemPush)
52 _PrefRow("Email", "Account security emails", systemEmail)
53 _PrefRow("In-App", "System notices in app", systemInApp)
54 SizedBox (height: 24)
55 Button "Save Preferences" (full width, primary)
56 On Tap Update Document users/{currentUser}
57 notificationPreferences: { full map from Page State }
58 Show SnackBar "Preferences saved"
59
60_PrefRow Pattern:
61 Row (padding: 12 0)
62 Expanded Column
63 Text (channel name, bodyLarge)
64 Text (description, bodySmall, grey)
65 Switch (bound to Page State boolean)
66 On Changed Update Page State
67
68ON PAGE LOAD:
69 1. Read current user document
70 2. Set all 12 Page State booleans from notificationPreferences map

Common mistakes when creating a Custom Notification System with User Preferences in FlutterFlow

Why it's a problem: Updating individual preference fields with separate Firestore writes on each Switch toggle

How to avoid: Update Page State on toggle, then write the entire notificationPreferences map in a single Update Document call when the user taps Save Preferences.

Why it's a problem: Not storing the FCM token in the user document after login

How to avoid: Call FirebaseMessaging.instance.getToken() on login, store it in the user document, and listen for onTokenRefresh to keep it current.

Why it's a problem: Sending notifications without checking the user's preference map in the Cloud Function

How to avoid: Always read notificationPreferences[category][channel] in the Cloud Function before sending. Skip silently if the preference is false.

Best practices

  • Store all notification preferences as a single nested map to enable atomic reads and writes
  • Default orders and messages to enabled, promotions to disabled — respect user attention from the start
  • Use a Save button rather than auto-saving each toggle to minimize Firestore writes
  • Register and refresh the FCM token on every login to handle device changes and token rotation
  • Add a Master Toggle per channel (e.g., disable all push) that sets all category push booleans at once
  • Show a subtitle on each toggle explaining exactly what notifications it controls
  • Log notification delivery attempts in a Firestore subcollection for debugging failed deliveries

Still stuck?

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

ChatGPT Prompt

I need to build a notification preferences page in FlutterFlow where users toggle push, email, and in-app notifications for each category (orders, messages, promotions, system). Show me the Firestore user document structure, preference page widget tree, save logic, and a Cloud Function that checks preferences before sending.

FlutterFlow Prompt

Create a settings page with four sections (Orders, Messages, Promotions, System). Each section has three toggle switches labeled Push, Email, and In-App. Add a Save button at the bottom.

Frequently asked questions

How do I set default notification preferences for new users?

In the sign-up action flow, after creating the user document, write the default notificationPreferences map with orders and messages enabled, promotions disabled. This ensures new users have sensible defaults.

Can I add a master toggle to disable all push notifications at once?

Yes. Add a Switch at the top of the page labeled 'Push Notifications.' On toggle off, set all four category push booleans to false in Page State. On toggle on, restore them to true.

How does the Cloud Function know which channel to use?

The calling code passes the channel parameter (push, email, or inApp) to the sendNotification function. The function reads the corresponding boolean from the user's preferences map and only sends if it is true.

What happens if the FCM token is expired or invalid?

The Cloud Function's messaging().send() call will throw a messaging/registration-token-not-registered error. Catch this error and delete the stale fcmToken from the user document so it gets refreshed on next login.

Can I schedule notification preferences to change automatically?

Not from FlutterFlow directly. You could add a 'quiet hours' feature with startHour and endHour fields on the user document. The Cloud Function checks the current time against quiet hours before sending push notifications.

Can RapidDev help build a full notification infrastructure?

Yes. RapidDev can implement push notifications with FCM, email delivery via SendGrid, in-app notification feeds, quiet hours, user segmentation, and analytics dashboards for notification performance.

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.