# Mobile Apps – technical documentation for iOS

R**equirements**
----------------

*   App should be written in Swift and target **iOS 16**
*   App should have configured **Firebase Cloud Messaging** (link: [https://firebase.google.com/docs/cloud-messaging/ios/client](https://firebase.google.com/docs/cloud-messaging/ios/client)) to handle push notifications
*   App should have configured requests for appropriate permissions

Installation
------------

To add the package as a dependency to your Xcode project, follow the steps:

1.  Select File > Add Package Dependency and enter the repository URL  
    `[https://github.com/GetResponse/MobileSDK-IOS](https://github.com/GetResponse/MobileSDK-IOS)` 
2.  Click Add package and select your main target.
3.  Repeat the steps for the Notification Service Extension target (see [Preparation](#Preparation)).

Alternatively:

1.  Go to your main target options.
2.  Under `General > Frameworks, Libraries, and Embedded Content`, click the + button
3.  Select `Add other > Add package` dependency and follow the steps above.
4.  Repeat the steps for `Notification Service Extension` target (see Preparation).

Preparation
-----------

To fully support notifications and collect statistics, you need to add the `Notification Service Extension` target.

1.  If you don’t have it already, add a `Notification Service Extension` target:
    *   Go to `File > New > Target`.
    *   Select `Notification Service Extension`, give it a name and click `Finish`.
    *   Click `Cancel` on the next dialog that asks to activate the scheme.
2.  If you haven’t done it already, add this package to the newly created target.

Next, configure required app capabilities by going to `Signing & Capabilities > + Capability`:

1.  In main target, add:
    *   App Groups
        *   Select an existing group or create one.
    *   Push Notifications
    *   Background Modes
        *   Select Background fetch and Remote notifications
2.  In Notification Service Extension target, add:
    *   App Groups
        *   Select the same group as in the main target
    *   Push Notifications The SDK uses Firebase Cloud Messaging to handle push notifications from the GetResponse App. 

1.  Follow the steps in the official Firebase guide to [add Firebase to your project](https://firebase.google.com/docs/ios/setup). You only need the FirebaseMessaging package.
    *   Note: Initialising Firebase in your app is covered in the code snippets below. 
2.  [Upload your APN keys](https://firebase.google.com/docs/cloud-messaging/ios/client#upload_your_apns_authentication_key) to Firebase.

Usage
=====

Managing consent
----------------

*   Create a `NotificationManager class` – you will use it to manage notifications permission and request a token used for subscribing users to notifications.

    @MainActor
    class NotificationManager: ObservableObject{
        @Published private(set) var hasPermission = false
        @Published var token: String?
        
        init() {
            Task{
                await getAuthStatus()
            }
        }
        
        func request() async{
            do {
                try await UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound])
                await getAuthStatus()
            } catch{
                print(error)
            }
        }
        
        func requestToken() {
            Messaging.messaging().token { token, error in
              if let error = error {
                print("Error fetching FCM registration token: \(error)")
              } else if let token = token {
                print("FCM registration token: \(token)")
                  self.token  = token
              }
            }
        }
        
        func getAuthStatus() async {
            let status = await UNUserNotificationCenter.current().notificationSettings()
            switch status.authorizationStatus {
            case .authorized, .ephemeral, .provisional:
                hasPermission = true
            default:
                hasPermission = false
            }
        }
    }

*   Extend the `AppDelegate class` to fully support token registration and sending tokens to GetResponse.
    *   Go to [app.getresponse.com](http://app.getresponse.com/) > Web Push Notifications > Mobile apps to get the `Application ID, Secret, and Entrypoint`  
        ![](https://confluence.int.getresponse.com/download/attachments/245962642/image-2024-3-20_14-31-15.png?version=1&modificationDate=1710941475183&api=v2)

    class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate {
      func application(_ application: UIApplication,
                        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
            application.registerForRemoteNotifications()
            FirebaseApp.configure()
            Messaging.messaging().delegate = self
            UNUserNotificationCenter.current().delegate = self
            GetResponsePushNotificationService.shared.configure(secret: /*secret*/, applicationId:/*applicationId*/, entrypoint: /*entrypoint*/)
            return true
        }
     
        
        func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
              Messaging.messaging().apnsToken = deviceToken
          }
          
          
        @objc func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
            guard let token = fcmToken else {
                return
            }
            let tokenDict = ["token": fcmToken ?? ""]
            NotificationCenter.default.post(
              name: Notification.Name("FCMToken"),
              object: nil,
              userInfo: tokenDict)
          }
    }

*   Create an instance of the `NotificationManager` in your main view to use across the app   

    
    @StateObject var notificationManager = NotificationManager()

##### Available methods

*   Request system notification permission

    await notificationManager.request()

*   Check system notification permission status

    notificationManager.hasPermission

Note that the `notificationManager.hasPermission`  is a `@Published`  property

*   Request and access the [registration token](https://firebase.google.com/docs/cloud-messaging/ios/client#access_the_registration_token) to send targeted notifications to any particular instance of your app

    notificationManager.requestToken()
    notificationManager.token

Note that the `notificationManager.token`  is a `@Published`  property

The registration token may change when:

*   The app is restored on a new device
*   The user uninstalls/reinstalls the app
*   The user clears app data
*   Consent to the notifications in GetResponse with the registration token in GetResponse

    await GetResponsePushNotificationService.shared.consent(lang:/*LanguageCode*/, externalId: /*externalId*/, email: \*email*\, fcmToken: notificationManager.token!)

The consent expires after 4 weeks. Refresh the consent on every app run to prevent it from being revoked.

*   `lang`  – user language
*   `externalId`  – custom unique user ID
*   `email`  – optional user email
*   Remove the consent to stop sending notifications (e.g. on logout)

    await GetResponsePushNotificationService.shared.removeConsent()

Handling GetResponse notifications
----------------------------------

To access all data in the incoming notification use the method below. It automatically sends statistics about the state of the notification lifecycle (see Handling notification statistics).

    GetResponsePushNotificationService.shared.handleIncomingNotification(userInfo: /* userInfo */, eventType: /*EventType*/)

It returns a `NotificationHandler` object.

    public struct NotificationHandler {
        public let title: String
        public let body: String
        public let imageURL: String?
        public let action: ActionType
        public let redirectionURL: String?
        public let deeplinkPath: String?
        public let customData: [String: String]
    }
    

*   `title` – title of notification
*   `body` – message body of notification
*   `imageURL` – image url of notification (optional)
*   `action` – selected action on notification tap (see Handling actions)

    public enum ActionType {
        case openApp
        case openURL
        case deeplink
    }

*   `redirectionURL`  – URL to open for openURL action
*   `deeplinkPath` – path of deeplink for deeplink action
*   `customData`  – map (key, value) of custom properties that can be configured in notification settings in the GetResponse App

![](https://us-wd.gr-cdn.com/help/sites/9/2024/06/1623/cnfl.png)

Handling actions
----------------

There are 3 types of actions:

*   open application
*   open URL
*   open deeplink

Open deeplink action requires additional configuration. You can access the deeplink path through the `NotificationHandler.deeplinkPath` and use it to redirect the user manually after they click the notification.

Modifying notifications before they are shown
---------------------------------------------

You can modify the content of the incoming notifications with the NotificationService from the Notification Service Extension target. In the following code, it is used for handling the notification’s `showed` statistics.

    class NotificationService: UNNotificationServiceExtension {
        ...
     
        override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
            self.contentHandler = contentHandler
            bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
            if let bestAttemptContent = bestAttemptContent {
                let _ = try? GetResponsePushNotificationService.handleIncomingNotification(userInfo: bestAttemptContent.userInfo, eventType: EventType.showed)
                Messaging.serviceExtension().populateNotificationContent(bestAttemptContent, withContentHandler: contentHandler)
            }
        }
        
        ...
    }

Handling notification click
---------------------------

To handle a notification being clicked, add the following code to your AppDelegate class. This code also handles the notification’s `clicked` statistics.

       func userNotificationCenter(
          _ center: UNUserNotificationCenter,
          willPresent notification: UNNotification,
          withCompletionHandler completionHandler:
          @escaping (UNNotificationPresentationOptions) -> Void
        ) {
          completionHandler([[.banner, .sound]])
        }
        func userNotificationCenter(
          _ center: UNUserNotificationCenter,
          didReceive response: UNNotificationResponse,
          withCompletionHandler completionHandler: @escaping () -> Void
        ) {
            let userInfo = response.notification.request.content.userInfo
            let notification = try? GetResponsePushNotificationService.shared.handleIncomingNotification(userInfo: userInfo, eventType: EventType.clicked)
            completionHandler()
    }

Handling notification statistics
--------------------------------

There are 3 types of notification statistics:

*   showed
    *   can be tracked in the `didReceive`  method of the `UNNotificationServiceExtension`  class (see Modifying notifications before they are shown)
*   clicked
    *   can be tracked in the `userNotificationCenter` method of the `AppDelegate` class (see Handling notification click)
*   closed

To send notification statistics to GetResponse use the following method:

    GetResponsePushNotificationService.shared.handleIncomingNotification(userInfo: /* userInfo */, eventType: /*EventType*/)