Skip to main content

FCM Integration

🎯 Overview

Firebase Cloud Messaging (FCM) integration enables DashClicks to send push notifications to web browsers and mobile devices. The system manages device tokens, sends multicast notifications, and tracks notification delivery status and read receipts.

Provider: Google Firebase (https://firebase.google.com/docs/cloud-messaging)
API Version: Firebase Admin SDK v11+
Integration Type: Server-side SDK with HTTP/2 push protocol

📁 Directory Structure

Documentation Structure:

fcm/
├── 📄 index.md - Integration overview and setup
├── 📄 tokens.md - Device token registration and management
├── 📄 notifications.md - Send notifications and track delivery
└── 📄 notification-management.md - List, read, and manage notifications

Source Code Location:

  • Base Path: external/Integrations/FCM/
  • Utils: Utils/send-notification.js
  • Controller: Controller/fcm.js
  • Model: Model/fcm.js, Model/fcm-notification.js
  • Routes: Routes/fcm.js

🗄️ MongoDB Collections

📚 Detailed Schema: See Database Collections Documentation

fcm.tokens

  • Purpose: Store FCM device tokens per user for push notification delivery
  • Model: shared/models/fcm-token.js
  • Primary Use: Map users to their registered device tokens (web, mobile)

Document Structure:

{
"_id": ObjectId,
"account_id": ObjectId,
"user_id": ObjectId, // Reference to User
"web_token": [ // Array of FCM tokens for web browsers
"fcm_token_string_1",
"fcm_token_string_2"
],
"createdAt": ISODate,
"updatedAt": ISODate
}

fcm.notifications

  • Purpose: Track sent notifications and read status
  • Model: shared/models/fcm-notification.js
  • Primary Use: Store notification history, delivery status, and user interactions

Document Structure:

{
"_id": ObjectId,
"account": ObjectId, // Account ID
"users": [ObjectId], // Recipient user IDs
"type": "task_assigned", // Notification type
"module": "tasks", // Module that triggered notification
"message": { // FCM response + notification content
"multicast_id": 0,
"success": 2,
"failure": 0,
"title": "New Task Assigned",
"body": "You have been assigned a new task",
"data": { /* custom payload */ },
"click_action": "https://app.dashclicks.com/tasks"
},
"read_by": [ObjectId], // Users who marked as read
"removed_by": [ObjectId], // Users who dismissed notification
"metadata": { // Module-specific metadata
"activity": {},
"task": {},
"report": {},
"order": {},
"communication": {}
},
"createdAt": ISODate,
"updatedAt": ISODate
}

🔐 Authentication & Configuration

Authentication Method: Google Application Default Credentials (ADC)

Required Environment Variables:

VariableDescriptionRequired
GOOGLE_APPLICATION_CREDENTIALSPath to Firebase service account JSON file

Credential Setup:

  1. Create Firebase project at Firebase Console
  2. Generate service account key (JSON file)
  3. Set environment variable pointing to JSON file path
  4. Firebase Admin SDK auto-initializes using credentials

Example Service Account JSON:

{
"type": "service_account",
"project_id": "dashclicks-project",
"private_key_id": "abc123...",
"private_key": "-----BEGIN PRIVATE KEY-----\n...",
"client_email": "firebase-adminsdk@dashclicks-project.iam.gserviceaccount.com",
"client_id": "123456789",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token"
}

🏗️ Architecture Overview

Key Responsibilities:

  • Device token registration and storage
  • Multicast push notification delivery
  • Notification history tracking
  • Read/unread status management
  • Module-specific notification categorization

Communication Pattern:

  • Server-to-client push via Firebase Cloud Messaging
  • HTTP/2 protocol for efficient delivery
  • Multicast messaging (send to multiple tokens simultaneously)
  • No client polling required

Token Management:

  • Web tokens stored per user (supports multiple devices)
  • Tokens added to array (supports concurrent sessions)
  • No automatic token cleanup (manual removal required)

🔗 Features & Capabilities

Core Features

🔄 Integration Data Flow

Token Registration Flow

sequenceDiagram
participant Client as Web/Mobile Client
participant API as FCM Controller
participant DB as MongoDB (fcm.tokens)
participant FCM as Firebase SDK

Client->>Client: Initialize FCM SDK
Client->>Client: Request notification permission
FCM-->>Client: Generate FCM token

Client->>API: POST /v1/e/fcm/web {token}
API->>DB: Find existing tokens by user_id

alt Tokens exist
API->>DB: Add token to web_token array
else No tokens
API->>DB: Create new document with token
end

DB-->>API: Token saved
API-->>Client: Success response

Notification Sending Flow

sequenceDiagram
participant Service as Internal Service
participant API as FCM Controller
participant TokenDB as MongoDB (fcm.tokens)
participant NotifDB as MongoDB (fcm.notifications)
participant FCM as Firebase Admin SDK
participant Device as User Device

Service->>API: POST /v1/e/fcm/send {users, notification}
API->>TokenDB: Find tokens for users
TokenDB-->>API: Return token arrays

API->>API: Flatten tokens from all users
API->>FCM: sendEachForMulticast(tokens, notification)
FCM->>Device: Push notification via HTTP/2
FCM-->>API: Delivery response (success/failure counts)

API->>NotifDB: Save notification + delivery status
API-->>Service: Success response

Notification Listing Flow

sequenceDiagram
participant Client as Web Client
participant API as FCM Controller
participant DB as MongoDB (fcm.notifications)

Client->>API: GET /v1/e/fcm?page=1&limit=25
API->>DB: Find notifications for user
API->>DB: Count total notifications
API->>DB: Count unread notifications

DB-->>API: Notification list + counts
API->>API: Add is_read flag per notification
API-->>Client: JSON with data + pagination + unread_count

🔗 API Endpoints

Token Management

EndpointMethodDescriptionAuth Required
/v1/e/fcm/webPOSTRegister device token

Notification Operations

EndpointMethodDescriptionAuth Required
/v1/e/fcm/sendPOSTSend notification to users
/v1/e/fcmGETList user notifications
/v1/e/fcm/readPUTMark notifications as read

🚨 Error Handling

Common Error Scenarios:

  1. Missing Token:

    • Returns 400 when token not provided in request body
    • Message: "Token not provided. (required)"
  2. Firebase Initialization Failed:

    • Occurs when GOOGLE_APPLICATION_CREDENTIALS not set or invalid
    • Application fails to start
  3. Invalid Tokens:

    • Firebase returns per-token delivery status
    • Failed deliveries tracked in failure count
    • System doesn't auto-remove invalid tokens
  4. No Registered Tokens:

    • Notification marked as sent but no actual delivery
    • Success response returned (not treated as error)

Error Response Format:

{
"success": false,
"errno": 400,
"message": "Error description"
}

📊 Monitoring & Logging

Delivery Tracking:

  • Success/failure counts stored in notification document
  • Per-message ID returned in results array
  • No automatic retry for failed deliveries

Read Status Tracking:

  • read_by array tracks which users read notification
  • removed_by array tracks dismissals
  • Unread count calculated per query

Performance Considerations:

  • Multicast messaging reduces API calls
  • Maximum 500 tokens per multicast batch (Firebase limit)
  • No rate limiting enforced by DashClicks layer

⚠️ Important Notes

  • 🔐 Service Account Required: Must have valid Firebase service account JSON file
  • 📱 Client Integration: Clients must implement FCM SDK to generate tokens
  • 🔄 Token Updates: Same token can be registered multiple times (uses $addToSet)
  • 📊 No Automatic Cleanup: Invalid tokens remain in database until manually removed
  • 🎯 Multicast Limit: Firebase limits multicast to 500 tokens per request
  • 📝 Notification History: All sent notifications stored permanently (no TTL)
  • 🔔 Module-Based: Notifications categorized by module (tasks, orders, reports, etc.)
  • 👥 Multi-User: Single notification can be sent to multiple users simultaneously
💬

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:30 AM