OneSignal Integration Documentation

Overview

The ms-notifications service now supports OneSignal as a push notification provider alongside the existing FCM (Firebase Cloud Messaging) integration. This enables multi-channel push notification delivery to maximize reach and reliability.

Key Features

Multi-Provider Push Notifications

  • Dual Provider Support: Send push notifications through both FCM and OneSignal simultaneously
  • Fallback Mechanism: If one service fails, the other can still deliver notifications
  • Channel-Specific Routing: Choose to send through specific providers or all at once

Multi-Device Support

  • Composite Primary Key: Users can register multiple devices (user_id + device_id)
  • Device Types: Support for web, iOS, Android, and other device types
  • Flexible IDs: Device ID can be any unique string (e.g., "web", "mobile-uuid-123")

Smart Token Management

  • Nullable Tokens: Devices can have FCM token, OneSignal player ID, both, or neither
  • Invalid Token Handling: Automatically marks tokens as invalid when push services report failures
  • Cleanup Strategy: Only removes tokens confirmed as invalid by the service (not based on inactivity)
  • 7-Day Grace Period: Invalid tokens are kept for 7 days before cleanup

Architecture

Push Notification Interface

type PushNotificationService interface {
    SendNotificationToUser(userID int, payload PushNotificationPayload) error
    RegisterDevice(userID int, deviceID string, token *string) error
    UnregisterDevice(userID int, deviceID string) error
    MarkTokenInvalid(userID int, deviceID string) error
    GetName() string
}

Channel Types

  • Push Channels: "fcm", "onesignal", "all"/"blast"/"push" (expands to both)
  • Email Channel: "email" (completely separate from push)
  • WebSocket: Used only for real-time data streaming, NOT push notifications

Database Schema

-- user_devices table
CREATE TABLE user_devices (
    user_id INTEGER NOT NULL,
    device_id VARCHAR(255) NOT NULL,
    device_name VARCHAR(255),
    device_type VARCHAR(50),  -- web, ios, android
    fcm_token TEXT,
    onesignal_player_id TEXT,
    token_invalid BOOLEAN DEFAULT false,
    invalid_since TIMESTAMP,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (user_id, device_id)
);

API Endpoints

Device Registration

POST /devices/register
Authorization: Bearer <token>

{
  "device_id": "web-browser-1",
  "device_name": "Chrome on MacBook",
  "device_type": "web",
  "fcm_token": "fcm-token-abc123",
  "onesignal_player_id": "player-id-xyz789"
}

Get User Devices

GET /devices
Authorization: Bearer <token>

Update Device Token

PUT /devices/:device_id/token
Authorization: Bearer <token>

{
  "fcm_token": "new-fcm-token",
  "onesignal_player_id": "new-player-id"
}

Unregister Device

DELETE /devices/:device_id
Authorization: Bearer <token>

Configuration

Environment Variables

# OneSignal Configuration
ENABLE_ONESIGNAL=true
ONESIGNAL_APP_ID=your-app-id
ONESIGNAL_API_KEY=your-api-key

# FCM Configuration (existing)
ENABLE_FCM=true
FCM_CREDENTIALS_PATH=/path/to/firebase-credentials.json
# or
FIREBASE_SERVICE_ACCOUNT_KEY={"type":"service_account"...}

Notification Channels

Sending Notifications

When creating notifications through the internal API:

{
  "user_id": 123,
  "title": "New Message",
  "message": "You have a new message",
  "channels": ["push"]  // Will send through both FCM and OneSignal
}

Channel Options

  • ["fcm"] - Send only through FCM
  • ["onesignal"] - Send only through OneSignal
  • ["push"] or ["all"] or ["blast"] - Send through both FCM and OneSignal
  • ["email"] - Send email notification (separate from push)
  • ["fcm", "email"] - Send through FCM and email

Frontend Integration

Web (Service Worker)

Both FCM and OneSignal use Web Push API. Frontend needs to:

  1. Register service worker
  2. Request notification permissions
  3. Get FCM token or OneSignal player ID
  4. Send to /devices/register endpoint

Mobile Apps

  • iOS/Android with FCM: Get FCM token from Firebase SDK
  • iOS/Android with OneSignal: Get player ID from OneSignal SDK
  • Register both tokens if using dual providers

Testing

Running Integration Tests

# Run all integration tests
./scripts/run_integration_tests.sh

# Run with coverage
./scripts/run_integration_tests.sh --coverage

# Run specific tests
go test -v ./internal/tests -run TestOneSignalService
go test -v ./internal/tests -run TestNotificationChannels
go test -v ./internal/tests -run TestDeviceEndpoints

Test Coverage

  • OneSignal service implementation
  • Multi-device registration
  • Token invalidation and cleanup
  • Multi-channel notification delivery
  • Device management endpoints
  • Channel expansion logic

Migration Notes

For Existing Systems

  1. Run migration: 001_add_onesignal_support.sql
  2. Update environment variables
  3. No changes needed to existing FCM implementations
  4. WebSocket connections remain unchanged (data streaming only)

Important Considerations

  • Push notifications work when apps are closed - don't clean up based on inactivity
  • Both providers can coexist - users can have FCM, OneSignal, or both
  • Email is a separate channel - never included in "push" or "all" broadcasts
  • WebSocket is for data updates only - not for push notifications

Error Handling

Invalid Tokens

  • Services report invalid tokens through specific error types
  • Tokens marked as token_invalid = true with invalid_since timestamp
  • Cleanup job removes tokens invalid for > 7 days
  • Temporary failures don't trigger cleanup

Service Failures

  • Each service failure is logged independently
  • Other services continue if one fails
  • Returns array of errors for debugging

Best Practices

  1. Multi-Device Registration: Allow users to register same device with updated tokens
  2. Token Refresh: Update tokens when apps refresh them
  3. Graceful Degradation: Continue with available services if one is down
  4. Channel Selection: Use "push" for maximum reach, specific channels for testing
  5. Monitoring: Track delivery rates per service to identify issues

Troubleshooting

Common Issues

  1. OneSignal Not Sending

    • Check ONESIGNAL_APP_ID and ONESIGNAL_API_KEY
    • Verify player IDs are valid
    • Check OneSignal dashboard for errors
  2. Duplicate Notifications

    • Ensure frontend doesn't register for both FCM and OneSignal browser notifications
    • Check service worker implementation
  3. Missing Notifications

    • Verify device registration successful
    • Check token_invalid status in database
    • Review service logs for errors
  4. WebSocket Confusion

    • Remember: WebSocket is NOT for push notifications
    • Used only for real-time data updates while app is open

Future Enhancements

  • Add support for additional push providers (APNs direct, Pusher, etc.)
  • Implement priority-based channel selection
  • Add delivery confirmation tracking
  • Create dashboard for push notification analytics
  • Implement rate limiting per provider