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
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" debugStateOn:FADEBUG options:launchOptions];
SWIFT
class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool { FAFollowApps.configureWithId("API_KEY_STRING", debugStateOn:true/false, options:launchOptions)
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
anytime after you have configured the SDK:
Objective-C
[FAFollowApps configureWithId:@"API_KEY_STRING" debugStateOn:FADEBUG options:launchOptions];
...
[FAFollowApps registerForPush];
SWIFT
FAFollowApps.configureWithId("API_KEY_STRING", debugStateOn: true/false, options: launchOptions)
...
FAFollowApps.registerForPush()
UserNotifications framework
Reminder: when using the UserNotification framework, you must implement the method bellow to handle the push received (only in foreground), otherwise your app will crash.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
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.
Don't miss your only shot!
You only get to ask a user once if they accept to receive push notifications from your app.
Try not to register for push notifications without telling the user why you offer this feature. When one knows what to expect, they are more likely to opt-in.
You could even build your own pre-question, asking the user if they'd like to be notified. Should they say yes, only then register for the push notifications. If you do so, don't forget to still call the registerForPush
method every now and then to ensure the push token is sync'ed with the FollowAnalytics servers.
Conflict with Notification Categories
If you register interactive notification categories and use our registerForPush
method, make sure you register categories after calling registerForPush
.
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
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.
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.
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).
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)
}
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 allow for interactive notifications, you need to register actions in your code. 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.
Conflict with Notification Categories
If you register interactive notification categories and use our registerForPush
method, make sure you register categories after calling registerForPush
.
To register actions, you can proceed as follows:
Objective-C
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
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
.
Apple Watch setup
Setup
Don't update the pod
If you are using pods to integrate the FollowAnalytics SDK, do not update it, because you are currently using a specific version not released yet on pods.
Please integrate the SDK version that we sent you with the FAWatchKit2 SDK. You just have to replace the old framework by the new one.
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
- PassKit.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
-
Under the Build Settings pane, look for the Other Linker Flags entry, and add it the following value:
-objC -all_load
-
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.
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 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.