Initial SDK setup
Minimum setup
To get started, you need to perform the following tasks:
Install using Cocoapods
If you want to use Cocoapods to manage your external dependencies, simply add the following line to your Podfile:
pod 'FollowApps'
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
If you don't have a podfile yet, open a console and do a pod init
in your project directory.
Using a local version of the Pod
If you'd rather have the file locally, download the SDK, copy the FollowApps/ directory located in Pod/ to your Xcode project root directory and use the following line in your Podfile:
pod 'FollowApps', :path => "FollowApps"
Initialize with your API key
Prepare your API key
Be sure to have your API key for this step of the configuration. If you are not sure where to find it, please reach out to your Customer Success Manager or message support@followanalytics.com
To initialize the SDK, you need to call the configureWithId
method on it, and pass it your API key.
To do so:
-
Import the
<FollowApps/FAFollowApps.h>
, in yourAppDelegate.h
file if you use Objective-C, or in yourBridging-Header.h
file in Swift.What if I don't have a bridging header file?
- Create a new Objective C file in your project (File->New->File[Objective C for iOS]).
- Accept the prompt (agree) to create a bridging header file between Objective C and Swift.
- Delete your newly created Objective C file but keep the bridging header file
${YOURPROJ}-Bridging-Header.h
.
-
Add the
FollowAppsDelegate
protocol to your AppDelegate, and configure the SDK using theconfigureWithId
method:Objective-C
// in AppDelegate.h @interface AppDelegate : UIResponder <FAFollowAppsDelegate> // in AppDelegate.m [FAFollowApps configureWithId:@"API_KEY_STRING" sharedAppGroup:@"APP_GROUP" automatise:YES debugStateOn:NO options:launchOptions];
SWIFT
class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool { FAFollowApps.configure(withId: "API_KEY_STRING", sharedAppGroup: "APP_GROUP", automatise: true, debugStateOn: false, options: launchOptions)
If you can't use the automated integration (bool to false), please refere to the bottom for additional documentation dedicated page.
The switch between debug and release mode is not automatic in Swift
- When developing your app, use
debugStateOn: true
to avoid sending irrelevant logs to the production server, and to see debugging information in the XCode console - Before publishing the app, make sure the debug state is OFF (
debugStateOn: false
).
- When developing your app, use
Define the URL scheme
To allow users to retrieve their device ID for campaign testing and tagging plan debugging, declare a URL Scheme in the info tab of your Xcode project using the bundleId of your app as URL Scheme:
Make sure that the bundle ID of your app appears in the URL Schemes field as shown in the screenshot (where com.follow-apps.followme.inHouse
needs to be replaced).
Once configured, your FA device ID can be obtained by opening the following URI:
xxx://followanalytics.com/deviceId
, where xxx shall be replaced by the application bundle identifier (com.follow-apps.followme.inHouse in the example above).
FA users can request, from the product interface, that an e-mail message containing this link be sent to their device to facilitate the operation.
Register for notifications
If your app code is already registered to send push notifications, nothing to do here. Otherwise, simply add a call to registerForPush
following the initialization line you added previously:
Objective-C
[FAFollowApps configureWithId:@"API_KEY_STRING" sharedAppGroup:@"APP_GROUP" automatise:YES debugStateOn:NO options:launchOptions];
[FAFollowApps registerForPush];
SWIFT
FAFollowApps.configure(withId: "API_KEY_STRING", sharedAppGroup: "APP_GROUP", automatise: true, debugStateOn: false, options: launchOptions)
FAFollowApps.registerForPush()
Then, to ensure FollowAnalytics can detect uninstalls, activate the Silent Notifications capabilities in the capabilities tab of your Xcode Project, by clicking the Remote Notifications box under Background Modes:
There is nothing else to do, FollowAnalytics will handle its own notifications and you will still receive yours, as long as you compile with the appropriate Push certificates, and provide FollowAnalytics with the required .pem
file. To generate the pem
push certificate required for FollowAnalytics, you can follow the
Certificates section in this tutorial.
Conflict with Notification Categories
If you register interactive notification categories: In your AppDelegate implement : - (void)followAppsRegisterNotificationCategories;
And register your category inside the method.
If you want to get the status of the user preferences you can call this method: FAFollowApps.isRegisteredForPushNotifications()
Register for location
FollowAnalytics will only access the location if you give the permission to the SDK. If you are already using it and want to share it with FollowAnalytics you will have to call : FAFollowApps.enableGeoffencing()
⚠️ If you call it in the didFinishLaunchingWithOptions
it will directly trigger the popup asking for the location. We advise you to only call it after you ask the permission to the user.
Validate
The SDK has a Validator that will ensure that everything is properly configured.
When your app is running in debug mode, a popup is shown at launch with the details of what is properly configured, and what is not. This makes it easier for you to validate that the various steps were performed properly.
Crash reporting test
To be able to validate that the crash configuration is working properly, you will have to launch your app once without the debugger, i.e. manually on the device or from the simulator, without using the "run" button in Xcode.
Validator description
To know more about what the validator checks and how, please refer to its dedicated page.
Logging
Data sent in debug mode will not appear on dashboards
When your app runs in DEBUG mode or in a simulator, the data is automatically sent as development logs, and is therefore not processed to be shown on the main UI page. DEBUG logs can be checked using the method given in the FAQ section.
See related entry in FAQ for more information on debug & release modes.
Logging best practices
To ensure your tags are relevant and will end up empowering your team through FollowAnalytics, please read the Logging best practices entry in the FAQ section.
Events vs Attributes
The FollowAnalytics SDK allows you to tag both events and attributes. If you are unsure about the difference, please refer to the corresponding FAQ entry.
Tag events
Regular, native event logging
The SDK allows you to log events happening in your code. These are the two methods you can call on the SDK:
Objective-C
+ (BOOL)logEventWithName:(NSString *)name details:(id)details;
+ (BOOL)logErrorWithName:(NSString *)name details:(id)details;
SWIFT
FAFollowApps.logEventWithName(name: String!, details: AnyObject!)
FAFollowApps.logErrorWithName(name: String!, details: AnyObject!)
Use the name as the unique identifier of your tag, use the details section to add specific details, context. Events can be renamed later: the name that you give to your event here can be overridden in the FollowAnalytics UI.
The details field can either be a String or a Hash, so that you can associated multiple key-values for additional context.
For instance, logging the appearance of a view could be done the following ways:
Objective-C
[FAFollowApps logEventWithName:@"Product view" details:@"Product reference"];
[FAFollowApps logEventWithName:@"In App purchase completed" details:@"Full pack"];
NSDictionary *detail_dictionary = @{ key_1: obj_1, key_2 : obj_2, key_3 : obj_3};
[FAFollowApps logEventWithName:@"Example log name" details:detail_dictionary];
SWIFT
FAFollowApps.logEventWithName("product view", details: "Product reference")
FAFollowApps.logErrorWithName("In App purchase completed", details: "Full pack")
let detail_dictionary:NSDictionary = [key_1: obj_1, key_2: obj_2, key_3: obj_3]
FAFollowApps.logEventWithName("Example log name", details: detail_dictionary)
In debug mode, the SDK will acknowledge the saving by writing in the console whatever it receives.
If the parameters sent to these methods are over 60Kb, the method will refuse them, return NO
, and write a message in the console if it is running in debug mode.
Logging from a web view
If you happen to use a web view to display elements of your app, you can also tag events and errors from within your HTML/JS code. To do so:
-
Make sure you use the FAWebView, both in your .h file and your .xib or Storyboard, instead of the regular UIWebView. For the latter, you need to set the Custom Class parameter of your UIWebView to FAWebView in the Identity Inspector.
-
Use the provided FAWebView.js in your web page code to save events. For instance, you could do:
<a href="#" onclick="FALogEvent('My event', 'My event details')">Log an event</a> <a href="#" onclick="FALogError('My error', '')">Log an error</a> <a href="#" onclick="FALogEvent('My event', {'hello': 'Hi', 'How are you': 'good!'})">Log an event with hash</a>
-
In case you want to register for push through a webview, you need to call FARegisterForPush(), like for instance:
<a href="#" onclick="FARegisterForPush()">register for push</a>
User ID and attributes
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 and can be shared across apps.
In both cases, attributes can be used in segments and campaigns to target users.
User ID
If users can sign in somewhere in your app, you can specify their identifier to the SDK. This way, you will be able to relate crashes to specific users, link your users between FollowAnalytics and your CRM, and more.
This identifier is usually an e-mail address, client identifier, phone number, or anything else that uniquely ties your customers to you.
To register the user identifier, use:
Objective-C
+ (void)setUserId:(NSString *)userId;
SWIFT
func setUserId(userId: AnyObject!)
If you want to remove the user identifier (in case of a sign out for instance) use the following method:
Objective-C
+ (void)unsetCurrentUserIdentifier;
SWIFT
func unsetCurrentUserIdentifier
Predefined attributes
The SDK allows to set values for both custom and predefined attributes.
For predefined attributes, the SDK has the following properties:
+ (void)setUserFirstName:(NSString *)firstName;
+ (void)setUserLastName:(NSString *)lastName;
+ (void)setUserEmail:(NSString *)email;
+ (void)setUserDateBirth:(NSDate *)dateBirth;
+ (void)setUserGender:(FAGender)gender;
+ (void)setUserCountry:(NSString *)country;
+ (void)setUserCity:(NSString *)city;
+ (void)setUserRegion:(NSString *)region;
+ (void)setUserProfilePictureUrl:(NSString *)url;
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:
[FAFollowApps setUserFirstName:@"Joe"];
[FAFollowApps setUserCity:@"Paris"];
Custom attributes
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. Please ensure the types match by visiting the profile data section of the product.
Set a custom attribute
To set your custom attributes, you can use methods that are adapted for each type:
+ (void)setInt:(NSInteger)intValue forKey:(NSString *)key;
+ (void)setDouble:(double)doubleValue forKey:(NSString *)key;
+ (void)setBoolean:(BOOL)booleanValue forKey:(NSString *)key;
+ (void)setDate:(NSDate *)dateValue forKey:(NSString *)key;
+ (void)setDateTime:(NSDate *)dateValue forKey:(NSString *)key;
+ (void)setString:(NSString *)stringValue forKey:(NSString *)key;
For example, to set the user's job:
[FAFollowApps setString:@"Taxi Driver" forKey:@"key_job"];
Delete a custom attribute value
You can delete the value of an attribute using its key. For example, to delete the user's job:
[FAFollowApps removeCustomUserAttributeForKey:@"key_job"];
Set of Attributes
You can add or remove an item to or from a set of attributes.
To add an item:
NSSet *set = [[NSSet alloc] initWithObjects:@"apple", @"strawberry", @"lemon", nil];
[FAFollowApps addCustomUserAttributeSet:set forKey:@"fruits"];
To remove an item:
[FAFollowApps removeCustomUserAttributeSet:@"lemon" forKey:@"fruits"]; // Removes "lemon" from set of fruits.
And to clear a set:
[FAFollowApps deleteCustomUserAttributeSetForKey:@"fruits"]; // Removes all the items from the set.
For further information, refer to the SDK header file.
Advanced Use Cases
Deep-linking: URL, Parameters
Campaigns created through FollowAnalytics allow to deep link to content in your app. You can either use an App Link, or use key-value parameters that are forwarded to your code.
App Links
Version 4.1.0 of the SDK introduced the possibility to use direct App Links like twitter://messages
, which will send you to the corresponding screen inside the Twitter application.
You're able to access the functionality by enabling the Deep Linking switch in our UI, when creating a campaign. There you'll find the field App Link that expects you to enter these type of url schemas. It can either be an URL Schema to an external application or for your own application.
In the case of an external application you'll be presented with a system alert asking you to allow the redirection for the target application (the first time only).
If you need to handle the execution of the App Link yourself, you can implement this delegate and call the completionOpenUrl()
when your app is ready to execute the App links.
⚠️This delegate is called only when the appLink is called from a notification.
Objective-C
- (void)followNotificationHandleOpenURLWithCompletion:(void (^_Nonnull)(void))completionOpenUrl`
SWIFT
func followNotificationHandleOpenURL(completion completionOpenUrl: @escaping () -> Void)
Deep-linking parameters
In FollowAnalytics campaigns, you can specify deep-linking parameters, e.g. in your push messages or for in-app button actions.
These parameters are given to the developer's code by the SDK. It is then up to the developer to implement the deep-linking in the app (specific path of screens, format of the arguments, etc.).
The parameters are passed using the following method of the FAFollowappsDelegate
delegate:
Objective-C
- (void)followAppsShouldHandleParameters:(NSDictionary *)customParameters actionIdentifier:(NSString *)actionIdentifier actionTitle:(NSString *)actionTitle completionHandler:(void (^)())completionHandler;
SWIFT
func followAppsShouldHandleParameters(customParameters: [NSObject : AnyObject]!, actionIdentifier: String!, actionTitle: String!, completionHandler: (() -> Void)!)
Through the key value format, FollowAnalytics supports both standardized deep-linking (by defining the key you'll always use to give the path), and more direct parameter passing for simpler use cases integrations.
Regular deep-linking is usually implemented using a Router, that will handle the URL called on the app and translate it into the display of the right page, with the right content. An example of an open-source deeplinking router is DeepLinkKit.
Once this Router is configured in your app, the link with the FollowAnalytics SDK can be done the following way, supposing you decide on using the key deeplinking-path
to pass your deeplink when creating your campaigns:
Objective-C
- (void)followAppsShouldHandleParameters:(NSDictionary *)customParameters actionIdentifier:(NSString *)actionIdentifier actionTitle:(NSString *)actionTitle completionHandler:(void (^)())completionHandler
{
NSURL *url = [NSURL URLWithString:customParameters[@"deeplinking-path"]];
if (url)
{
[self.router handleURL:url withCompletion:nil];
}
}
SWIFT
func followAppsShouldHandleParameters(customParameters: [NSObject : AnyObject]!, actionIdentifier: String!, actionTitle: String!, completionHandler: (() -> Void)!) {
let url:NSURL = NSURL(string: customParameters["deeplinking-path"] as! String)!
self.router?.handleURL(url, withCompletion: nil)
}
AdaptiveSDK
The SDK has a feature called AdaptiveSDK: it allows to benefit from tags already in place and use them directly without having to implement a new tagging plan.
The SDK is currently compatible with Segment, Mixpanel, Google Analytics, Localytics and Urban Airship.
To check that our SDK detects the current integration you have in place, use:
Objective-C
[FAFollowApps detectedSDKs];
SWIFT
FAFollowApps.detectedSDKs()
You can then pick the SDKs you want to get tags from:
- MixPanel:
FASDKMixpanelKey
- Google Analytics:
FASDKGoogleAnalyticsKey
- Localytics:
FASDKLocalyticsKey
- Urban Airship:
FASDKUrbanAirshipKey
For instance, to fetch tags from Mixpanel, you would use:
Objective-C
[FAFollowApps fetchTagsFromSDKs:FASDKMixpanelKey];
SWIFT
FAFollowApps.fetchTagsFromSDKs(FASDKMixpanelKey)
If you wish to fetch tags from all compatible SDKs, you can chain the 2 method calls:
Objective-C
[FAFollowApps fetchTagsFromSDKs:[FAFollowApps detectedSDKs]];
SWIFT
FAFollowApps.fetchTagsFromSDKs(FAFollowApps.detectedSDKs())
How it works
All the events you save using the compatible Analytics SDKs will also be saved on FollowAnalytics. The event name will be prefixed with a two-character code identifying the source: UA for UrbanAirship, LL for Localytics, and so on.
Just like for events tagged directly with our SDK, you can see logs in your developer console when a log is saved, so that you can check it is properly working.
Rich iOS 10 notifications
Notification Service Extension Framework
Requirement
To make your app able to receive iOS 10 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.
Install using 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'
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
-
Select the target of your main app, in Build phase
- Presse the + button, and select
New Copy File Phase
. - Change the destination to
Frameworks
- Add the FANotificationExtension.framework, you should find it in the Pod folder.
- Presse the + button, and select
-
Still in the Build phase
- Presse the + button, and select
New Run Script Phase
. - Add this script:
bash "${PODS_ROOT}/FANotificationExtension/FANotificationExtension.framework/strip-frameworks.sh"
- Presse the + button, and select
Manual installation
- Drag and drop the framework in your project and add it to your extension target.
-
Go to your project configuration, select your target(the extension). Under the General pane, add the following frameworks (if not already listed) in the Linked Frameworks and Libraries section:
- UserNotifications.framework
- MobileCoreServices.framework
-
Select the target of your main app, in Build phase
- Presse the + button, and select
New Copy File Phase
. - Change the destination to
Frameworks
- Add the FANotificationService.framework
- Presse the + button, and select
-
Select the Build phase
- Presse the + button, and select
New Run Script Phase
. - Add this script:
bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/FANotificationExtension.framework/strip-frameworks.sh"
- Presse the + button, and select
Initiliaze
- import the
<FANotificationExtension/FANotificationExtension.h>
in your file of your target extension. - Implement the code in the method:
didReceiveNotificationRequest
:
Objective-C
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
[FANotificationService getFAContentIfNeededWithRequest:request bestContent:self.bestAttemptContent appGroup:@"APPGROUP" completion:^(UNMutableNotificationContent * _Nullable newContent) {
// Modify the notification content here...
self.contentHandler(newContent);
}];
}
SWIFT
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
FANotificationService.getFAContentIfNeeded(with: request, bestContent: bestAttemptContent, appGroup: "APPGROUP", completion: { (newContent:UNMutableNotificationContent?) in
// Modify the notification content here...
contentHandler(newContent!)
})
}
}
⚠️If you need to inscrease the badge number with a push, you will need an app Group between your main App and you extension.
Badge management
For using this feature, there are 3 requirements:
* Have the Notification Service Extension with our FollowAnalytics extension framework. more information here
* Create an app group between your app and the extension.
* Specify your app group in the init (configureWithId...
)
Just after initilize follow call :
Objective-C
[FABadge enable];
SWIFT
FABadge.enable()
We only update the value of the badge when a push is receive. You have to implement the logic and the code to decrement or reset the value. They are 3 methods:
Objective-C
[FABadge setBadge:INTEGER]; // Set the value of the icon badge number
FABadge.setBadge(Int) // Set the value of the icon badge number
Objective-C
[FABadge updateBadgeBy:INTEGER]; // Update the value of the icon badge number
SWIFT
FABadge.updateBadgeBy(Int) // Update the value of the icon badge number
Objective-C
[FABadge badge]; // Get the value of the icon badge number
SWIFT
FABadge.badge // Get the value of the icon badge number
Control over campaigns
Custom handling of rich campaigns
Rich campaigns can be handled directly by the application code, instead of being showed automatically by the SDK. The behavior is defined when creating the campaign, using the "automatically display content" switch.
For campaigns where the content is not handled by FollowAnalytics, implement the following FAFollowAppsDelegate method in your AppDelegate:
Objective-C
- (void)followAppsShouldHandleWebViewUrl:(NSURL *)url withTitle:(NSString *)webviewTitle;
func followAppsShouldHandleWebViewUrl(url: NSURL!, withTitle webviewTitle: String!)
Pausing in-app campaigns
You can prevent in-app campaigns from being displayed on certain views of your app. This can be useful when you are displaying a media content, or if the topmost screen is only shown for a few seconds, for instance.
Any campaign supposed to be displayed when the mechanism is paused is stacked and shown as soon as it is resumed.
To tell the SDK to prevent the display of rich campaigns, and then to activate it back, use the following methods:
Objective-C
[FAFollowApps pauseCampaignDisplay]
[FAFollowApps resumeCampaignDisplay]
SWIFT
FAFollowApps.pauseCampaignDisplay()
FAFollowApps.resumeCampaignDisplay()
Tip: use view lifecycle methods
If you want to prevent the display on a given page, you can call the pause method from the viewDidAppear
method, and the resume one in the viewDidDisappear
call.
Tip: only allow display in some places of the app
You can use these methods the other way round, by pausing all campaigns when the app starts, right after the SDK was initialized, and then resuming where the messages can be shown. Just pause again when the user leaves that "safe" area of your app.
Interactive notifications
To ensure your interactive notification categories are properly set, write your category definition code inside the followAppsRegisterNotificationCategories
delegate method, so that the SDK can trigger this registration when needed. It will be called when the SDK registers for push notifications.
This allows to use custom button and actions on your notifications.
This has to be done in your code. The categories created can then be used when creating a FollowAnalytics push campaign.
If a user receives an interactive notification sent from FollowAnalytics, and taps one of the buttons, it calls the followAppsShouldHandleParameters:actionIdentifier:actionTitle:completionHandler:
method and passes the action identifier and title. If no custom parameter was defined when creating the campaign, the first parameter is an empty dictionary.
The completionHandler
comes from the default interactive notification handling methods. Make sure you call it if it is not nil as it won't be called by FA if passed to you.
To register actions, you can proceed as follows:
Objective-C
- (void)followAppsRegisterNotificationCategories {
UIMutableUserNotificationCategory *category = [[UIMutableUserNotificationCategory alloc] init];
category.identifier = @"categoryIdentifier1";
[category setActions:actionsArray forContext:UIUserNotificationActionContextDefault];
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:[NSSet setWithObjects:category, nil]];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}
SWIFT
func followAppsRegisterNotificationCategories() {
let category:UIMutableUserNotificationCategory = UIMutableUserNotificationCategory()
category.identifier = "categoryIdentifier1"
category.setActions(actionsArray, forContext:UIUserNotificationActionContext.Default)
let settings:UIUserNotificationSettings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: Set(arrayLiteral: category))
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
}
Get params from last notification
Some applications might not be able to receive the notification custom parameters. Although this is unlikely, you can get the latest NSDictionary
containing the custom parameters passed by the notification by calling:
[FAFollowApps lastPushCampaignParams]
You cannot call this method twice
This is a one shot call as a second call to this method will return an empty NSDictionary
.
Campaign Archives
All scheduled campaigns received by a device can be archived locally and accessed from the developer's code, formatted as a message object. In order to configure your campaign storage, you have to call this method:
Objective-C
[FAFollowApps storeMessagesPush:YES inApp:YES];
SWIFT
FAFollowApps.storeMessagesPush(true, inApp: true)
We recommend adding it right after the FollowAnalytics SDK initialization.
In the class : FAInApp
& FAPush
you will find all methods related to a simple database.
- Methods:
+ (NSArray <FAMessage *> *)all;
+ (FAMessage *)identifier:(NSString *)identifier;
+ (BOOL)markAsRead:(NSArray <NSString *> *)identifiers;
+ (BOOL)markAsUnread:(NSArray <NSString *> *)identifiers;
-
+ (BOOL)deleteIdentifiers:(NSArray <NSString *> *)identifiers;
-
FAMessage
property: BOOL isRead;
BOOL isPush;
BOOL isInApp;
NSString *identifier;
NSDate *dateReceived;
NSString *campaignId;
NSString *type;
NSString *title;
NSString *body;
NSString *url;
NSString *layout;
NSString *deepLinkUrl;
NSDictionary *params;
NSDictionary *rawData;
⚠️ If you use this feature (storeMessages), we won't delete any message.
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
You can stop the display of InApp Campaigns in screens where you don't want them to appear. In order to do this call theses methods
Objective-C
[FAFollowApps pausePopupCampaignDisplay];
[FAFollowApps pauseBannerCampaignDisplay];
SWIFT
FAFollowApps.pausePopupCampaignDisplay()
FAFollowApps.pauseBannerCampaignDisplay()
Whenever you want to display them, just call these other methods
Objective-C
[FAFollowApps resumePopupCampaignDisplay]
[FAFollowApps resumeBannerCampaignDisplay]
SWIFT
FAFollowApps.resumePopupCampaignDisplay()
FAFollowApps.resumeBannerCampaignDisplay()
EmbeddedView
Overview
The embeddedView is very particular, it will move contents in your view. That is why to use one, you will need to activate autoLayout and use constraints. Otherwise you will need to move your affected content manually.
Configuration
- In your Storyboard or xib file:
- Enable AutoLayout.
- Add a
UIView
in the position you need the embeddedView. (We advise to have a scroll view as parent view). - Choose your width and set the height to 0.
- put the height constraint priority to Low (250).
- Link the view to your controller (IBOutlet), you can name it myEmbeddedViewContainer.
- In your viewController :
- Add
#import <FollowApps/FAEmbeddedView.h>
- In the method
ViewDidLoad
construct theFAEmbeddedView
with one theses differents constructors:
- Add
Objective-C
FAEmbeddedView *embeddedView = [[FAEmbeddedView alloc] init];
FAEmbeddedView *embeddedView = [[FAEmbeddedView alloc] initWithCategory:@"pub"]; //If you have more than one embedded in your app, use the category to identify it
FAEmbeddedView *embeddedView = [[FAEmbeddedView alloc] initWithMaxHeight:100]; // If your view don't have a scrollView or the height of view can't overpass a precise height, you can specify a maximum height for the embedded.
FAEmbeddedView *embeddedView = [[FAEmbeddedView alloc] initWithCategory:@"pub" maxHeight:100];
SWIFT
let embeddedView = FAEmbeddedView()
let embeddedView = FAEmbeddedView(category: "pub")
let embeddedView = FAEmbeddedView(maxHeight: 100)
let embeddedView = FAEmbeddedView(category: "pub", maxHeight: 100)
add the delegate in your controller: <FAEmbeddedViewDelegate>
and set the delegate:
Objective-C
embeddedView.embeddedDelegate = self;
SWIFT
embeddedView.embeddedDelegate = self
Add the FAEmbeddedView in the container created in Interface Builder:
Objective-C
[self.myEmbeddedViewContainer addSubView:embeddedView];
SWIFT
self.myEmbeddedViewController.addSubView(embeddedView)
You can implement these methods if needded:
Objective-C
- (BOOL)embeddedViewWillBeDisplayed:(FAEmbeddedView *)embeddedView;
- (NSInteger)embeddedView:(FAEmbeddedView *)embeddedView didFinishLoadWithpreferedHeight:(NSInteger)preferedHeight;
SWIFT
func embeddedViewWillBeDisplayed(_ embeddedView: FAEmbeddedView!) -> Bool
func embeddedView(_ embeddedView: FAEmbeddedView!, didFinishLoadWithpreferedHeight preferedHeight: Int) -> Int
Testing
There are 3 methods you can call to have a preview of the embedded. Theses methods are only here for testing and debugging. You will have a preview of your view if the embedded is activated.
Initialise the embedded (don't forget the first step in your interface view).
Objective-C
FAEmbeddedView *embeddedView = [[FAEmbeddedView alloc] init];
[self.myEmbeddedViewContainer addSubView:embeddedView];
SWIFT
let embeddedView = FAEmbeddedView()
self.myEmbeddedViewContainer.addSubView(embeddedView)
And after you just have to call one of theses methods:
Objective-C
FAEmbeddedView *embeddedView = [FAEmbeddedView displayBigForDebuggingWithMaxheight:INTEGER] // Display a embedded with a big height (around 600)
FAEmbeddedView *embeddedView = [FAEmbeddedView displayRegularForDebuggingWithMaxheight:INTEGER]; // Display a embedded with a regular height (around 400)
FAEmbeddedView *embeddedView = [FAEmbeddedView displaySmallForDebuggingWithMaxheight:INTEGER]; // Display a embedded with a small height (around 200)
[YOUR_VIEW addSubview:embeddedView]
SWIFT
let embeddedView = FAEmbeddedView.displayBigForDebugging(withMaxHeight : Int) // Display an embedded view with a height of ~600px
let embeddedView = FAEmbeddedView.displayRegularForDebugging(withMaxHeight : Int) // Display an embedded view with a height of ~400px
let embeddedView = FAEmbeddedView.displaySmallForDebugging(withMaxHeight : Int) // Display an embedded view with a height of ~200px
self.myEmbeddedViewContainer.addSubView(embeddedView)
Apple Watch setup
Setup
Add the watchConnectivity.framework library to your watch and app projects.
Drag and drop the FAWatchKit2SDK.framework in the Frameworks group in the XCode project navigator (left pane) and check both the Copy boxes. Select the build scheme watch Extension, as shown below.
Usage
-
Import the
<FAWatchKit2SDK/FAWatchKit2SDK.h>
header file in your InterfaceController.h and NotificationController.h header files. -
Add the following code as the first line of the
awakeWithContext:
method, in the InterfaceController.m file:[FAWatchKit2SDK configureForMainInterfaceController:self];
-
Add the following code outside the
self
block of theawakeWithContext:
method, in the NotificationController.m file:[FAWatchKit2SDK configureForNotificationInterfaceController:self];
-
If you defined a glance for you watch app, import the
<FAWatchKit2SDK/FAWatchKit2SDK.h>
header file in your GlanceController, and add the following code as the first line of theawakeWithContext:
method:[FAWatchKit2SDK configureForGlanceInterfaceController:self];
Then you can log events and errors the way you do it with the main SDK:
+ (BOOL)logEventWithName:(NSString *)name details:(id)details;
+ (BOOL)logErrorWithName:(NSString *)name details:(id)details;
Manual install
Cocoapods is the prefered method
Even though you can install the SDK manually, cocoapods is the prefered method, since it will take care of much of the work and ensure your SDK is easily updated.
-
Drag and drop the FollowApps.framework in the Frameworks group in the Xcode project navigator (left pane) and check both the Copy box and your target's.
-
Go to your project configuration, select your target. Under the General pane, add the following frameworks (if not already listed) in the Linked Frameworks and Libraries section:
- Security.framework
- SystemConfiguration.framework
- CoreTelephony.framework
- CoreLocation.framework
- libc++.dylib (before iOS 9) or libc++.tbd (iOS 9 and later)
- libsqlite3.dylib (before iOS 9) or libsqlite3.tbd (iOS 9 and later)
- UserNotifications.framework
- libz.tbd
- MobileCoreServices.framework
- ZipArchive.framework (You can find it in the zip folder)
-
Under the Build Settings pane, look for the Other Linker Flags entry, and add it the following value:
-objC -lz -lc++ -lsqlite3
-
To improve the accuracy of your crash reports on the platform, look for Strip style, and set it to Debugging Symbols
-
Now, you can proceed to configuring and validating your setup.
Manual integration
In this integration you will have to listen to our delegate followAppsDelegate, a couple of methods of your AppDelegate and UNUserNotificationCenter to forward them to us. This is needed so we can track the UIApplication lyfe cycle (EnterBackground, EnterForeground, …).
For example :
func applicationDidEnterBackground(_ application: UIApplication) {
FAFollowApps.sharedFA().applicationDidEnterBackground(application)
}
You will find here a sample project to show you how to do the non-automatic integration with all methods require.
Misc
Opt-out
Setup
To allow your user to opt-out of data collection, drag and drop the Settings.bundle file in the Xcode project navigator. It'll add a settings pane in the settings app on their device, in which they will find a switch that they can turn off to disable logging.
If you already have a settings bundle, simply add the two items from the provided bundle into yours (in the same order).
Settings bundle localization
In order to add localizations for the Settings bundle the procedure is as follows:
- Right-click the Settings.bundle in the Finder and click Show Package Contents
- Duplicate the en.lproj folder and change its name to match the locale you want to add, e.g. fr.lproj for French locale.
- The files should now appear in Xcode (you may need to open and close the directory hierarchy to get it to refresh). At this point it is simple to edit the Root.strings.
As an example, the French localization of the file looks like this:
/* Localize the settings strings here if needed */
"Anonymous usage reports" = "Rapports d'Usage Anonymes";
"Help us improve the app by sending anonymous usage reports. Your data is not shared with third parties." =
"Aidez-nous à améliorer l'application en envoyant anonymement les rapports d'usage. Vos données ne seront pas partagées avec des tiers.";
"Send usage reports" = "Envoyer les rapports";
Access your original Swift AppDelegate
If you need to access your application's original delegate
you can now use:
FAFollowApps.applicationDelegate()
Handling URLs in your application
Apple introduced App Transport Security (ATS) in iOS 9 to improve user security and privacy by requiring apps to use secure network connections over HTTPS. At WWDC 2016 they announced that apps submitted to the App Store will be required to support ATS at the end of the year. To give you additional time to prepare, this deadline was extended. Apple has yet to announce the new date. Learn more about it here.
While this security policy is not enforced you can load unsafe urls by adding the folloing exception to your .plist
.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
When creating campaigns in FollowAnalytics, you will be able to use URLs for message contents or actions. We recommend using HTTPS, but if you cannot, you will need to add this exception in your .plist file.
Migrating from older versions
Migrating 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 geoffencing in your app. You have to call this method :
+ (void)enableGeoffencing;
Migrating 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)removeCustomUserAtributeSet:(NSSet *)set fromSetWithKey:(NSString *)key // remove a set of string element from a specify set
Migrating 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.
Migrating 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
by:
- (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.