Skip to main content

How to track received push notifications

To track when a user receives a push notification, use the notification service extension. While you may have used this extension to customize push content, it’s also great for integrating tracking.

One of the problems with tracking pushes is the number of things you need to consider. There are multiple methods for handling notifications depending on the type (regular or silent) and the application’s state (foreground, background, or terminated). This complexity can quickly become overwhelming and difficult to manage.

The notification service extension addresses this issue by providing a single entry point to the system, regardless of the notification type or application state.

Here’s a step-by-step guide on how to track receiving a push notification.

1. Configure the payload

To ensure the notification service extension activates every time a user receives a push notification, include the mutable-content key in your notification payload and set it to 1:

{
   "aps" : {
      "mutable-content" : 1, // šŸ‘ˆ
      "alert" : {
         "title" : "The title",
         "body"  : "The body"
     },
   }
}

Per Apple:

The system executes your notification service app extension only when a remote notification’s payload contains the following information:

  • The payload must include theĀ mutable-contentĀ key with a value ofĀ 1.
  • The payload must include anĀ alertĀ dictionary with title, subtitle, or body information. TheĀ mutable-contentĀ flag is set so that the user’s device knows to run the corresponding service app extension, …

With this configuration, any type of push notification sent will first trigger the service app extension:

override func didReceive(
  _ request: UNNotificationRequest,
  withContentHandler contentHandler: 
  @escaping (UNNotificationContent) -> Void) {
  // track received notifications
}

2. Access user credentials

To track when a user receives a push notification, you will likely need to make authenticated network requests. A common method for storing user credentials is the keychain. However, you cannot access the same keychain used in the main application without first enabling keychain sharing.

Per Apple:

When you want two apps to be able to share keychain items, you can add both to the same keychain access group. Do this by enabling the Keychain Sharing capability in Xcode for each app, and adding a common string to the list of keychain groups in each case. Typically, you use the same kind of reverse DNS naming for a keychain group that you use for a bundle ID, so you might choose com.example.SharedItems

Enabling keychain sharing does not require changes to the provisioning profile.

Once enabled, you can access user credentials stored in your iOS app. Just ensure that both the main app and the extension use the same keychain access group:

let keychain = Keychain(
  service: "com.example.foobar",
  accessGroup: "com.example.shared"
)

3. Respect user privacy

Users can opt out of tracking, and you must respect their choices. While it’s common to store user consent information in user defaults, you cannot read values from the standard user defaults used in the main app. Similar to the shared keychain, you need to take additional steps.

To enable data sharing, use an app group.

Per Apple:

AnĀ app groupĀ allows multiple apps developed by the same team to access one or more shared containers. … When your app becomes a member of an app group, there are a number of APIs you can use to read and write data to that group’s shared container, such as:

  • Sharing preferences and other limited data by using theĀ ~init(suiteName:)~Ā method to access the app group’s shared user defaults database.

The app group requires changes to your provisioning profile. Add the newly created app group to your profile and regenerate it.

When initializing user defaults, use the suite name that matches the app group identifier you created:

let userDefaults = UserDefaults(suiteName: "group.com.example.mygroup")

Tracking the receipt of push notifications can be a great metric of delivery success ratio, particularly if you have your own backend solution for sending pushes. Leverage the notification service extension, utilize shared keychain access, and don’t forget to respect user privacy.