Firebase and FCM Token
The SDK does not include Firebase. Your app owns Firebase Cloud Messaging and passes the FCM token to the SDK, which registers it on the current contact. How push delivery works in general: Push Notifications.
Requirements
- SDK 1.0.0 or later. Versions 0.7.x bundled Firebase, see the Migration Guide.
- Firebase Cloud Messaging added to your app, see the Firebase guide.
- An APNs authentication key uploaded to the same Firebase project, see the Firebase guide.
- The same Firebase project's service account key uploaded to the Positive User panel.
Setup
-
Configure Firebase and set the messaging delegate as described in the Firebase guide.
-
Pass every token Firebase reports to the SDK:
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {guard let fcmToken else { return }UserSDK.default?.setFcmToken(fcmToken)} -
When a contact logs in, pass the token together with the identity. See Login and logout.
The SDK keeps the token only for the lifetime of the process. Pass it again on every launch, which didReceiveRegistrationToken already does in a standard Firebase setup.
After the first launch with a token, a push notification sent to this contact arrives on the device. The panel does not show the push token itself. To check that devices have one, go to Data → Contacts and filter contacts by FCM key with the condition has any value.
Ways to pass the token
All of these store the token and attach it to pings. Pick the one that matches the moment you have the token.
| When | Call | Sends a ping |
|---|---|---|
| Token known at launch | UserSDK(application:apiKey:baseURL:shouldTrackActivities:fcmToken:) | No. Call ping() yourself. |
| Token arrives or rotates | setFcmToken(_:) | Yes, except while logout is in progress |
| You ping anyway | ping(fcmToken:_:) | Yes, this call is the ping |
| Login or profile update | updateContact(_:fcmToken:_:) | Yes, contact data and token in one request |
Login and logout
At login, send the contact data and the token in one call:
let contact = Contact(userId: "12345", email: "jane@example.com")
UserSDK.default?.updateContact(contact, fcmToken: token)
Two separate calls (updateContact and then setFcmToken) send two pings, and a retried ping can reach the backend after the other one. One call avoids that.
At logout, pass the token you want to remove from the contact who is leaving:
UserSDK.default?.logout(fcmToken: token) { success, error in
// a new anonymous contact is ready
}
The anonymous contact created by logout gets the same token, so the device keeps receiving push notifications. Turning them off after logout is up to your app. Details: Contacts.
Before 1.3.0 the anonymous contact created by logout had no token, and the device received no push notifications until the next login or setFcmToken(_:). From 1.3.0 it keeps the token. A push notification sent to the logged out contact does not reach the device. If you call setFcmToken(_:) after logout only to keep push notifications, remove that call.
Firebase method swizzling
Firebase replaces some app delegate methods at runtime by default (method swizzling). The SDK works with swizzling on or off. What changes is the code your app writes.
FirebaseAppDelegateProxyEnabled in Info.plist | What your app does |
|---|---|
Not set or YES (default) | Firebase maps the APNs token to the FCM token for you. Forward notifications to the SDK as in Installation, Step 6. |
NO | Your app sets Messaging.messaging().apnsToken in application(_:didRegisterForRemoteNotificationsWithDeviceToken:) and calls Messaging.messaging().appDidReceiveMessage(_:) for incoming notifications. Forward notifications to the SDK the same way. |
The details of both modes are in the Firebase guide. In both modes, application(_:didReceiveRemoteNotification:fetchCompletionHandler:) must call UserSDK.default?.handleNotification(_:), otherwise in-app messages are not shown.
Methods
setFcmToken(_:)
Stores the FCM token and sends a ping, which registers the token on the current contact. Call it whenever Firebase reports a new token.
| Name | Type | Required | Description |
|---|---|---|---|
token | String | Yes | The FCM registration token from Firebase. |
Returns nothing. The ping goes through the SDK's request queue.
- Swift
- Objective-C
UserSDK.default?.setFcmToken(fcmToken)
[[UserSDK default] setFcmToken:fcmToken];
setFcmToken(_:) sends a ping on every call, also when the token has not changed. Earlier versions ignored a repeated token. If you call it on each launch or after each login, expect one ping per call.
The other methods that accept a token are described with their topic: ping(fcmToken:_:), updateContact(_:fcmToken:_:), logout(fcmToken:_:).
Common errors
| Symptom | Cause | Fix |
|---|---|---|
| The contact cannot be selected in a push campaign | The contact has no device with a push token: no FCM token was passed to the SDK, or the token moved to another contact that later used the same device. | Call setFcmToken(_:) from messaging(_:didReceiveRegistrationToken:). |
| Firebase reports no token or an APNs error | No APNs key in Firebase, or the Push Notifications capability is missing. | Upload the APNs key in Firebase, see the Firebase guide, and add the capability. |
| Delivery fails with a sender ID mismatch | The app uses a different Firebase project than the service account key in the panel. | Upload the service account key of the project in your app's GoogleService-Info.plist. |
No token with FirebaseAppDelegateProxyEnabled set to NO | Firebase does not know the APNs token. | Set Messaging.messaging().apnsToken in application(_:didRegisterForRemoteNotificationsWithDeviceToken:). |
| Push notifications go to the previous contact after logout | logout was called without the token. | Pass the token: logout(fcmToken: token). |
| The anonymous contact after logout cannot be selected in a push campaign | SDK earlier than 1.3.0: the anonymous ping carries no token. | Update to 1.3.0, or call setFcmToken(_:) after logout completes. |