Seamless Notification Delivery System: The Pusher Solution

Feature:

Tech Stack:

Project Overview

The Seamless Notification Delivery System was designed to provide a fully automated and highly customizable push notification experience. The aim was to connect backend triggers with mobile app notifications, ensuring instant and efficient communication between users and the platform. This system was designed for a client needing an advanced notification delivery mechanism with real-time capabilities and personalized user experiences.

Workflow Overview

The following diagram illustrates the end-to-end workflow for the notification delivery system.

Workflow Diagram

Workflow Steps

1. Event Triggering and Backend Processing

The workflow begins when an Event or Trigger occurs. This can be an automated event via a cron job or a hook from an external action. The backend processes this trigger and initiates the necessary messaging through Firebase.

2. Triggering Firebase Messaging

The backend sends a trigger to Firebase Messaging, which broadcasts notifications. Firebase manages real-time data flow to ensure messages are sent to the correct users instantly.

public async sendNotification({
  registrationTokens,
  title,
  body,
  data,
}: {
  registrationTokens: string[];
  title: string;
  body: string;
  data: any;
}) {
  const message: MulticastMessage = {
    data: {
      title,
      body,
      ...data,
    },
    tokens: registrationTokens,
  };
  try {
    const response = await this.app.messaging().sendEachForMulticast(message);
    logger.info('Successfully sent message:', response);
    return response;
  } catch (error) {
    logger.info('Error sending message:', error);
    throw error;
  }
}

3. Broadcast Notification through Awesome Notifications Package

Once Firebase has processed the message, it is broadcast through the Awesome Notifications Package. This package facilitates the creation of customized notifications, allowing each notification to be tailored to specific user preferences or roles.

4. Mobile App Reception and User Data Handling

The Mobile App receives the notification and displays it according to the user’s preferences. Each notification is also saved in the local database to provide a history of received messages, improving user convenience.

Important Note

The created notifications from the backend fully depend on the data layer of the notification rather than the notification layer payload. This ensures flexibility in customizing notifications and adding additional data parameters as needed. Please refer to the JavaScript code for how the data layer is utilized.

Features and Solutions

1. Automated Trigger System

The system utilizes both manual and automated triggers. Notifications can be initiated through backend events, cron jobs, or manual actions by the platform administrators. Additionally, notifications are divided based on user roles, allowing targeted, personalized messaging that ensures the relevance of content delivered.

@pragma('vm:entry-point')
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  await NotificationService().showNotification(message);
  await ElasticServcie().logEvent(
    MessageRecievedEvent(
      timestamp: DateTime.now(),
      message: message,
      isBackgroundMessage: true,
    ),
  );
}

2. Customized Notification Channels

The notifications system allows the creation of custom channels with different sounds and visual configurations to suit specific user needs. This customization ensures that each type of notification can be easily differentiated, enhancing user experience.

final NotificationChannel highPriorityChannel = NotificationChannel(
  channelKey: 'high_priority',
  channelName: 'High Priority Notifications Channel',
  channelDescription: 'Notification channel for high priority notifications.',
  defaultColor: const Color(0xFF9D50DD),
  ledColor: Colors.white,
  playSound: true,
  importance: NotificationImportance.High,
  channelShowBadge: true,
  enableVibration: true,
  enableLights: true,
  vibrationPattern: highVibrationPattern,
  soundSource: "resource://raw/res_notification",
);

3. Integration with Firebase Messaging

We leveraged Firebase Messaging to facilitate real-time notifications. Firebase served as the bridge between the backend server and the mobile applications, broadcasting notifications quickly and reliably. This ensures that notifications reach the intended audience without delay.

FirebaseMessaging.onMessage.listen((message) async {
  await Firebase.initializeApp();
  await NotificationService().showNotification(message);
  await ElasticServcie().logEvent(
    MessageRecievedEvent(
      timestamp: DateTime.now(),
      message: message,
    ),
  );
});

4. Real-Time Delivery with Pusher

Pusher was integrated to enhance the speed and reliability of notifications, especially during times of high traffic. Pusher guarantees that every notification, whether manual or automated, is delivered in real time to all active devices.

5. Mobile App Integration

A Flutter-based Mobile App received customized notifications. Using the Awesome Notifications Package, the system created visually engaging and contextually relevant notifications that were immediately reflected on the app. Notifications were stored locally to ensure that users had easy access to recent messages.

Future<void> navigateToMessage() async {
  final String? generalAccessToken = await _getGeneralAccessToken();
  if (generalAccessToken != null && generalAccessToken.isNotEmpty) {
    await AwesomeNotifications().resetGlobalBadge();
    if (Get.isRegistered<MessagesController>()) {
      await Get.find<MessagesController>().refreshData();
    }
    if (Get.currentRoute == homePageName) {
      Get.find<HomeController>().currentTabIndex(1);
      Get.find<HomeController>().tabController.index = 1;
    } else {
      Get.toNamed(permissionsPageName, arguments: {"homeTab": 1});
    }
  }
}

Challenges and Solutions

1. Custom Notification Channels

Challenge: Creating notification channels that users can easily distinguish.
Solution: We used the Awesome Notifications package to customize sounds, visual layouts, and channel identifiers, ensuring that each type of notification stands out.

2. Integration between Firebase, Backend, and Flutter

Challenge: Establishing seamless connectivity between Firebase, backend logic, and the mobile app.
Solution: Firebase served as an intermediary that ensured all data flow was handled smoothly between the backend and the Flutter app.

3. Automating the System

Challenge: Ensuring that notifications were automated for different scenarios while maintaining a high level of personalization.
Solution: The use of cron jobs, event-based hooks, and customized user roles ensured each notification was timely, relevant, and fully automated.

Impact

The implementation of the Seamless Notification Delivery System resulted in a highly efficient and automated notification process. The platform saw reduced operational costs by leveraging a fully automated system, increased user engagement due to real-time updates, and positive feedback regarding the customization and usability of the notifications. Overall, the system created a better experience for users and provided a robust, scalable notification solution.