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:
-
Connect to your developer portal, and go to the App IDs.
-
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. -
In the list of Capabilities, check the Push Notifications box
-
Click Edit to display the window for Apple Push Notification service SSL Certificates
-
Create a certificate by clicking the Create button
-
Upload your Certificate Signing Request (create a Certificate Signing Request here) and click continue
-
Click Download button to create your certificate, open the Keychain Assistant app and locate that certificate
-
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. -
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)
-
Connect to your developer portal.
-
Click on your
Keys
tab. -
Click in the
+
button in the top of page to add a new Key. -
Add a
Key Name
. -
Check the
Apple Push Notification service (APNs)
-
Click
Continue
. -
Download the
.p8
file. (You must download the p8 file in this step because this is your unique chance to download it) -
Go to the
Identifiers
Tab. -
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. -
In the list of Capabilities, check the Push Notifications box
-
Go to the Administration page, upload the
.p8
file and click inProceed
. -
Enter your
Key ID
andIssuer 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:
-
Access the application page and click on the "Manage API keys" tab
-
Click the "+ Generate new API key" button.
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:
- Installing the SDK in your app
- Initializing the SDK using your API key
- Registering for notifications
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.
-
Add
pod 'FollowAnalytics','~> 6.3.0'
in the Podfile (see screenshot below) -
Run
pod repo update
from the command line. This will enable CocoaPods to detect the latest available version of FollowAnalytics. -
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.
-
Import the FollowAnalytics framework in your
AppDelegate
. -
Inside your UIApplicationDelegate implementation, create a configuration object and set the required fields
-
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:
-
Enable Push Notifications by setting the switch to ON.
-
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:
-
Go to the
info
tab of the project targets. -
At the bottom you select the subsection called "URL Types".
-
Click the
+
sign at the bottom. -
Add the bundle ID of your app in both
identifier
andURL Schemes
fields
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:
- A
nil
value - A
String
- A
Dictionary
representing a valid flat JSON object (i.e. that doesn't contain any nested Dictionary or Array field).
Passing any invalid details
argument to those methods will:
- Print an error in the console (that you can see while debugging)
- Ignore the
details
argument and send the log with nodetails
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:
-
Adopt WKUIDelegate protocol in your object of choice, typically a UIViewController.
@interface ViewController <WKUIDelegate>
class ViewController: UIViewController, WKUIDelegate {
-
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?
-
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 }
-
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:
-
In your xCode project, add a new target.
-
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.
-
Select the target of your main app, in
Build Phases
- Press the + button, and select
New Copy File Phase
. - Change the destination to
Frameworks
. - Click in
add other
. - Add the
FANotificationExtension.framework
file that you previously copied into your project directory. - Uncheck
Copy items if needed
box.
- Press the + button, and select
-
Still in the
Build Phases
- Press the + button, and select
New Run Script Phase
. - Add this script:
bash "PATH_TO_YOUR_PROJECT_DIRECTORY/FANotificationExtension.framework/strip-frameworks.sh"
- Press the + button, and select
-
In
Build Settings
->Framework Search Paths
entry, add the path to where theFANotificationExtension.framework
is located (actually your project directory).
Initialise
-
Before all, an App Group must be created.
- Go to the
apple developer
portal. - Choose the
identifier
tab. - Choose the
App Groups
filed from the list.
- Tap
+
to create a newApp Group
- Create your
App Group
and clickContinue
- Switch to the
App ID
of the app. - Add
App Groups
capability
- Select the new
App Group
recently created.
- Go to the
-
Then, the
app group
must be added to theAppId
of app and extension -
Finally, the
app group
capability must be activated inXcode
for both app and extension
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:
- Choose the extension
- Click
Edit Scheme
- Select app in excutable field
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:
- Create an App Groups between your main App and you extension.
- 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.
- Activate the app group capability in XCode project configuration, and add the corresponding app group bundle.
- 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:
- Push notifications
- Contextual notifications
- Silent push notifications
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:
url
is aNSURL
containing the value of AppLink field of the campaign editor (optional, may benil
)parameters
is aNSDictionary
set with the content of the Key / Value field of the campaign editor
The onNotificationTapped
callback handles:
- Push notifications
- Contextual notifications
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:
-
Declare the actionable notification types in your code. See Apple documentation here
-
Create an interactive notification campaign from the FollowAnalytics platform by adding one or more categories in the
Advanced options
section
-
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
- The methods are the following
(nonnull NSArray<FAMessage_>_)getAll;\
(nullable FAMessage*)get:(nonnull NSString*)identifier;
(void)markAsRead:(nonnull NSArray<NSString_>_)identifiers;\
(void)markAsUnread:(nonnull NSArray<NSString*>*)identifiers;
(void)deleteIdentifiers:(nonnull NSArray<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
.
Policy download and consent
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:
- If
FollowAnalytics.dataWallet.isRead
isfalse
, the current policy major version has yet to be accepted by the user. - If the current policy is accepted,
FollowAnalytics.dataWallet.isRead
becomestrue
.
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.
-
Go to your Xcode project’s
General
settings of your target, drag and drop the FollowAnalytics.framework in theEmbedded Binaries
section. Make sure Copy items if needed is selected and clickFinish
. -
Create a new
Run Script Phase
in your app’s target’sBuild 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.
-
Now, you can proceed to configuring your setup.
Manual installation of Rich Push notifications
- Drag and drop the FANotificationExtension.framework in your project and add it to your extension target.
-
Select the target of your main app, in Build phase
- Press the + button, and select
New Copy File Phase
. - Change the destination to
Frameworks
- Add the FANotificationExtension.framework
- Press the + button, and select
-
Create a new
Run Script Phase
in your app’s target’sBuild 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:
- Move your current implementation of
onIncomingDeepLink
toonNotificationReceived
and make necessary changes - Add
onNotificationTapped
andonNotificationReceived
callbacks - Move your current implementation of
onOpenURL
toonNotificationTapped
and make necessary changes. You you want to open theurl
passed as argument to this callback, you will have to add your own code to do so.
Updating from 6.1 to 6.2
- Replace
debug
byisVerbose
in FollowAnalyticsConfiguration
Updating to 6.0
- Replace all undefined methods with corresponding methods defined by the new FollowAnalytics interfaces
- For manual integration, do not forward anymore delegate methods to FollowAnalytics. We automatically intercept the invocations when needed.
- Remove
UserNotifications.framework
andMobileCoreServices.framework
from all your targets.
Updating from 5.3 to 5.4
- Change imports from
<FollowApps/...>
to<FollowAnalytics/...>
- Previous versions of opt-out via settings bundle are deprecated and completely removed starting with version 6 of the SDK. While still available, a warning shall be sent to log about the deprecated use. The new 5.4 opt-out feature must be used for RGPD compliance.
- if using change strip framework to the new
${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/FollowAnalytics.framework/strip-frameworks.sh
Updating from 5.2 to 5.3
- In your Podfile replace
pod FollowApps
bypod FollowAnalytics
Updating from 5.0 to 5.1
-
Replace this method:
+ (BOOL)configureWithId:(nonnull NSString *)FAId debugStateOn:(BOOL)isDebug options:(nonnull NSDictionary *)options;
by
+ (BOOL)configureWithId:(nonnull NSString *)FAId sharedAppGroup:(nullable NSString * )appGroup automatise:(BOOL)automatise debugStateOn:(BOOL)isDebug options:(nullable NSDictionary *)options;
-
If you used the badge management, you have to specify your appGroup shared between the app and the notification service extension.
-
If you use geofencing in your app. You have to call this method :
+ (void)enableGeofencing;
Updating from 4 to 5.0.0
To use version 5.0.0+ of the iOS SDK:
- Link these additional Frameworks in the Settings of your targets:
UserNotifications.framework
.MobileCoreServices.framework
.libz.tbd
.
- PassKit is not required anymore. If you don't use it you can remove it.
-
Replace these deprecated methods:
+ (void)addCustomUserAttributeSet:(NSSet *)attributeSet forKey:(NSString *)key + (BOOL)removeCustomUserAttribute:(NSString *)attribute fromSetWithKey:(NSString *)key //Remove one element from the specify set.
by:
+ (BOOL)addCustomUserAttribute:(NSString *)attribute toSetWithKey:(NSString *)key //Add only one string element into the specify set + (BOOL)removeCustomUserAttributeSet:(NSSet *)set fromSetWithKey:(NSString *)key // remove a set of string element from a specify set
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:
- Link an additional Framework in the Settings of your targets:
libsqlite3.dylib
. -
In your
AppDelegate.m
file, replace this deprecated method:- (void)followAppsShouldHandleParameters:(NSDictionary *)openingParameters
with:
- (void)followAppsShouldHandleParameters:(NSDictionary *)customParameters actionIdentifier:(NSString *)actionIdentifier actionTitle:(NSString *)actionTitle completionHandler:(void (^)())completionHandler
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.