# Troubleshooting


# Push notifications not arriving

Check notification permission

The SDK requests permission only when you explicitly call registerForRemoteNotifications. If you haven't called it yet, or the user denied the prompt, no notifications will be delivered.

To verify the current permission status, check in Settings → [Your App] → Notifications on the device.

Check the FCM token

Without a valid FCM token the device can't receive notifications. The token is registered automatically after registerForRemoteNotifications succeeds. You can verify it was received by checking UserSDK.default?.userId - it's populated after the first successful ping(), which the SDK triggers automatically when the token is ready.

Simulators don't support push notifications

Push notifications only work on a physical iOS device. This is an Apple platform limitation - simulators will never receive them. Always test push flows on real hardware.

When to call registerForRemoteNotifications

You don't have to call it at app launch. The prompt can appear at any point in your user's journey - after login, on a settings screen, wherever makes sense for your product. What matters is that you call it before you need to deliver the first notification.


# Firebase & FCM errors

Mismatch Sender ID

This error means the GoogleService-Info.plist in your app doesn't match the Firebase project you uploaded to Positive User. Make sure both point to the same Firebase project.

Steps to check:

  1. In Firebase Console, go to Project settings → Your apps and confirm the correct iOS app is selected
  2. Re-download GoogleService-Info.plist and replace the one in your Xcode project
  3. In Positive User, go to Settings → App Settings → Advanced → Mobile keys and confirm the SDK Admin key was generated from the same Firebase project

Unregistered

The device token was revoked or expired. This typically happens after a reinstall or when the app hasn't been opened in a long time. A new token is registered automatically next time the app calls registerForRemoteNotifications.

FCM token not being passed to Positive User

The SDK sends the FCM token automatically via ping() whenever the token is refreshed. If the token isn't appearing in Positive User, check:

  • registerForRemoteNotifications has been called
  • GoogleService-Info.plist is present and added to the correct target
  • FirebaseApp.configure() is not being called elsewhere in your app — the SDK handles this internally

# Push notification image not showing

If a push notification arrives without the attached image, work through these checks in order:

  1. Notification Service Extension not set up - images require a Notification Service Extension with NotificationExtensionHelper. See Push Notifications.

  2. HTTP instead of HTTPS - Apple's App Transport Security blocks non-HTTPS image URLs. Make sure the image URL uses https://.

  3. Image too large - iOS imposes a 10 MB limit on notification attachments. If the image exceeds that, the notification appears without it.

  4. Image server not responding - The extension has a short time window to fetch and attach the image. If the server is slow or unreachable, the notification displays without the image. Check that the image URL is publicly accessible.


# Events not being sent

sendEvent or trackScreen returning an error immediately after init

Both methods require a contact to exist - internally they check userId != nil. If you call them before the first ping() has completed and returned a contact ID, they'll fail immediately with a userNotExistsError.

The fix: call ping() first and send events in its completion handler, or wait until you know the contact session is established.

UserSDK.default?.ping { success, _ in
    guard success else { return }
    UserSDK.default?.sendEvent(with: "app_opened", params: [:])
}

# Push banner not visible when the app is in the foreground

This is expected behavior. When your app is active, the SDK intercepts incoming push notifications and passes only .badge and .sound to the system - no banner. Instead, Positive User delivers an in-app message for foreground communication.

If you need to show a native banner in the foreground regardless, implement RemoteNotificationDelegate and handle the presentation yourself.


# In-app message doesn't appear

In-app messages are only displayed when the app is in the foreground (applicationState == .active). If the trigger fires while the app is backgrounded or suspended, the message is silently dropped - it won't appear when the app returns to the foreground.

If you're not seeing in-app messages at all, also check:

  • registerForRemoteNotifications has been called
  • The GoogleService-Info.plist is correctly configured
  • The user exists (i.e., ping() has completed successfully)

# Compile error when using the SDK in an app extension

UserSDK is not available in app extensions - the entire class is marked @available(iOSApplicationExtension, unavailable). If you're getting a compile error in a Notification Service Extension or other extension target, this is why.

For Notification Service Extensions specifically, use NotificationExtensionHelper - it's the only SDK class available in that context. See Push Notifications.


# FAQ

What if I have two SDK Admin Keys configured in Positive User?

Positive User will use both keys to attempt delivery. Having multiple keys doesn't cause errors, but make sure all active keys correspond to Firebase projects that are still valid - an expired or deleted key will generate delivery errors in the dashboard.

Can one FCM token belong to multiple contacts?

No. When a token is assigned to contact A and the same token already exists on contact B, it's automatically removed from B and attached to A. This happens at the moment of assignment - no manual cleanup needed.

A common scenario: an anonymous contact opens the app and gets a token registered. When they log in and tracking switches to their existing identified contact, the token moves with them.

Which token gets used when a contact has multiple devices?

Positive User always delivers to the most recently registered token. If a contact uses two apps (or two devices) and both pass their tokens, the push goes to whichever app last called register() / ping(). When that app calls again, it becomes active again.

If a token is removed and the contact still has older tokens stored (from other devices or apps), the next most recent one becomes active automatically.


# Still stuck?

Check the iOS SDK sample project (opens new window) for a working reference implementation.