Minimal version of iOS

The current version of the FollowAnalytics SDK works with iOS version 8 and above.

Prerequisites

In this section, we explain how to get started with FollowAnalytics SDK for iOS. You can access your app from the administration page of the platform. Before you start, you need to do all the following: add the push certificate and generate the API Key.

Registering a new app

FollowAnalytics enables you to synchronize directly with you app store, therefore your app should already be available. However, if this is not the case, you can register you app by following the instructions here

Add a push certificate for notifications

FollowAnalytics requires a valid p12 or p8 certificate in order to communicate with Apple Push Notification Services (APNS). This certificate is generated for a unique Application Identifier (App ID).

Certificates have an expiration date

Your certificates are only valid for a year. Remember to update them, otherwise you will not be able to send push notifications any more.

We recommend to use p8 file

we strongly recommend using p8 file because you need to generate only one p8 to all your apps.

Generate and import a .p12 push certificate

To generate your push certificate:

  1. Connect to your developer portal, and go to the App IDs.

  2. Click on your Application Identifier to edit your app configuration if it exist or Create a new App ID by clicking in the + button in the top of page.

  3. In the list of Capabilities, check the Push Notifications box

  4. Click Edit to display the window for Apple Push Notification service SSL Certificates

  5. Create a certificate by clicking the Create button

  6. Upload your Certificate Signing Request (create a Certificate Signing Request here) and click continue

  7. Click Download button to create your certificate, open the Keychain Assistant app and locate that certificate

  8. From the Keychain Assistant app, click the certificate line and export the .p12 file by right-clicking on the profile below the certificate. Enter a password for your certificate.

  9. Go to the Administration page, upload the .p12 file and enter the password you've entered on the previous step.

Do not forget to ensure your provisioning profile has the Push Notifications service enabled by expanding it from the list in your developer portal.

Generate and import a .p8 push certificate

To generate your server key (p8)

  1. Connect to your developer portal.

  2. Click on your Keys tab.

  3. Click in the + button in the top of page to add a new Key.

  4. Add a Key Name.

  5. Check the Apple Push Notification service (APNs)

  6. Click Continue.

  7. Download the .p8 file. (You must download the p8 file in this step because this is your unique chance to download it)

  8. Go to the Identifiers Tab.

  9. Click on your Application Identifier to edit your app configuration if it exist or Create a new App ID by clicking in the + button in the top of page.

  10. In the list of Capabilities, check the Push Notifications box

  11. Go to the Administration page, upload the .p8 file and click in Proceed.

  12. Enter your Key ID and Issuer Key. You can find you Key ID in the Keys tab in the developer account and the Issuer Key is you team ID and you can find it by clicking in the View Membership in the developer account also.

Do not forget to ensure your provisioning profile has the Push Notifications service enabled by expanding it from the list in your developer portal.

Generate the API key

Now that your application is registered, you can generate its API key:

  1. Access the application page and click on the "Manage API keys" tab

  2. Click the "+ Generate new API key" button.

Add API key

The API key is now active. It can now be used in your application and continue to the integration of the SDK!

Integration

In this section, you will find the steps for integrating the SDK in your app:

Once the integration is finished, we highly recommend you test the setup. You will find out how to test your setup in this section. Then, you can start tagging events and saving attributes in your app.

Installation with Cocoapods

Starting with CocoaPods

The best way to install the SDK is with CocoaPods. This will allow you to easily update the SDK when new versions are released. If you have not installed CocoaPods yet, you may refer to the this site, where you can install Cocoapods (1.1.0 or later).

Before you start, be sure to have a Podfile. You could create one by writing pod init in your terminal in your project. To open your Podfile, you could find it in your Workspace, or by writing open -a Xcode Podfile in the terminal.

  1. Add pod 'FollowAnalytics','~> 6.3.0' in the Podfile (see screenshot below)

  2. Run pod repo update from the command line. This will enable CocoaPods to detect the latest available version of FollowAnalytics.

  3. Run pod install

Now FollowAnalytics is successfully installed.

Use the .xcworkspace file

To open your project with Xcode, use the .xcworkspace file generated by CocoaPods.

Initialize the SDK with your API key

Prerequisites: Generate your API key

If you haven't already, you can generate the API of your app by following the steps here.

  1. Import the FollowAnalytics framework in your AppDelegate.

  2. Inside your UIApplicationDelegate implementation, create a configuration object and set the required fields

  3. Just below the configuration object, start the SDK

Your code should look like this:

#import <FollowAnalytics/FollowAnalytics.h>

@implementation AppDelegate
- (BOOL)application:(UIApplication*)application
  didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
  // ....
  // as early as possible
  FollowAnalyticsConfiguration* configuration = [FollowAnalyticsConfiguration
    configurationWith:^(FollowAnalyticsConfiguration* _Nonnull config) {
      config.apiKey = @"YOUR API KEY";
      config.isVerbose = true; // Before publishing the app, set isVerbose to false
    }];
  [FollowAnalytics startWithConfiguration:configuration startupOptions:launchOptions];
  //....
}
// ..
@end
import FollowAnalytics

class AppDelegate: UIResponder, UIApplicationDelegate {
  func application(_ application: UIApplication, didFinishLaunchingWithOptions
    launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // ....
    let configuration = FollowAnalyticsConfiguration.init { (config) in
      config.apiKey = "YOUR API KEY"
      config.isVerbose = true // Before publishing the app, set isVerbose to false
    }
    FollowAnalytics.start(with: configuration, startupOptions: launchOptions)
    // ....
  }
}

You can configure the SDK with all the available parameters which you can find here.

Register for push notifications

Preparing your project for FollowAnalytics

These methods and settings are necessary to your app in order to use the FollowAnalytics SDK. These include:

  • Adding push notification capabilities in the project settings
  • Calling the push notification method for displaying push notifications
  • Enabling device geolocation
  • Defining the URL Scheme for acquiring the device ID

Push notification capabilities

In the Capabilities tab of your Xcode Project:

  1. Enable Push Notifications by setting the switch to ON.

  2. Enable the Remote notifications capability in the Background Modes:

    This will ensure that FollowAnalytics can detect uninstalls and send Silent Push Notifications.

Display the notifications

On iOS, you are required to add a permission from the user to send them push notifications. You can do this by calling the requestNotificationCenterDefaultAuthorisation method.

[FollowAnalytics requestNotificationCenterDefaultAuthorisation]
FollowAnalytics.requestNotificationCenterDefaultAuthorisation()

Without this request, notifications will be sent to the app as a silent notification.

Enable device registration

Registering devices on iOS

Registering devices is enables users of the FollowAnalytics platform to test their campaigns. Unlike Android, you need to declare the URL scheme on your app on iOS so the users can use this feature.

To allow the user to retrieve the device ID for testing from the platform, declare a URL Scheme in the info tab of your Xcode project using the bundleId of your app as URL Scheme:

  1. Go to the info tab of the project targets.

  2. At the bottom you select the subsection called "URL Types".

  3. Click the + sign at the bottom.

  4. Add the bundle ID of your app in both identifier and URL Schemes fields

URL Scheme

Once configured, your FollowAnalytics device ID can be obtained by opening the following URI: YourURLScheme://followanalytics.com/deviceId, with YourURLScheme as the application bundle ID.

Now, users can add devices to the FollowAnalytics platform without knowing the device ID. From the platform, they will send an email a link that will open the app and allow them to register the device.

Analytics

The FollowAnalytics SDK allows you to tag both events and attributes. In this section, we explain how to use both of them in your app and benefit from analytics capabilities. If you are unsure about the difference, you may refer to the corresponding FAQ entry.

Data does not display on the platform with isVerbose as true

When your app runs with isVerbose as true mode or in a simulator, the data is automatically sent as development logs. Development logs are not sent to the server and will not be displayed on the FollowAnalytics platform. Therefore, always release with isVerbose as false.

Tagging Events and Errors

You can tag Events and Errors in your app by calling the related logging methods provided by the SDKs. These logs are then received and visible on the FollowAnalytics platform.

Tagging best practices

To successfully empower your team with FollowAnalytics make sure your logs are relevant, you can find our recommendations and tagging best practices in the FAQ.

Regular, native event tagging

To tag an Event or an Error, send a log using the following SDK methods:

+ (void)logEvent:(nonnull NSString*)name details:(nullable id)args;
+ (void)logError:(nonnull NSString*)name details:(nullable id)args;
FollowAnalytics.logEvent(name: String, details: Any?)
FollowAnalytics.logError(name: String, details: Any?)

Use the name as the unique identifier of your log. Use the details argument section to pass specific context to your log.

To be valid, the details argument must be one of the following:

Passing any invalid details argument to those methods will:

For example, you can log the display of a view by writing the following:

[FollowAnalytics logEvent:@"Product view" details:@"Product reference"];
[FollowAnalytics logEvent:@"In App purchase completed" details:@"Full pack"];

NSDictionary *detail = @{ @"reference": @"RF1672", @"payment_mode" : @"credit_card", @"color" : @"red"};
[FollowAnalytics logEvent:@"Product purchased" details:detail];
FollowAnalytics.logEvent("Product view", details: "Product reference")
FollowAnalytics.logError("In App purchase completed", details: "Full pack")

let detail = ["reference": "RF1672", "payment_mode": "credit_card", "color": "red"]
FollowAnalytics.logEvent("Product purchased", details: detail)

If you have set FollowAnalyticsConfiguration.isVerbose to true at initialization, the SDK will acknowledge the log validity by printing the complete log information into the console when logEvent() or logError() is called.

If you try to send a log which size exceeds 60Kb, it will not be sent to the server and an error message will be printed in the console.

Events can be renamed on the FollowAnalytics platform

The name that you give to your event here can be overridden in the FollowAnalytics platform. For more information, reach out to your Customer Success Manager or message support.

Tagging from a web view

If your app contains web views, you can also tag events and errors from within your HTML/JS code. Our solution integrates itself inside a WKWebView. Here, you have a selection of JavaScript methods that you can use:

JavaScript

FollowAnalytics.logError('err1','str value')
FollowAnalytics.logEvent('event1','str value')

The complete list of JavaScript methods is documented in FAWKWebViewJSBridge.h .

In order to use it, you need to do the following:

  1. Adopt WKUIDelegate protocol in your object of choice, typically a UIViewController.

    @interface ViewController <WKUIDelegate>
    
    class ViewController: UIViewController, WKUIDelegate {
    
  2. At the initialization of the hosting view controller, keep a strong reference to our FAWKWebViewJSBridge:

    self.webViewJSBridge = [[FAWKWebViewJSBridge alloc] init];
    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
    
    var webViewJSBridge: FAWKWebViewJSBridge?
    var webView : WKWebView?
    
  3. Provide the configuration, make sure that you use the configuration for the WKWebView and set your controller as a UIDelegate

    [self.webViewJSBridge addToConfiguration:configuration];
    WKWebView* webView = [[WKWebView alloc] initWithFrame:frame configuration:configuration];
    webView.UIDelegate = self;
    
    override func viewDidLoad() {
      self.webViewJSBridge = FAWKWebViewJSBridge()
      let configuration = WKWebViewConfiguration()
      self.webViewJSBridge?.add(to: configuration)
      let frame = self.view.frame
      webView = WKWebView.init(frame: frame, configuration: configuration)
      webView?.uiDelegate = self
    }
    
  4. Implement the delegate method

    - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler{
    if([prompt hasPrefix:@"FollowAnalytics"]){
      [self.webViewJSBridge webView:webView runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText initiatedByFrame:frame completionHandler:completionHandler];
      return;
    }
    
    func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
     if prompt.hasPrefix("FollowAnalytics") {
             self.webView(webView, runJavaScriptTextInputPanelWithPrompt: prompt, defaultText: defaultText, initiatedByFrame: frame, completionHandler: completionHandler)
     }
    }
    

User ID and attributes

The User ID is a string that you provide to the SDK to uniquely identify a user of your app. It can be an e-mail address, an identifier from your own backend, a phone number, or anything else that could allow you to identify a user profile. Customer attributes (like first name, date of birth) can be associated to this user or a device. This section covers the integration of a user ID and customer attributes. The SDK allows you to set values for predefined as well as custom attributes which you can make yourself.

You don't need a user ID to set attributes

Attributes are tied to the device when no user ID is provided. If a user ID is set, a profile is created server-side and can be shared across apps.

In both cases, attributes can be used in segments and campaigns to target users.

User ID

To get or set the user ID, use the following methods available on FollowAnalytics class:

+ (void)setUserId:(nullable NSString*)userId;
+ (nullable NSString*)getUserId;
open class func setUserId(_ userId: String?)
open class func getUserId() -> String?

Predefined attributes

The SDK allows to set values for both custom and predefined attributes.

For predefined attributes, the SDK has the FollowAnalyticsUserAttributes protocol with the following properties:

- (void)setFirstName:(nullable NSString*)firstName;
- (void)setLastName:(nullable NSString*)lastName;
- (void)setEmail:(nullable NSString*)email;
- (void)setDateOfBirth:(nullable NSDate*)dateOfBirth;
- (void)setGender:(FollowAnalyticsGender)gender;
- (void)setCountry:(nullable NSString*)country;
- (void)setCity:(nullable NSString*)city;
- (void)setRegion:(nullable NSString*)region;
- (void)setProfilePictureUrl:(nullable NSString*)profilePictureUrl;
- func setFirstName(firstName : String?)
- func setLastName(lastName: String?)
- func setEmail(email : String?)
- func setDateOfBirth(dateOfBirth : Date?)
- func setGender(gender : FollowAnalyticsGender)
- func setCountry(country : String?)
- func setCity(region : String?)
- func setRegion(city : String?)
- func setProfilePictureUrl(profilePictureUrl : String?)

The FollowAnalyticsUserAttributes is implemented by FollowAnalytics.userAttributes so you can use it.

They are "predefined" in the sense that they will be attached to default fields on your user profiles.

For example, to set user Joe's city to "Paris", you would proceed as follows:

[FollowAnalytics.userAttributes setFirstName:@"Joe"];
[FollowAnalytics.userAttributes setCity:@"Paris"];
FollowAnalytics.userAttributes.setFirstName("Joe")
FollowAnalytics.userAttributes.setCity("Paris")

Custom attributes

In addition to predefined attributes, you can add your own custom attributes to your code.

Always double check your custom attribute types

When a value for an unknown attribute is received by the server, the attribute is declared with the type of that first value.

If you change the type of an attribute in the SDK, values might be refused server-side. Ensure the attribute types match. This could be done by comparing with the ones you have in the profile data section of the product.

Set a custom attribute

To set your custom attributes, you can use these additional methods from FollowAnalyticsUserAttributes protocol that are adapted for each type:

- (void)setInteger:(NSInteger)integerValue forKey:(nonnull NSString*)key;
- (void)setDouble:(double)doubleValue forKey:(nonnull NSString*)key;
- (void)setString:(nonnull NSString*)string forKey:(nonnull NSString*)key;
- (void)setBoolean:(bool)boolean forKey:(nonnull NSString*)key;
- (void)setDate:(nonnull NSDate*)date forKey:(nonnull NSString*)key;
- (void)setDateTime:(nonnull NSDate*)dateTime forKey:(nonnull NSString*)key;
- (void)clear:(nonnull NSString*)key;
- (void)add:(nonnull NSSet<NSString*>*)values toSet:(nonnull NSString*)key;
- (void)remove:(nonnull NSSet<NSString*>*)values toSet:(nonnull NSString*)key;
- (void)clearSet:(nonnull NSString*)key;
- func setInteger(integerValue: Int, forKey: String)
- func setDouble(doubleValue : Double, forKey: String)
- func setString(string: String, forKey: String)
- func setBoolean(boolean: Bool, forKey: String)
- func setDate(date: Date, forKey: String)
- func setDateTime(dateTime: Date, forKey: String)
- func clear(key: String)
- func add(values: Set<String>, toSet: String)
- func remove(values: Set<String>, toSet: String)
- func clearSet(key: String)

For example, to set the user's occupation:

[FollowAnalytics.userAttributes setString:@"Taxi Driver" forKey:@"occupation"];
FollowAnalytics.userAttributes.setString("Taxi Driver", forKey: "occupation")
Delete a custom attribute value

You can delete the value of an attribute using its key. For example, to delete the user's job:

[FollowAnalytics.userAttributes  clear:@"occupation"];
FollowAnalytics.userAttributes.clear("occupation")
Set of Attributes

You can add or remove an item to or from a set of attributes.

To add an item:

NSSet *set = [NSSet setWithObjects:@"apple", @"strawberry", @"lemon", nil];
[FollowAnalytics.userAttributes add:set toSet:@"fruits"];
set = [NSSet setWithObjects:@"lemon", nil];
[FollowAnalytics.userAttributes remove:set toSet:@"fruits"]; // Removes "lemon" from set of fruits.
[FollowAnalytics.userAttributes clearSet:@"fruits"]; // Removes all the items from the set.
var set : Set = ["apple","strawberry","lemon"]
FollowAnalytics.userAttributes.add(set, toSet: "fruits")
set = ["lemon"]
FollowAnalytics.userAttributes.remove(set, toSet: "fruits") // Removes "lemon" from set of fruits.
FollowAnalytics.userAttributes.clearSet("fruits") // Removes all the items from the set.

To remove an item:

[FollowAnalytics.userAttributes remove:@"lemon" toSet:@"fruits"]; // Removes "lemon" from set of fruits.
FollowAnalytics.userAttributes.remove(["lemon"], toSet: "fruits")// Removes "lemon" from set of fruits.

And to clear a set:

[FollowAnalytics.userAttributes clearSet:@"fruits"]; // Removes all the items from the set.
FollowAnalytics.userAttributes.clearSet("fruits")// Removes all the items from the set.

For further information, refer to the SDK header file.

Opt-in Analytics

The SDK can be configured to no longer track user information. This is what we call to opt-out of analytics. Conversely, if the user allows the app to collect his data, he has to opt-in analytics. To inspect and set the opt-in state, call the following methods on FollowAnalytics class:

+ (BOOL)getOptInAnalytics;
+ (void)setOptInAnalytics:(BOOL)optInAnalytics;
FollowAnalytics.getOptInAnalytics()
FollowAnalytics.setOptInAnalytics(true)

Additionally, if the opt-in by default policy doesn't suit your use case you can change it by setting the optInAnalyticsDefault on FollowAnalyticsConfiguration.

@property(nonatomic, readonly, assign) BOOL optInAnalyticsDefault;

GDPR

You can record when the user expresses his demand to access or delete his personal data by calling one of the following methods:

[FollowAnalytics.GDPR requestToAccessMyData]
[FollowAnalytics.GDPR requestToDeleteMyData]
FollowAnalytics.gdpr.requestToAccessMyData()
FollowAnalytics.gdpr.requestToDeleteMyData()

The SDK will record all requests and send them to FollowAnalytics servers as soon as network conditions allow it. The SDK remembers pending requests between app restarts.

Campaigns

Prerequisites

Before you start, be sure that the SDK is properly initialized. This includes registration for push notifications, which is covered in the integration section.

Campaigns are the push notifications and in-app messages you will be sending from the FollowAnalytics platform. In this section, we cover all you need for your app to display them, and how you can add the features the fully take of advantage the SDK's capabilities.

Rich push notifications

Rich push notifications on iOS

Rich push notifications are notifications with embedded rich media (images, GIFs, videos). They are only available on iOS 10 and above. Should a user have a version under iOS 10, they will receive rich push notifications but not be able to see the rich media included.

Notification Service Extension Framework

Requirement

To make your app able to receive rich notifications & badge incrementation, follow these steps:

  1. In your xCode project, add a new target.



  2. Select Notification Service Extension, give it a name and confirm. Then when prompted, activate the scheme.



Installation from Cocoapods

If you want to use Cocoapods to manage your external dependencies, simply add the following line to your Podfile only in the extension target:

pod 'FANotificationExtension', :source => 'https://github.com/followanalytics/fa-pod-spec.git'

If you don't have a podfile yet, open a console and do a pod init in your project directory.

Then, you only need to update your Cocoapods dependencies:

pod install
Manual installation

If you want to manually integrate the .framework, extract the FollowAnalytics SDK archive and copy the FANotificationExtension.framework into your project directory.

  1. Select the target of your main app, in Build Phases

    1. Press the + button, and select New Copy File Phase.
    2. Change the destination to Frameworks.
    3. Click in add other.
    4. Add the FANotificationExtension.framework file that you previously copied into your project directory.
    5. Uncheck Copy items if needed box.
  2. Still in the Build Phases

    1. Press the + button, and select New Run Script Phase.
    2. Add this script:
      bash "PATH_TO_YOUR_PROJECT_DIRECTORY/FANotificationExtension.framework/strip-frameworks.sh"
      
  3. In Build Settings -> Framework Search Paths entry, add the path to where the FANotificationExtension.framework is located (actually your project directory).

Initialise

Copy and paste the following implementation in the NotificationService.m file of the extension you created

#import “NotificationService.h”
#import <FANotificationExtension/FANotificationExtension.h>

@interface NotificationService ()

@property(nonatomic, strong) void (^contentHandler)(UNNotificationContent* contentToDeliver);
@property(nonatomic, strong) UNMutableNotificationContent* bestAttemptContent;

@end

@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest*)request
   withContentHandler:(void (^)(UNNotificationContent* _Nonnull))contentHandler {
    self.contentHandler = contentHandler;
    self.bestAttemptContent = [request.content mutableCopy];
    [FANotificationService
        getFAContentIfNeededWithRequest:request
                            bestContent:self.bestAttemptContent
                            appGroup:@"group.your.identifier"
                            completion:^(UNMutableNotificationContent* _Nullable newContent) {
                            NSLog(@"NotificationService: %@", request);
                            // Modify the notification content here...

                            self.contentHandler(newContent);
                            }];
}

- (void)serviceExtensionTimeWillExpire {
    // Called just before the extension will be terminated by the system.
    // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the
    // original push payload will be used.
    self.contentHandler(self.bestAttemptContent);
}
@end
import UserNotifications
import FANotificationExtension

class NotificationService: UNNotificationServiceExtension {

    var contentHandler: ((UNNotificationContent) -> Void)?
    var bestAttemptContent: UNMutableNotificationContent?

    override func didReceive(_ request: UNNotificationRequest,
                                withContentHandler contentHandler:
                                @escaping (UNNotificationContent) -> Void) {
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

        if let bestAttemptContent = bestAttemptContent,
        let contentHandler = self.contentHandler {
        // Modify the notification content here...

            FANotificationService.getFAContentIfNeeded(with: request,
                                                        bestContent: bestAttemptContent,
                                                        appGroup: "group.your.identifier") {
                                                        (newContent) in
                                                        if let newC = newContent {
                                                            contentHandler(newC)
                                                        }
            }
        }
    }

    override func serviceExtensionTimeWillExpire() {
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }
}
Configuration

To complete the extension configuration, the extension needs to be matched with the app. To do so, set the app as the Executable of the extension:





Badge Management

Prerequisites

For using this feature, there are 3 prerequisites:

  • Have the Notification Service Extension with the FollowAnalytics extension framework. More information here
  • Create an app group between your app and the extension.
  • Specify your app group in the init (configureWithId...)

Badges are the numbers displayed on the icon of the app, indicating to user that the app has new information. In order to enable badges, add the following:

[FABadge enable];
FABadge.enable()

By default, the value of the badge is incremented by 1 when a push is received. In order to update that value differently or reset the value, implement the following methods:

[FABadge setBadge:INTEGER]; // Set the value of the icon badge number
[FABadge updateBadgeBy:INTEGER]; // Update the value of the icon badge number
[FABadge badge]; // Get the value of the icon badge number
FABadge.setBadge(Int) // Set the value of the icon badge number
FABadge.updateBadgeBy(Int) // Update the value of the icon badge number
FABadge.badge // Get the value of the icon badge number

Enable badges in rich push notifications

If you need to increase the badge number with a push:

  1. Create an App Groups between your main App and you extension.
  2. Enable app group capability in the App IDs of your main application and your notification service extension. The app group should be the same in main application and notification service extension.
  3. Activate the app group capability in XCode project configuration, and add the corresponding app group bundle.
  4. Re-download all the provisioning profiles for application and notification service extension.

Enable geofencing campaigns

Geofencing campaigns are campaigns that are triggered when the user enters or leaves a specific location. The FollowAnalytics SDK will only have access to the device's location if it has the give the permission. If you wish to use this feature, implement the enableGeofencing method.

[FollowAnalytics enableGeofencing]
FollowAnalytics.enableGeofencing()

When this method is called, the user will see a dialog asking the permission of the app to use location analytics.

Deep-linking: URL, Parameters

Campaigns created through FollowAnalytics allow to deep link to content in an app. This could be for your app or a third party. For this you can use specific deep-linking features you will find explained here.

Handling Notifications received

You can handle the reception of a notification by implementing the onNotificationReceived callback in FollowAnalyticsConfiguration. This allows you to access notification information like deep-link url or key/value pairs and perform specific actions accordingly.

FollowAnalyticsConfiguration* configuration = [FollowAnalyticsConfiguration
    configurationWith:^(FollowAnalyticsConfiguration* _Nonnull config) {
        config.onNotificationReceived = ^(FAMessage * _Nonnull message){
            // YOUR BEHAVIOR
        }
    };
}];
let configuration = FollowAnalyticsConfiguration.init { (config) in
    config.onNotificationReceived = { (message) in
        // YOUR BEHAVIOR
    }
}

All the content of the notification is provided in the message argument. You will find a complete list of the FAMessage class attributes here.

The onNotificationReceived callback handles:

This callback may not be called if the user has force-quit the app before the notification reception.

Handling Notifications Taps

You can handle the tap on a notification by implementing the onNotificationTapped callback in FollowAnalyticsConfiguration. This allows you to perform specific actions when a notification is tapped, like opening a particular screen instead of the home screen, based on the arguments passed to the callback.

FollowAnalyticsConfiguration* configuration = [FollowAnalyticsConfiguration
    configurationWith:^(FollowAnalyticsConfiguration* _Nonnull config) {
        config.onNotificationTapped = ^(NSURL _Nullable url, NSDictionary * _Nonnull parameters) {
            // YOUR BEHAVIOR
            // Be careful: the argument url can be nil.
        }
    };
}];
let configuration = FollowAnalyticsConfiguration.init { (config) in
    config.onNotificationTapped = { (url, parameters) in
        // YOUR BEHAVIOR
        // Be careful: the argument url can be nil.
    }
}

A part of the notification content is provided through the url and the parameters arguments. These are configurable by the sender of the notification from the FollowAnalytics platform:

The onNotificationTapped callback handles:

Callbacks onOpenURL and onIncomingDeepLink are deprecated

The previously mentioned onNotificationTapped and onNotificationReceived callbacks also replace the onOpenURL callback for app links and the onIncomingDeepLink callback for deep-linking parameter, both of which are deprecated since the 6.3.0 version.

Interactive notifications

Interactive notifications are notifications with buttons that allow you to interact with the app without needing to open it. FollowAnalytics only handles only the notification registration. It is your responsibility to define how the notification will be displayed. To implement this feature, follow these steps:

  1. Declare the actionable notification types in your code. See Apple documentation here

  2. Create an interactive notification campaign from the FollowAnalytics platform by adding one or more categories in the Advanced options section



  3. Sort your actions by actionIdentifier from the function below:

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
        withCompletionHandler:(void (^)(void))completionHandler;
func userNotificationCenter(_ center: UNUserNotificationCenter,
                          didReceive response: UNNotificationResponse,
               withCompletionHandler completionHandler: @escaping () -> Void)

Custom handling of rich campaigns

Rich campaigns refer to the customizable in-apps and in-app web pages. These can be handled directly by the app code. If you do not want the code to handle the message automatically, and would rather show the message yourself when you see fit, you can turn on the switch labelled "automatically display content" in the Advanced Options when creating the campaign.

For campaigns where the content is not handled by FollowAnalytics, set your handler to onIncomingCustomCampaign on the FAFollowAnalyticsConfiguration before the SDK startup.

Pausing and resuming in-app campaigns

To pause and resume campaigns, add the following methods in you code at the location you wish the pause and resume to take effect:

[FollowAnalytics.inApp pauseCampaignDisplay]
[FollowAnalytics.inApp resumeCampaignDisplay]
FollowAnalytics.inApp.pauseCampaignDisplay()
FollowAnalytics.inApp.resumeCampaignDisplay()

Create safe spaces for you in-app messages

Rather than pause everywhere you have an important screen or process, you can pause right at the initialization of the SDK and resume in the areas you think it is safe for in-app campaigns to be displayed.

Enable campaign archiving

FollowAnalytics SDK allows you to store all campaigns and push notifications received by your app . This makes them available for custom usage, like building an inbox feature. All campaigns displayed by a device can be archived locally and accessed from the developer's code, formatted as a FAMessage object. In order to configure your campaign storage, you have to set the following FollowAnalyticsConfiguration properties at SDK initialization:

@property(nonatomic, readonly, assign) BOOL archivePushMessages;
@property(nonatomic, readonly, assign) BOOL archiveInAppMessages;
open var archivePushMessages: Bool { get }
open var archiveInAppMessages: Bool { get }

In FollowAnalyticsInApp and FollowAnalyticsPush protocols you will find all necessary methods to manage all FAMessage objects that are archived. They are implemented by FollowAnalytics.inApp and FollowAnalytics.push

(nonnull NSArray&lt;FAMessage_>_)getAll;\
(nullable FAMessage*)get:(nonnull NSString*)identifier;
(void)markAsRead:(nonnull NSArray&lt;NSString_>_)identifiers;\
(void)markAsUnread:(nonnull NSArray<NSString*>*)identifiers;
(void)deleteIdentifiers:(nonnull NSArray&lt;NSString_>\*)identifiers;\
func getAll()->[FAMessage]
func get(identifier : String) -> FAMessage
func markAsRead(identifiers : [String])
func markAsUnread(identifiers : [String])
func deleteIdentifiers(identifiers : [String])

Here are the attributes for FAMessage:

* BOOL isRead;
* BOOL isPush;
* BOOL isInApp;
* NSString identifier;
* NSString campaignId;
* NSString type;
* NSString title;
* NSString body;
* NSString url;
* NSString layout;
* NSString deepLinkUrl;
* NSDate dateReceived;
* NSDictionary params;
* NSDictionary rawData;
* bool isRead;
* bool isPush;
* bool isInApp;
* string identifier;
* string campaignId;
* string type;
* string title;
* string body;
* string url;
* string layout;
* string deepLinkUrl;
* date dateReceived;
* dictionary params;
* dictionary rawData;

Data Wallet

If you want to use Data Wallet, the very first step is to enable it in your app at startup. This is done by accessing the FollowAnalyticsConfiguration object which contains the property isDataWalletEnabled. Set this property to true.

Now that the Data Wallet is enabled, the SDK will automatically download the new policies as they are published. In order to deal with the currently known policy, call the following APIs:

// gets the current policy
id<FADataWalletPolicy> policy = [FollowAnalytics.dataWallet getPolicy];

// true if the current policy is considered accepted
BOOL policyIsRead =  FollowAnalytics.dataWallet.isRead;

// informs the SDK that the user has accepted the current policy
[FollowAnalytics.dataWallet setIsRead:true];
// gets the current policy
var policy = FollowAnalytics.dataWallet.getPolicy()

// true if the current policy is considered accepted
var policyIsRead =  FollowAnalytics.dataWallet.isRead()

// informs the SDK that the user has accepted the current policy
FollowAnalytics.dataWallet.setIsRead(true)```

There could only be one active policy at a time. When a new policy becomes available online, the SDK will call on the main thread onDataWalletPolicyChange, callback set on the FollowAnalyticsConfiguration. To set this up before starting the SDK, include the following code:

FollowAnalyticsConfiguration* configuration = [FollowAnalyticsConfiguration configurationWith:^(FollowAnalyticsConfiguration * _Nonnull config) {
    config.isDataWalletEnabled = true;
    config.onDataWalletPolicyChange = ^{
      [self displayNewPolicy];
    };
}];
let configuration = FollowAnalyticsConfiguration.init { (config) in
  config.isDataWalletEnabled = true;
  config.onDataWalletPolicyChange = {
    //YOUR_BEHAVIOR;
  }
}

At each major policy update, there needs to be consent from the client. When the user accepts a policy call [FollowAnalytics.dataWallet setIsRead:true] to mark the current policy as "read". In other words:

The SDK records the major version of the current policy for future reference. By default, if no other configuration is present, the SDK will return a default policy with version 0.0. This policy is always read. You should check for version 0.0 and handle it appropriately.

Custom default policy

If you want to provide a custom default policy for your users, download the policy JSON file from the back office and add it to your app, then modify the configuration to use it as follows:

FollowAnalyticsConfiguration* configuration = [FollowAnalyticsConfiguration configurationWith:^(FollowAnalyticsConfiguration * _Nonnull config) {
    // assuming that you have Policy.json in you main bundle
    config.dataWalletDefaultPolicyPath = [[NSBundle mainBundle] pathForResource:@"Policy" ofType:@"json"];
}];
let configuration = FollowAnalyticsConfiguration.init { (config) in
     config.dataWalletDefaultPolicyPath = Bundle.main.path(forResource: "Policy", ofType: "JSON")
  }

Advanced Use Cases

Configure the SDK

Before initializing the SDK you must enable the different functions of the SDK.

Parameter Type Default Value Description
apiKey string - Your app api key to use our SDK
appGroup string - An app group identifier to manage badges
isVerbose boolean false To avoid sending irrelevant logs to the production server (debug in previous versions)
apiMode enum .prod Either .dev or .prod for Swift and FollowAnalyticsAPIModeDev or FollowAnalyticsAPIModeProd for Objective-C
environment string - If you want to use a custom environment
environmentDomain string follow-apps.com If you want to use a custom domain
environmentProtocol string https By default we use https, you can change it to http
optInAnalyticsDefault boolean true To choose your default opt-in / opt-out behavior
crashReportingEnabled boolean true To enable the crash reports
isDataWalletEnabled boolean false To enable or disable the DataWallet
dataWalletDefaultPolicyPath string - To determine the path of your dataWallet policy
onDataWalletPolicyChange call back - Called when a new significant version of dataWallet policy is available
archivePushMessages boolean false To choose if you want to archive push messages or not
archiveInAppMessages boolean false To choose if you want to archive inApp messages or not
maxBackgroundTimeWithinSession int 120 To determine the lifetime of a session when in background (between 15 and 3600)
onIncomingDeepLink callback - Called when the app is opened from a deep link
onOpenURL callback - Called when the user opens an url from your app
onIncomingCustomCampaign callback - Called when the SDK receive a custom campaign
onConsoleLog call back - Called when new logs are made internally in FollowAnalytics SDK
onNotificationTapped callback - Called when user taps on a notification
onNotificationReceived callback - Called when user receives a notification and the app is in foreground

Manual installation of the SDK

Cocoapods is the preferred method

Even though you can install the SDK manually, cocoapods is the preferred method, since it will take care of much of the work and ensure your SDK is easily updated.

  1. Go to your Xcode project’s General settings of your target, drag and drop the FollowAnalytics.framework in the Embedded Binaries section. Make sure Copy items if needed is selected and click Finish.

  2. Create a new Run Script Phase in your app’s target’s Build Phases and paste the following snippet in the script text field:

    bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/FollowAnalytics.framework/strip-frameworks.sh"
    

    This step is required to work around an App Store submission bug when archiving universal binaries.

  3. Now, you can proceed to configuring your setup.

Manual installation of Rich Push notifications

  1. Drag and drop the FANotificationExtension.framework in your project and add it to your extension target.
  2. Select the target of your main app, in Build phase

    1. Press the + button, and select New Copy File Phase.
    2. Change the destination to Frameworks
    3. Add the FANotificationExtension.framework
  3. Create a new Run Script Phase in your app’s target’s Build Phases and paste the following snippet in the script text field:

    bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/FANotificationExtension.framework/strip-frameworks.sh"
    

    This step is required to work around an App Store submission bug when archiving universal binaries.

InApp Template Configuration

In your info.plist add the following line (only required for fullScreen InApp): View controller-based status bar appearance and set the boolean to NO

Updating from older versions

Updating from 6.2 to 6.3

If your app implements onIncomingDeepLink and onOpenURL callbacks:

Updating from 6.1 to 6.2

Updating to 6.0

Updating from 5.3 to 5.4

Updating from 5.2 to 5.3

Updating from 5.0 to 5.1

Updating from 4 to 5.0.0

To use version 5.0.0+ of the iOS SDK:

Updating from 3.* to 4.*

The migration is seamless. However, please refer to the section around user attributes to learn how to feed user profiles using the SDK.

Updating from 2.* to 3.0.0

To use version 3.0.0+ of the iOS SDK:

These new parameters are provided only when running on iOS 8 and later. They are the interactive notification parameters that you would want to get to know which action was performed on a FollowAnalytics notification.

Nothing else changes. Please refer to the rest of the documentation to discover what the newer versions of the SDK now allow.