Tutorial11 min read

Push notifications in Capacitor with Firebase

A complete guide to adding push notifications to a Capacitor app with Firebase Cloud Messaging — iOS and Android setup, permissions, tokens, and handling taps — plus shipping the JS side over the air.

Push notifications are table stakes for a real mobile app, and Firebase Cloud Messaging (FCM) is the standard way to deliver them to both iOS and Android from a Capacitor app. This guide walks through the full setup — native config, permissions, tokens, and handling taps — and shows where OtaKit lets you iterate the notification logic without a rebuild.

Split the work in your head: the native wiring (FCM, APNs, the push plugin) is a one-time store build. The notification handling logic — routing a tap, formatting content, deciding what to show — lives in your web layer and ships over the air.

1. Install the push plugin

npm install @capacitor/push-notifications
npx cap sync

2. Set up Firebase

  • Create a Firebase project and register your iOS and Android apps.
  • Add google-services.json to the Android project and GoogleService-Info.plist to the iOS project.
  • For iOS, upload your APNs key to Firebase — FCM delivers to iOS through APNs.

3. Request permission and register

import { PushNotifications } from '@capacitor/push-notifications';

const perm = await PushNotifications.requestPermissions();
if (perm.receive === 'granted') {
  await PushNotifications.register();
}

PushNotifications.addListener('registration', (token) => {
  // send token.value to your backend to target this device
  saveDeviceToken(token.value);
});

4. Handle received notifications and taps

PushNotifications.addListener('pushNotificationReceived', (notification) => {
  // app in foreground — show your own in-app UI
});

PushNotifications.addListener('pushNotificationActionPerformed', (action) => {
  // user tapped — route to the right screen
  router.navigate(action.notification.data.route);
});

This routing logic is pure web-layer code. When you change how a tap routes, or tweak the in-app presentation, ship it over the air:

otakit upload --release production

Common gotcha: iOS push requires the Push Notifications capability and a real device (the simulator won't receive remote push). Android needs the notification permission on API 33+. Both are native concerns — get them right in the store build.

Where to go next

See Setup to add OtaKit alongside the push plugin, and deep links since notification taps and deep links often share routing.

Related docs