Back to blog
April 14, 2024
5 min read

Firebase In-App Messaging in Flutter

Engage users with in-app messages

Firebase In-App Messaging in Flutter

Firebase In-App Messaging helps you engage your app’s active users by sending them targeted, contextual messages. This guide will show you how to implement in-app messaging in your Flutter applications.

Why Use Firebase In-App Messaging?

Firebase In-App Messaging offers several benefits:

  • User engagement
  • Contextual messages
  • Rich content
  • Analytics integration
  • User segmentation
  • Real-time updates
  • Free messaging solution

Implementation Steps

  1. Setup Dependencies

    # pubspec.yaml
    dependencies:
      firebase_core: ^2.24.2
      firebase_in_app_messaging: ^0.6.0+18
    
  2. Configure Firebase

    Android (android/app/src/main/AndroidManifest.xml):

    <manifest>
      <uses-permission android:name="android.permission.INTERNET"/>
    </manifest>
    
  3. Create In-App Messaging Service

    class InAppMessagingService {
      final FirebaseInAppMessaging _inAppMessaging = FirebaseInAppMessaging.instance;
    
      // Initialize In-App Messaging
      Future<void> initialize() async {
        try {
          await _inAppMessaging.setMessagesSuppressed(false);
          await _inAppMessaging.setAutomaticDataCollectionEnabled(true);
        } catch (e) {
          print('Error initializing in-app messaging: $e');
        }
      }
    
      // Trigger Event
      Future<void> triggerEvent(String eventName) async {
        try {
          await _inAppMessaging.triggerEvent(eventName);
        } catch (e) {
          print('Error triggering event: $e');
        }
      }
    
      // Set User Property
      Future<void> setUserProperty(String property, String value) async {
        try {
          await _inAppMessaging.setUserProperty(property, value);
        } catch (e) {
          print('Error setting user property: $e');
        }
      }
    
      // Set Messages Suppressed
      Future<void> setMessagesSuppressed(bool suppressed) async {
        try {
          await _inAppMessaging.setMessagesSuppressed(suppressed);
        } catch (e) {
          print('Error setting messages suppressed: $e');
        }
      }
    
      // Set Automatic Data Collection
      Future<void> setAutomaticDataCollection(bool enabled) async {
        try {
          await _inAppMessaging.setAutomaticDataCollectionEnabled(enabled);
        } catch (e) {
          print('Error setting automatic data collection: $e');
        }
      }
    
      // Get Instance
      FirebaseInAppMessaging getInstance() {
        return _inAppMessaging;
      }
    }
    
  4. Create In-App Messaging Manager

    class InAppMessagingManager {
      final InAppMessagingService _inAppMessagingService = InAppMessagingService();
    
      // Initialize In-App Messaging
      Future<void> initialize() async {
        await _inAppMessagingService.initialize();
      }
    
      // Trigger Welcome Event
      Future<void> triggerWelcomeEvent() async {
        await _inAppMessagingService.triggerEvent('welcome_event');
      }
    
      // Trigger Feature Event
      Future<void> triggerFeatureEvent(String featureName) async {
        await _inAppMessagingService.triggerEvent('feature_$featureName');
      }
    
      // Set User Properties
      Future<void> setUserProperties(Map<String, String> properties) async {
        for (final entry in properties.entries) {
          await _inAppMessagingService.setUserProperty(
            entry.key,
            entry.value,
          );
        }
      }
    
      // Enable Messages
      Future<void> enableMessages() async {
        await _inAppMessagingService.setMessagesSuppressed(false);
      }
    
      // Disable Messages
      Future<void> disableMessages() async {
        await _inAppMessagingService.setMessagesSuppressed(true);
      }
    
      // Enable Data Collection
      Future<void> enableDataCollection() async {
        await _inAppMessagingService.setAutomaticDataCollection(true);
      }
    
      // Disable Data Collection
      Future<void> disableDataCollection() async {
        await _inAppMessagingService.setAutomaticDataCollection(false);
      }
    }
    
  5. Create In-App Messaging UI

    class InAppMessagingScreen extends StatefulWidget {
      @override
      _InAppMessagingScreenState createState() => _InAppMessagingScreenState();
    }
    
    class _InAppMessagingScreenState extends State<InAppMessagingScreen> {
      final InAppMessagingManager _inAppMessagingManager = InAppMessagingManager();
      bool _isLoading = false;
      bool _messagesEnabled = true;
      bool _dataCollectionEnabled = true;
    
      @override
      void initState() {
        super.initState();
        _initializeInAppMessaging();
      }
    
      Future<void> _initializeInAppMessaging() async {
        setState(() {
          _isLoading = true;
        });
    
        try {
          await _inAppMessagingManager.initialize();
        } catch (e) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('Error initializing in-app messaging: $e')),
          );
        } finally {
          setState(() {
            _isLoading = false;
          });
        }
      }
    
      Future<void> _triggerWelcomeEvent() async {
        setState(() {
          _isLoading = true;
        });
    
        try {
          await _inAppMessagingManager.triggerWelcomeEvent();
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('Welcome event triggered')),
          );
        } catch (e) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('Error triggering welcome event: $e')),
          );
        } finally {
          setState(() {
            _isLoading = false;
          });
        }
      }
    
      Future<void> _toggleMessages() async {
        setState(() {
          _isLoading = true;
        });
    
        try {
          if (_messagesEnabled) {
            await _inAppMessagingManager.disableMessages();
          } else {
            await _inAppMessagingManager.enableMessages();
          }
          setState(() {
            _messagesEnabled = !_messagesEnabled;
          });
        } catch (e) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('Error toggling messages: $e')),
          );
        } finally {
          setState(() {
            _isLoading = false;
          });
        }
      }
    
      Future<void> _toggleDataCollection() async {
        setState(() {
          _isLoading = true;
        });
    
        try {
          if (_dataCollectionEnabled) {
            await _inAppMessagingManager.disableDataCollection();
          } else {
            await _inAppMessagingManager.enableDataCollection();
          }
          setState(() {
            _dataCollectionEnabled = !_dataCollectionEnabled;
          });
        } catch (e) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('Error toggling data collection: $e')),
          );
        } finally {
          setState(() {
            _isLoading = false;
          });
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('In-App Messaging Demo'),
          ),
          body: _isLoading
              ? Center(child: CircularProgressIndicator())
              : SingleChildScrollView(
                  padding: EdgeInsets.all(16),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        'In-App Messaging Status:',
                        style: Theme.of(context).textTheme.titleLarge,
                      ),
                      SizedBox(height: 16),
                      Text('Messages Enabled: $_messagesEnabled'),
                      Text('Data Collection Enabled: $_dataCollectionEnabled'),
                      SizedBox(height: 24),
                      Center(
                        child: Column(
                          children: [
                            ElevatedButton(
                              onPressed: _triggerWelcomeEvent,
                              child: Text('Trigger Welcome Event'),
                            ),
                            SizedBox(height: 16),
                            ElevatedButton(
                              onPressed: _toggleMessages,
                              child: Text(
                                _messagesEnabled
                                    ? 'Disable Messages'
                                    : 'Enable Messages',
                              ),
                            ),
                            SizedBox(height: 16),
                            ElevatedButton(
                              onPressed: _toggleDataCollection,
                              child: Text(
                                _dataCollectionEnabled
                                    ? 'Disable Data Collection'
                                    : 'Enable Data Collection',
                              ),
                            ),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
        );
      }
    }
    

Advanced Features

  1. Message Analytics

    class MessageAnalyticsService {
      final FirebaseAnalytics _analytics = FirebaseAnalytics.instance;
    
      Future<void> logMessageImpression(String messageId) async {
        await _analytics.logEvent(
          name: 'message_impression',
          parameters: {
            'message_id': messageId,
            'timestamp': DateTime.now().toIso8601String(),
          },
        );
      }
    
      Future<void> logMessageClick(String messageId) async {
        await _analytics.logEvent(
          name: 'message_click',
          parameters: {
            'message_id': messageId,
            'timestamp': DateTime.now().toIso8601String(),
          },
        );
      }
    
      Future<void> logMessageDismiss(String messageId) async {
        await _analytics.logEvent(
          name: 'message_dismiss',
          parameters: {
            'message_id': messageId,
            'timestamp': DateTime.now().toIso8601String(),
          },
        );
      }
    }
    
  2. Message Targeting

    class MessageTargetingService {
      final FirebaseInAppMessaging _inAppMessaging = FirebaseInAppMessaging.instance;
    
      Future<void> setUserSegment(String segment) async {
        await _inAppMessaging.setUserProperty('user_segment', segment);
      }
    
      Future<void> setUserBehavior(String behavior) async {
        await _inAppMessaging.setUserProperty('user_behavior', behavior);
      }
    
      Future<void> setUserPreferences(Map<String, String> preferences) async {
        for (final entry in preferences.entries) {
          await _inAppMessaging.setUserProperty(entry.key, entry.value);
        }
      }
    }
    
  3. Message Customization

    class MessageCustomizationService {
      final FirebaseInAppMessaging _inAppMessaging = FirebaseInAppMessaging.instance;
    
      Future<void> setMessageStyle(Map<String, dynamic> style) async {
        // Implementation depends on Firebase In-App Messaging API
      }
    
      Future<void> setMessageLayout(String layout) async {
        // Implementation depends on Firebase In-App Messaging API
      }
    
      Future<void> setMessageContent(Map<String, dynamic> content) async {
        // Implementation depends on Firebase In-App Messaging API
      }
    }
    

Best Practices

  1. Message Design

    • Clear content
    • Engaging visuals
    • Proper timing
    • User context
  2. Implementation

    • Error handling
    • Performance monitoring
    • User preferences
    • Analytics tracking
  3. User Experience

    • Non-intrusive
    • Relevant content
    • Easy dismissal
    • Clear actions

Common Use Cases

  1. User Engagement

    • Welcome messages
    • Feature announcements
    • Promotional offers
    • User guidance
  2. User Onboarding

    • App introduction
    • Feature tutorials
    • Tips and tricks
    • Next steps
  3. User Retention

    • Re-engagement
    • Feedback requests
    • Update reminders
    • Special offers

Conclusion

Implementing Firebase In-App Messaging in your Flutter application provides powerful user engagement capabilities. By following these guidelines and implementing the provided examples, you can create an effective messaging system that enhances user experience and drives engagement.