Xamarin FollowAnalytics SDK versions
The current versions of the FollowAnalytics SDK for Xamarin are based on the native SDK. The versions of these native SDKs are the following:
Integration
The FollowAnalytics SDK Xamarin component provides full bindings to the FollowAnalytics SDK for use in Visual Studio. With this component, Xamarin developers can target both iOS and Android devices with access to the full scope of the FollowAnalytics SDK, all while remaining in the C#/.NET ecosystem.
This document will cover app setup and the component installation process, as well as basic integration steps for iOS and Android.
For more information, please read the iOS and Android FollowAnalytics SDK documentations.
Prerequisites and minimal setup
In this section, we explain how to get started with FollowAnalytics SDK for Xamarin. Before you start, be sure to have all the necessary prerequisites. These include:
- Registering the application on the Platform
- Generating the API Key
Here are the minimal 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. Then, you can start tagging events and saving attributes in your app.
Installation
Download the FollowAnalytics SDK from the developer portal.
To install the iOS/Android part of the SDK, follow these steps:
-
Right Click on project References.
-
Choose
Edit References ....
-
Choose the
.Net Assembly
tab. -
Go to
Browse...
-
Add
FollowAnalyticsSDK.iOS.dll
to your iOS Xamarin project References andFollowAnalyticsSDK.Android.dll
to your Android Xamarin project References.
Dynamic registrar issue
If there is any dynamic registrar issue
in the iOS app, you need to add --optimize=-remove-dynamic-registrar
flag to MTouchExtraArgs in iOS Build
tab in the project settings.
Initialize with your API keys
Be sure to have your API key
Be sure to have your API key for this step of the configuration. You can retrieve you app's API key from the administration section of the FollowAnalytics platform.
iOS
- In your
AppDelegate.cs
add at the top:
using FollowAnalyticsSDK;
- In the method
FinishedLaunching
, right after theloadApplication
, add:
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
...
FollowAnalytics.Configuration configuration = new FollowAnalytics.Configuration((obj) =>
{
obj.apiKey = "YOUR_API_KEY";
obj.isVerbose = true; //Optional, false by default
});
FollowAnalytics.iOS.Init(configuration, launchOptions);
...
}
Android
Google Play Service version
The SDK requires version 8.4.0 or higher of the google-play-service
dependency. Install or update it from the Android Extras section using the Android SDK manager (run android
).
To initialize FollowAnalytics SDK, you need to configure FollowAnalytics SDK by creating the Configuration and setting the api key.
Create a class that extends Application
and call FollowAnalytics.Android.Init(Context context, FollowAnalytics.Configuration configuratio)
in the onCreate()
method of your class.
This is necessary to have the SDK initialized in all cases: either when app is launched by the user, or when the Android OS wakes the app (for example, at push notification receiving).
Open your Application subclass, or create a new one, and add the following lines to override the onCreate
method:
using System;
using Android.App;
using Android.Util;
using Android.Runtime;
using FollowAnalyticsSDK;
namespace FollowAnalyticsSDK.Android.Sample {
[Application(Label = "@string/app_name")]
public class MyApplication : Application {
public MyApplication(IntPtr handle, JniHandleOwnership ownerShip) : base(handle, ownerShip) {
}
public override void OnCreate() {
base.OnCreate();
FollowAnalytics.Configuration mConfig = new MyConfiguration(); // Configuration class created
FollowAnalytics.Android.Init(this, mConfig);
}
}
}
If you just created an Application subclass, remember to declare it in your AndroidManifest.xml
file:
<application
android:name=".MyApplication"
/>
Custom Configuration
In order to customize the behavior of FollowAnalytics SDK, it is possible to change the default configuration.
In order to achieve this, you need to :
- Create a class that extends to
FollowAnalytics.Configuration
with the parameters that are necessary to be changed and override call backs. - The basic configuration should have at least the
ApiKey
parameter. All other parameters are optional :
using FollowAnalyticsSDK;
namespace FollowAnalyticsSDK.Android.Sample
{
public class MyConfiguration : FollowAnalytics.Configuration
{
public MyConfiguration() {
this.ApiKey = "YOUR_API_KEY";
}
}
}
Now, FollowAnalytics SDK will start by default with the value associated in the customized configuration class.
Setting up push notifications
iOS
Add a push certificate for notifications
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.
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).
After generating a .p12
push certificate or a .p8
server Key, you need to go to your project in Visual Studio :
-
Open your info.plist file
-
Enable Background Modes
-
Check Remote Notification and Background fetch
-
Open your Entitlements.plist
-
Scroll down
-
Check the push notification capabily
Finnaly, you need to add a call to registerForPush
following the initialization line you added previously:
FollowAnalytics.iOS.RequestNotificationAuthorization();
Enable quiet notifications
Since iOS 12, Apple introduced a way to receive non-interruptive notifications before the user grants notification authorization. These are notification delivered quietly (no sound, no banner) and that are only displayed in the Notification Center.
You can allow your app to receive quiet notifications from FollowAnalytics as soon as it's installed on the user's device. To do so, just call requestProvisionalNotificationAuthorization in the FinishedLaunching
method of your app delegate, after the SDK initialization call.
FollowAnalytics.RequestProvisionalNotificationAuthorization();
Android
Reminders
Build in release mode
The application must be built in release mode in order to receive push notifications
Notification channel for Android 8.0 (Oreo)
Since Google has refactored of its "Notification system" for Android 8.0 ("Oreo"), (details here) FollowAnalytics SDK uses default_notification_fa
as an id for id for the NotificationChannel
object.
Notification icon customization
The SDK will use your applauncher icon as default notification icon. You could change this by adding a ic_fa_notification.png
file in your drawable folders.
If you wish to have a custom background color on your notifications, you can add a value to your color.xml
: <color name="ic_fa_notification_color">#ff0000</color>
.
Be sure to follow Google's guidelines for notification icons on Android.
In order to make sure that your custom notifications logo will be properly displayed on every device, you should have all these files in your project :
file path | image size |
---|---|
res/drawable-mdpi/ic_fa_notification.png | (24x24px) |
res/drawable-hdpi/ic_fa_notification.png | (36x36px) |
res/drawable-xhdpi/ic_fa_notification.png | (48x48px) |
res/drawable-xxhdpi/ic_fa_notification.png | (72x72px) |
res/drawable-xxxhdpi/ic_fa_notification.png | (96x96px) |
res/drawable-xxxhdpi/ic_fa_notification.png | (256x256px) |
Implementation and setup
The FollowAnalytics SDK supports push notifications based on Firebase Cloud Messaging. If you haven't done so already, you will need to create/add a Firebase Project in Firebase Console in order to continue the following steps.
-
Add the required Packages to your project:
- Xamarin.Firebase.Common (version >= 71.1610.4)
- Xamarin.Firebase.Iid (version >= 71.1710.4)
- Xamarin.Firebase.Messaging (version >= 71.1740.4)
-
Add those FCM Receiver tags to your manifest
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" /> <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND"> <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> <category android:name="${applicationId}" /> </intent-filter> </receiver>
-
Create a class that extends to
FirebaseMessagingService
and override the methodsOnMessageReceived
andOnNewToken
:using Android.App; using Android.Content; using Firebase.Messaging; using FollowAnalyticsSDK; namespace FollowAnalyticsSDK.Android.Sample { [Service] [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })] public class MyFirebaseMessagingService : FirebaseMessagingService { public override void OnMessageReceived(RemoteMessage message) { FollowAnalytics.Android.ProcessFirebaseMessage(Application.Context, message); } public override void OnNewToken(string token) { FollowAnalytics.Android.SetPushToken(token); } } }
-
Add the
FirebaseMessagingService
service tag in yourAndroidManifest
application file by changing the value associated withandroid:name
. In order to do this, you need to retrieve the value associated to the name of the Android Callable Wrapper for your custom implementation. The easiest way to get the value at runtime, is to implement the following code://import the namespace in your activity using Android.Util; //implement this code in one of the lifecycle method of your activity Log.Debug("FA","The MyFirebaseMessagingService name is : " + Java.Lang.Class.FromType(typeof(<ABSOLUTE_PATH_OF_THE_CLASS>.<NAME_OF_THE_FIREBASE_MESSAGING_SERVICE>)).Name);
For instance:
Log.Debug("FA", "The MyFirebaseMessagingService name is : " + Java.Lang.Class.FromType(typeof(MyFirebaseMessagingService)).Name);
This will output a similar result, at runtime, in the Logcat console:
FA D The MyFirebaseMessagingService name is : md56f33aca13e7603ac857c2a0fb45b66ab.MyFirebaseMessagingService
Finally, copy the result and paste it to
android:name
value as shown below:<service android:name="md56f33aca13e7603ac857c2a0fb45b66ab.MyFirebaseMessagingService"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
-
Do not forget to add the next lines of code inside of
OnMessageReceived
method :FollowAnalytics.Android.ProcessFirebaseMessage(Application.Context, message); // Pass the push notification to FollowAnalytics SDK
-
Also do not forget to add this line of code inside of
OnNewToken
method :7. Download theFollowAnalytics.Android.SetPushToken(token); // Function that pass the FCM token retrieved to FollowAnalytics SDK
google-services.json
file in your Firebase Project and add it to your Xamarin Project. -
Set the
GoogleServicesJson
as action to yourgoogle-services.json
by right clicking the file. -
Finally, do not forget to copy the FCM Server key token (available through Firebase Console in your project settings).
and paste it to our platform in the application's administration.
Verify your Google Services configuration
Be sure to check the configuration of Google Services as they have to be the following if you want the FollowAnalytics SDK and Firebase to work.
- The JSON for Google Services in your application is correct. Compare if it is the same as the one in Firebase (which you can download from the Firebase Console)
Define the URL scheme
To allow users to retrieve their device ID for campaign testing and tagging plan debugging, you need to define a URL scheme in your iOS and Android projects.
iOS
-
Make sure that the Rivets component is installed. If not, install with NuGet.
-
Open your app's Info.plist file, and under the Advanced tab, in the URL Types section, add a new URL Type like:
-
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).
Android
- Edit your AndroidManifest.xml file to add this:
<activity android:name="com.followapps.android.internal.activities.DeviceIdActivity" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="followanalytics.com"
android:path="/deviceId"
android:scheme="%YOUR_APP_PACKAGE_NAME%" />
</intent-filter>
</activity>
- Replace
%YOUR_APP_PACKAGE_NAME%
with the Android package name of your app.
Analytics
Events vs Attributes
The FollowAnalytics SDK allows you to tag both events and attributes. In this section, we explain how to utilize 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 sent in debug mode will not appear on dashboards
When your application 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.
App tags
The SDK allows you to implement log events and errors in your code. The following methods that you can call with the SDK are the following:
FollowAnalytics.LogEvent(string eventName);
FollowAnalytics.LogEvent(string eventName, string details);
FollowAnalytics.LogEvent(string eventName, IDictionary<string, string> details);
FollowAnalytics.LogError(string eventName);
FollowAnalytics.LogError(string eventName, string details);
FollowAnalytics.LogError(string eventName, IDictionary<string, string> details);
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.
Use the eventName as the unique identifier of your tag. Use the details section to add specific details or 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 way:
FollowAnalytics.LogEvent("Product view", "Product reference");
var options = new Dictionary<string, string>();
options["product_id"] = "ABCD123";
options["product_category"] = "Jeans";
FollowAnalytics.LogEvent("Add product to cart", options);
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 applications.
In both cases, attributes can be used in segments and campaigns to target users.
User ID
If users can sign in somewhere in your application, 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.
It is recommended to use a cryptographic number that uniquely ties your customer to you.
To register the user identifier, use:
FollowAnalytics.SetUserId("1547521wed2155w57e02dwe574");
If you want to remove the user identifier (in case of a sign out for instance) use the following method:
FollowAnalytics.SetUserId(null);
At any moment, you can retrieve the current user ID this way:
string user_id = FollowAnalytics.GetUserId(); // returns null if there is no user id
Predefined attributes
The SDK allows to set values for both custom and predefined attributes.
For predefined attributes, the SDK has the following properties:
FollowAnalytics.UserAttributes.SetFirstName("Peter");
FollowAnalytics.UserAttributes.SetLastName("Jackson");
FollowAnalytics.UserAttributes.SetCity("San Francisco");
FollowAnalytics.UserAttributes.SetRegion("California");
FollowAnalytics.UserAttributes.SetCountry("USA");
FollowAnalytics.UserAttributes.SetGender(FollowAnalytics.Gender.Male);
FollowAnalytics.UserAttributes.SetEmail("mail@mail.com");
FollowAnalytics.UserAttributes.SetDateOfBirth(DateTime.Today);
FollowAnalytics.UserAttributes.SetProfilePictureUrl("https://picture/picture");
They are "predefined" in the sense that they will be attached to default fields on your user profiles.
To unset an attribute, set it to null
. For instance :
FollowAnalytics.UserAttributes.SetFirstName(null);
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:
FollowAnalytics.UserAttributes.SetNumber("key_number", 1);
FollowAnalytics.UserAttributes.SetNumber("key_double", 32.428);
FollowAnalytics.UserAttributes.SetDate("key_date", DateTime.Today);
FollowAnalytics.UserAttributes.SetDateTime("key_dateTime", Date.Now);
FollowAnalytics.UserAttributes.SetString("key_string", "string");
FollowAnalytics.UserAttributes.SetBoolean("key_bool", true);
For example, to set the user's job:
FollowAnalytics.UserAttributes.SetString("job", "Taxi driver");
Delete a custom attribute value
You can clear the value of an attribute using its key. For instance, to delete the user's job:
FollowAnalytics.UserAttributes.Clear("job");
Set of Attributes
You can add or remove an item to or from a set of attributes.
To add an item:
FollowAnalytics.UserAttributes.AddToSet("fruits", "apple");
To add several items:
FollowAnalytics.UserAttributes.AddToSet("fruits", "orange", "banana");
To remove an item:
FollowAnalytics.UserAttributes.RemoveFromSet("fruits", "orange");
And to clear a set:
FollowAnalytics.UserAttributes.ClearSet("fruits");
Opt-out Analytics
What is Opt-out analytics?
The SDK can be configured to no longer track user information. This is what we call to opt out of analytics.
Once opted-out, no new data is collected, nor is it stored in the app. New session are not generated at launch and nothing is sent back to the server. This data includes the following:
- tagged elements such as events, errors
- new user identification and attributes
- crash reports
When a user is opted-out of analytics, campaigns will continue to work with the following limitations:
- No Contextual campaigns - as they depend on log tracking
- No Transactional campaigns - as they depend on the user ID
- No Dynamic campaigns - as they depend on users entering a segment
- Campaigns filters will depend on old data (before the user opted-out)
All data collected before the user has opted-out is preserved within FollowAnalytics servers. This means that a user having opted-out will still receive campaigns based on data acquired before opting out (previous campaigns, existing segments, etc). The opt-in state is persisted between app starts (unless storage of the app is emptied).
To inspect and set the opt-out state, call the following methods on FollowAnalytics class:
FollowAnalytics.SetOptInAnalytics(bool optInAnalytics);
FollowAnalytics.GetOptInAnalytics();
Please see additional doc in the new FollowAnalytics and FollowAnalyticsConfiguration interface for more details.
Additionally, if the opt-in by default policy doesn't suit your use case you can change it by setting the optInAnalyticsDefault
on FollowAnalyticsConfiguration.
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.RequestToAccessMyData();
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
Notification Service Extension Framework
Rich notifications are notifications with embedded rich media (images, GIFs, videos). When defining a Push campaign on the platform, you can add a rich media to the notification.
A badge is the number displayed on the icon of the app, indicating to the user that the app has new information. On the platform, you can set by how much the badge is to be increased or decreased at the notification reception on the user's device. This is defined as the badge increment in the Campaign Editor.
The SDK allows your app to receive rich notifications and to manage badges thanks to the FANotificationExtension
notification service extension framework. In this section, we will see how to install and use this extension framework by:
- Adding a Notification Service Extension target
- Installing from CocoaPods or manually
- Setting an App Group for both app and extension targets
- Configuring the SDK to work with the extension
- Implementing the extension
- Managing badges
Notification Service Extension and iOS version
FANotificationExtension
is only available on iOS 10.0 and above. If a user has a device with iOS version under 10.0, he will receive rich notifications but not be able to see the rich media included. Also he will not able to see your app icon's badge change done through the extension framework.
Add the Notification Service Extension
To handle rich notification you need to implement Notification Service Extension .
Build in release mode
To receive rich push notification, the app should be build in release mode.
Bundle identifier should be lower case
The bundle identifier
of the host application and notification service extension should be in lower case.
Install FANotificationExtension
To install the FANotificationExtension
SDK, follow these steps:
-
Right Click on project References.
-
Choose
Edit References ....
-
Choose the
.Net Assembly
tab. -
Go to
Browse...
-
Add
FANotificationExtension.dll
to your Service Extension Xamarin project References.
Set an App Group for both app and extension targets
To let host application and notification service extension communicate, you need to create an AppGroup which will be shared between them.
Configuring the SDK to work with the extension
First, make sure you have set the proper App Group for the app target:
The appGroup
parameter should be specified in the configuration init of the SDK:
FollowAnalytics.Configuration configuration = new FollowAnalytics.Configuration((obj) =>
{
...
obj.appGroup = @"group.your.identifier";
});
Implement the Notification Service Extension
First, make sure you have set the proper App Group for the extension target:
Copy and paste the following implementation in the NotificationService
file of the extension you created
using System;
using Foundation;
using UserNotifications;
namespace FollowMeExtension
{
[Register("NotificationService")]
public class NotificationService : UNNotificationServiceExtension
{
Action<UNNotificationContent> ContentHandler { get; set; }
UNMutableNotificationContent BestAttemptContent { get; set; }
protected NotificationService(IntPtr handle) : base(handle)
{
// Note: this .ctor should not contain any initialization logic.
}
public override void DidReceiveNotificationRequest(UNNotificationRequest request, Action<UNNotificationContent> contentHandler)
{
ContentHandler = contentHandler;
BestAttemptContent = (UNMutableNotificationContent)request.Content.MutableCopy();
FANotificationExtension.NotificationService.GetFAContentIfNeededWithRequest(request,
BestAttemptContent, "group.your.identifier", (newContent) => {
ContentHandler(newContent);
});
}
public override void TimeWillExpire()
{
// 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.
ContentHandler(BestAttemptContent);
}
}
}
Badge Management
Prerequisites
For using this feature, make sure you have installed and configured FANotificationExtension properly. More information here
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 management, add the following instruction just before the SDK initialization:
FollowAnalytics.Badge.Enable()
FollowAnalytics.Badge
class lets you set and get the badge value thanks to the following methods:
FollowAnalytics.Badge.Set(Int) // Set the value of the icon badge number
FollowAnalytics.Badge.UpdateBy(Int) // Update the value of the icon badge number
FollowAnalytics.Badge.Get() // Get the value of the icon badge number
FollowAnalytics.Badge.Clear() // Clear the icon badge number
Implement custom behavior on URL opening (iOS only)
From the FollowAnalytics platform, you can add URLs (website links or custom URL schemes) to your Push or InApp campaigns. By default, those links will be opened by the SDK, unless the shouldOpenURL
callback is defined on the FollowAnalyticsConfiguration provided at SDK initialization.
Implement shouldOpenURL
to handle Universal Links to your own website
Universal Links allow your app to be opened to handle links that point to your website. Due to the behavior of the iOS method OpenUrl(NSUrl, UIApplicationOpenUrlOptions, ActionshouldOpenURL
.
You can handle links with your own URL opening logic by implementing the shouldOpenURL
callback in FollowAnalyticsConfiguration. Use the return value of this callback to allow the SDK to actually open the URL or not:
-
If return value is
true
the SDK will open the URL. Be careful that the SDK will not able to open Universal Links to your own website. -
If return value is
false
the SDK will not open the URL and it will be the your responsibility to implement the opening of the URL.
obj.shouldOpenUrl = delegate(Uri uri)
{
// YOUR_IMPLEMENTATION
// Returning `true` will tell the SDK to automatically open the URL.
return true;
};
Opt-in Notifications
The FollowAnalytics SDK opt-in notifications status defines whether your app will receive notifications from your Push campaigns. Opt-in notifications is true
by default, meaning notifications from your Push campaigns will be received by your app. This status is independent from the system notification authorization, which is also needed by your app to display notifications.
Thanks to this opt-in notifications status, you can implement a UI in your app to allow to choose whether to receive notifications, without the need to go to the system notification authorization settings. Note that the opt-in notifications status will have no effect if the system notification authorization is not allowed, and in this case, your app will not receive notifications from your Push campaigns, whatever the opt-in notifications status.
To update your app UI to reflect the current opt-in notifications status, use the GetOptInNotifications
method:
public static bool GetOptInNotifications()
To update the current opt-in notifications status upon UI change, use the SetOptInNotifications
method:
public static void SetOptInNotifications(bool state)
Handling transistion from opt-out to opt-in notifications
Just calling SetOptInNotifications(true)
after the user interacts with your app UI to opts-in for notifications could be insufficient if the system notification authorization is not allowed. For this reason, we recommend to implement the following flow after the user opts-in for notifications in your app:
- Check the return value of
FollowAnalytics.GetPushNotificationsRegistrationStatus()
which istrue
only if the system notification authorization is allowed AND the SDK opt-in notifications status istrue
. - If
false
, display a message and button to invite your user to enable the system notification authorization. - Call
FollowAnalytics.OpenNotificationSettingsEventually()
when the user taps the button. The method will take care of either displaying the notification authorization request alert (iOS only), or directing to the app settings screen. This will allow the user to enable notifications.
Another possibility is to bypass the first two steps and only implement the last one.
It's possible to set the opt-in notifications status to false
at the SDK initialization by setting the optInNotificationsDefault
parameter to false
in the FollowAnalyticsConfiguration object passed to the initialization method. This is only used to set the default opt-in value at the first launch of the app. Note that calling the setOptInNotifications
will persist the opt-in notifications status for all subsequent launch of your application, meaning optInNotificationsDefault
will be ignored.
Interactive notifications
An Interactive Notification is a notification containing custom action buttons that the user can access by revealing the notification:


When tapped, an action button will:
- Close the notification.
- Eventually launch your application in the foreground, if you specified it explicitly when creating the action (See details below). Otherwise your app is not opened.
- Execute the custom behavior you implemented for the notification tap.
To create a campaign with Interactive Notifications:
-
On the platform, create a Push Campaign and define a Category(iOS)/Action Key(Android) in the Interactive Notification section of the campaign editor. For our example, let's set this field to
"NewContent"
. -
In your app, define the action names you want for your notification, we will call them
actionIdentifiers
. Those identifiers will be displayed as is on the platform in the Push Opened stats:const string ActionIdentifierDelete = "Delete"; const string ActionIdentifierView = "View"; const string ActionIdentifierRemind = "Remind me tomorrow";
-
On Android add action buttons to the notification by using the
FollowAnalytics.NotificationBuilder.addAction(Context context, int icon, String actionLabel, String actionIdentifier)
method in your implementation of theOnPushMessageNotificationBuilding()
callback. TheactionLabel
argument is your localized String that represents your action button's text and theactionIdentifier
should be used as a unique identifier for each of your action buttons. This identifier will be passed as an argument to theonPushMessageClicked
callback, which will be called whenever an action button is clicked on, so you can identify which action button has been clicked on.An example of adding buttons to the notification on Android is available below. Please note how the "NewContent" field defined above is used.
public override void OnPushMessageNotificationBuilding(Context context, Com.Followanalytics.FollowAnalytics.NotificationBuilder notificationBuilder, Com.Followanalytics.FollowAnalytics.IMessage message) { if (message.Category == "NewContent") { notificationBuilder.AddAction(context, Resource.Drawable.ic_menu_send, context.Resources.GetString(Resource.String.view), ActionIdentifierDelete); notificationBuilder.AddAction(context, Resource.Drawable.ic_menu_send, context.Resources.GetString(Resource.String.delete), ActionIdentifierView); notificationBuilder.AddAction(context, Resource.Drawable.ic_menu_send, context.Resources.GetString(Resource.String.remind_me), ActionIdentifierRemind); } }
-
On iOS add action buttons to the notification by adding the following lines in your AppDelegate's
FinishedLaunching
method :var viewAction = UNNotificationAction.FromIdentifier(ActionIdentifierView, NSBundle.MainBundle.GetLocalizedString(ActionIdentifierView), UNNotificationActionOptions.Foreground); var deleteAction = UNNotificationAction.FromIdentifier(ActionIdentifierDelete, NSBundle.MainBundle.GetLocalizedString(ActionIdentifierDelete), UNNotificationActionOptions.Destructive); var remindMeAction = UNNotificationAction.FromIdentifier(ActionIdentifierRemind, NSBundle.MainBundle.GetLocalizedString(ActionIdentifierRemind), UNNotificationActionOptions.Destructive); var actions = new UNNotificationAction[] { viewAction, deleteAction, remindMeAction}; var category = UNNotificationCategory.FromIdentifier("NewContent", actions, new string[] { }, UNNotificationCategoryOptions.CustomDismissAction); var notificationCenter = UNUserNotificationCenter.Current; notificationCenter.SetNotificationCategories(new NSSet<UNNotificationCategory>(category));
Note that the notification action title is a localized version of the
actionIdentifier
, while the platform displays theactionIdentifier
as is in the Push Opened stats.
Implement custom behavior on notification tap
iOS
You can implement a custom behavior when the user taps on a notification by implementing the onNotificationTapped
callback in FollowAnalyticsConfiguration. This allows you to perform specific actions when a notification is tapped:
obj.onNotificationTapped = delegate(FollowAnalytics.NotificationInfo notification, string actionIdentifier)
{
// YOUR_IMPLEMENTATION
// To open received URL you can use this code :
if (notification.url != null) {
UIApplication.SharedApplication.OpenUrl(notification.url);
}
};
The SDK passes some Push campaign information to your app through this callback thanks to the notificationInfo argument , The NotificationInfo
is an object with the following attributes :
Parameter | Type | Description |
---|---|---|
messageId |
string | Containing the FollowAnalytics campaign identifier. |
isSilent |
bool | Telling if the notification is silent or not. In onNotificationTapped, this property is always false. |
url |
Uri | Containing App Link value defined in the campaign editor. |
parameters |
IDictionary | Containing the key/value pairs defined in the campaign editor. |
Add background fetch capability
For your app to be woken-up to execute your implementation of onNotificationReceived
when your app is in background, you must activate the Background Fetch
capability in the Background Modes
. Note that your code implemented in in this callback must not take more that 30s to execute. Otherwise the callback execution will be stopped by iOS. As a consequence, when using this callback to fetch data, make sure data size not too big compared to the data connection speed of your users.
Implement only synchronous calls
The SDK executes your onNotificationReceived
code in a background thread and expects that the whole callback implementation is synchronous. Any asynchronous call is not guaranteed to finish before the end of the callback execution and then will be terminated at the time the callback execution is finished. Make sure that your implementation follows those rules, to ensure proper runtime execution:
- All statements are synchronous calls.
- No call to any API that should be called on the main thread.
While the actionIdentifier argument provides information about which notification button has been tapped :
The actionIdentifier
is a String containing the identifier for the tap action. It can be either :
- FANotificationDefaultActionIdentifier when user tapped on a regular notification, or on the default button of a category notification.
- FANotificationDismissActionIdentifier when user tapped on the dismiss button of a category notification.
- Your custom defined action identifier when user tapped on a custom button of a category notification.
Android
In FollowAnalytics campaigns through our platform, 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.).
To obtain these parameters, you can extend the FollowAnalytics.DefaultMessageHandler
class, like in the following example:
//import the namespace
using System.Collections.Generic;
using Android.Content;
....
public class CustomMessageHandler : FollowAnalytics.DefaultMessageHandler
{
public override void OnPushMessageClicked(Context context, string url, IDictionary<string, string> parameters){
base.OnPushMessageClicked(context, url, parameters);
//Write code to process information
}
public override void OnPushMessageClicked(Context context, IDictionary<string, string> parameters){
base.OnPushMessageClicked(context, parameters);
//Write code to process information
}
}
If you chose to define a custom MessageHandler
, you must declare it in your application on your AndroidManifest file as meta-data.
In order to do this, you need to retrieve the value associated to the name of the Android Callable Wrapper for your custom implementation.
The easiest way to get the value at runtime, is to implement the following code:
//import the namespace in your activity
using Android.Util;
//implement this code in one of the lifecycle method of your activity
Log.Debug("FA","The CustomMessageHandler name is : " + Java.Lang.Class.FromType(typeof(<ABSOLUTE_PATH_OF_THE_CLASS>.<NAME_OF_THE_CUSTOM_MESSAGE_HANDLER_CLASS>)).Name);
For instance:
Log.Debug("FA","The CustomMessageHandler name is : " + Java.Lang.Class.FromType(typeof(FollowAnalyticsSDK.Android.Sample.CustomMessageHandler)).Name);
This will output a similar result, at runtime, in the Logcat console:
FA D The CustomMessageHandler name is : md5dc1df9376dd70f35e4f0f156de0b2eea.CustomMessageHandler
Nothing appears in Logcat console
The problem can be due to the wrong absolute path or the activity that has not executed the line of code (wrong place). Consider to recheck your code.
Finally, copy the value and paste it to the attribute android:value
in your <meta-data> tag.
For instance:
<application>
[...]
<meta-data android:name="com.followanalytics.deeplinking.handler" android:value="md5dc1df9376dd70f35e4f0f156de0b2eea.CustomMessageHandler"/>
[...]
</application>
Don't change the attribute android:name
The content associated to the attribute android:name
must not be changed !
It is used by the FollowAnalytics SDK in order to find the customized class.
Consider to test those changes before removing the code which retrieves the value associated to the name of the Android Callable Wrapper.
Implement custom behavior on Push reception
You can implement a custom behavior when the device receives a message from a Push campaign that contains custom parameters (i.e. at least one key/value pair). This can be used to fetch data from your server if a particular custom parameter is defined in the Push message. To do so, implement the onNotificationReceived
callback in FollowAnalyticsConfiguration:
iOS
The call back need to be implemented in the configuration object in the AppDelegate
class :
obj.onNotificationReceived = delegate(FollowAnalytics.NotificationInfo notification)
{
// YOUR_IMPLEMENTATION
// To open received URL you can use this code :
if (notification.url != null) {
UIApplication.SharedApplication.OpenUrl(notification.url);
}
};
Android
The call back need to be implemented in the custom configuration class that you created :
public override void OnNotificationReceived(Com.Followanalytics.FollowAnalytics.IMessage p0) // Optional, called when new app received a notification
{
// YOUR_IMPLEMENTATION
}
The SDK passes some Push campaign information to your app through this callback thanks to the message argument , The IMessage
is an object with the following attributes :
Parameter | Type | Description |
---|---|---|
IsSilentPush |
bool | Telling if the notification is silent or not. In onNotificationTapped, this property is always false. |
Body |
string | Containing the body of the campaign. |
Params |
Map |
Containing the key/value pairs defined in the campaign editor. |
Id |
string | Containing the identifier. |
ReceivedDate |
string | Telling the received date of the message. |
DeepLinkUrl |
string | Containing App Link value defined in the campaign editor. |
IsPush |
bool | Telling if the inapp is a push notification. |
MessageType |
string | Telling the type of the message . |
IsRead |
bool | Telling if the message is read. |
Implement custom behavior on Native Alert button tap
iOS
You can implement a custom behavior when the user taps on a Native Alert button by implementing the onNativeInAppButtonTapped
callback in the FollowAnalyticsConfiguration. This allows you to perform specific actions when a native alert button is tapped:
obj.onNativeInAppButtonTapped = delegate (FollowAnalytics.CustomButtonInfo customButton) {
// YOUR_IMPLEMENTATION
};
The iOS SDK passes some Native Alert campaign information to your app through this callback thanks to the buttonInfo argument:
Parameter | Type | Description |
---|---|---|
campaignId |
string | Containing the FollowAnalytics campaign identifier. |
url |
Uri | Containing App Link value defined in the campaign editor. |
parameters |
IDictionary | Containing the key/value pairs defined in the campaign editor. |
Android
The Android SDK allow to retreive parameters (key, value) sent in the Native Alert campaign through the callback OnInAppMessageClicked
which need to be implemented in your CustomMessageHandler
class :
//import the namespace
using System.Collections.Generic;
using Android.Content;
....
public class CustomMessageHandler : FollowAnalytics.DefaultMessageHandler
{
public override void OnInAppMessageClicked(Context context, string buttonText, IDictionary<string, string> p2){
base.OnInAppMessageClicked(p0,p1,p2);
//Write code to process information
}
}
Pausing in-app campaigns
What is pausing and resuming an in-app campaign?
Pausing campaigns are used to prevent in-app from being displayed on certain screens and views of your app. You may pause a screen of the app when it is too important, or is part of a process that is too important to be interrupted by an in-app (i.e a payment screen in the process of the user making a purchase).
When the screen is safe to display an in-app, you resume in-app campaigns. Any campaign supposed to be displayed when the mechanism is paused, is stacked and shown as soon as the mechanism is resumed. This way you can send send in-app campaigns without impacting the user experience.
To prevent the SDK from displaying rich campaigns use the following method:
FollowAnalytics.InApp.PauseCampaignDisplay();
To resume the SDK from displaying rich campaigns use the following method:
FollowAnalytics.InApp.ResumeCampaignDisplay();
Tip: Use the lifecycle concepts from android to control campaigns.
To prevent the SDK from displaying the campaigns on a given activity, call the Pause method before the creation of an activity in order to block the campaigns.
Resume the campaigns by calling the Resume method on any other place of the application which will activate them.
Archiving messages
FollowAnalytics SDK allows you to store campaigns's messages received by your app. This makes them available for custom usage, like building an inbox feature. Messages received by a device can be archived locally and accessed from the developer's code, formatted as a FollowAnalytics.Message
. In order for you to enable the message archiving, you need to set the following Configuration properties at SDK initialization:
protected boolean archivePushMessages;
protected boolean archiveInAppMessages;
You will find below all the methods you need to handle all the archived Messages.
In the FollowAnalytics
class you will find all necessary methods to manage all FollowAnalytics.Message
objects that are archived. They are implemented by FollowAnalytics.InApp
and FollowAnalytics.Push
.
- The methods are the following on both Android and iOS
public static IList<Message> GetAll(); //Get all in-app messages
public static Message Get (string id);//Get an Message by its id
public static void Delete (string[] ids); //Delete an in-app message
public static void MarkAsRead (string[] ids); //Mark one or several Message as read
public static void MarkAsUnRead (string[] ids); //Mark one or several Message as unread
And here is a description of some of the Message
attributes:
Common
Accessor | Return type | Description |
---|---|---|
Id |
string | Unique message Identifier. |
IsRead |
boolean | Indicates if the message has been read or not. False at message reception. |
IsPush |
boolean | Returns true if message comes from a Push campaign, false if it comes from a In-App campaign. |
IsInApp |
boolean | Returns true if message comes from a In-App campaign, false` if it comes from a Push campaign. |
IsSilent |
boolean | Returns true if message comes from a Push campaign with the "Silent" option enabled (silent push), false otherwise. |
Title |
string | Text provided in the platform's "Title" field of the Push campaign editor. |
Body |
string | Text provided in the platform's "Content" field of the Push campaign editor. |
Url |
string | Url provided in the platform's "URL" field of In-App Custom Web Page campaign editor. If the message comes from a Push campaign, this is the url of the Rich Media. |
ReceivedDate |
date | If message comes from a Push campaign, this is the date at which the message is received on the device. If message comes from an In-App campaign, this is the start date of the campaign. |
DeepLinkUrl |
string | Url provided in the platform's "App Link" field of the Push campaign editor. |
Params |
dictionary | Key/Value pairs provided in the Push campaign editor. |
Android
Accessor | Return type | Description |
---|---|---|
IsNotificationDismissed |
boolean | If the message comes from a Push campaign, this method returns true if the notification has been dismissed, false otherwise. |
NotificationId |
int | If message comes from a Push campaign, this is the Android notification identifier. |
iOS
Accessor | Return type | Description |
---|---|---|
Subtitle |
string | Text provided in the platform's "Subtitle" field of the Push campaign editor. |
NotificationId |
string | If message comes from a Push campaign, this is the UNNotificationRequest unique identifier (iOS >= 10.0), otherwise it's nil . |
Disabling Swizzling (iOS only)
By default, the SDK swizzles your UIApplicationDelegate methods and your UNUserNotificationCenterDelegate methods. On the other hand, this swizziling can be disabled.
FollowAnalytics.Configuration configuration = new FollowAnalytics.Configuration((obj) =>
{
obj.swizzlingEnabled = enableSwizziling;
}
Required Methods
By disabling the swizzling the SDK requires the developer to forward the following methods without exception. This is mandatory to ensure the SDK works as expected. Not doing so may cause unexpected side-effects.
The required UIApplicationDelegate
methods are:
-
didRegisterForRemoteNotificationsWithDeviceToken
:Forwarding this method the SDK will be able to send the device token to the server for Push Notifications delivery.
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken) { FollowAnalytics.RegisterForRemoteNotifications(application, deviceToken); }
-
applicationDidEnterBackground
:Forwarding this method the SDK will be able to calculate session duration, handle app badge number and detect campaign triggers.
public override void DidEnterBackground(UIApplication application) { FollowAnalytics.DidEnterBackground(application); }
-
applicationWillEnterForeground
:Forwarding this method the SDK will be able to synchronize campaigns, detect campaign triggers and present queued triggered campaigns.
public override void WillEnterForeground(UIApplication application) { FollowAnalytics.WillEnterForeground(application); }
-
applicationDidBecomeActive
:Forwarding this method the SDK will be able to calculate sessions durations and detect campaign triggers.
public override void OnActivated(UIApplication application) { FollowAnalytics.OnActivated(application); }
-
applicationWillTerminate
:Forwarding this method the SDK will be able to calculate sessions durations and handle app badge number.
public override void WillTerminate(UIApplication application) { FollowAnalytics.WillTerminate(application); }
-
applicationDidReceiveMemoryWarning
:Forwarding this method the SDK will be able to send statistics information.
public override void ReceiveMemoryWarning(UIApplication application) { FollowAnalytics.ReceiveMemoryWarning(application); }
-
didReceiveRemoteNotification
:Forwarding this method the SDK will be able to handle Push Notifications and In-App campaigns.
public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo) { FollowAnalytics.ReceivedRemoteNotification(application, userInfo); }
-
handleActionWithIdentifierForRemoteNotification
:Forwarding this method the SDK will be able to handle Push Notifications and In-App campaigns.
public override void HandleAction(UIApplication application, String identifier, NSDictionary userInfo, Action completionHandler) { FollowAnalytics.HandleAction(application, identifier, userInfo, completionHandler); }
-
handleActionWithIdentifierForLocalNotification
:Forwarding this method the SDK will be able to handle Notifications and In-App campaigns.
public override void HandleAction(UIApplication application, String identifier, UILocalNotification LocalNotification, Action completionHandler) { FollowAnalytics.HandleAction(application, identifier, LocalNotification, completionHandler); }
-
handleOpenURL
:If your application support iOS version less than 9.0.
Forwarding this method the SDK will be able to present alerts about the current user status if the URL is related to this SDK.
public override bool OpenUrl(UIApplication app, NSUrl url) { return FollowAnalytics.OpenUrl(app, url); }
-
openURLSourceApplication
:If your application support iOS version less than 9.0.
Forwarding this method the SDK will be able to present alerts about the current user status if the URL is related to this SDK.
public override bool OpenUrl(UIApplication app, NSUrl url, string sourceApplication, NSObject annotation) { return FollowAnalytics.OpenUrl(app, url, sourceApplication, annotation); }
-
openURLOptions
:Forwarding this method the SDK will be able to present alerts about the current user status if the URL is related to this SDK.
public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options) { return FollowAnalytics.OpenUrl(app, url, options); }
-
didReceiveLocalNotification
:Forwarding this method the SDK will be able to handle In-App campaigns.
public override void ReceivedLocalNotification(UIApplication application, UILocalNotification notification) { FollowAnalytics.ReceivedLocalNotification(application, notification); }
-
performFetchWithCompletionHandler
:Forwarding this method the SDK will be able to close sessions and fetch contents.
public override void PerformFetch(UIApplication application, Action<UIBackgroundFetchResult> completionHandler) { FollowAnalytics.PerformFetch(application, completionHandler); }
-
didReceiveRemoteNotificationFetchCompletionHandler
:Forwarding this method the SDK will be able to synchronize campaigns, handle the badge icon and detect campaign triggers.
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler) { FollowAnalytics.ReceivedRemoteNotification(application, userInfo, completionHandler); }
-
handleEventsForBackgroundURLSession
:Forwarding this method the SDK will be able to synchronize campaigns, handle the badge icon and detect campaign triggers.
public override void HandleEventsForBackgroundUrl(UIApplication application, string sessionIdentifier, Action completionHandler) { FollowAnalytics.HandleEventsForBackgroundUrl(application, sessionIdentifier, completionHandler); }
The required UNUserNotificationCenterDelegate
methods are:
-
didReceiveNotificationResponse
:Forwarding this method the SDK will be able to handle Push Notifications and In-App campaigns.
public void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler) { FollowAnalytics.DidReceiveNotificationResponse(center, response, completionHandler); }
-
willPresentNotification
:Forwarding this method the SDK will be able to handle Push Notifications and In-App campaigns.
public void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler) { FollowAnalytics.WillPresentNotification(center, notification, completionHandler); }
Configuration
To customize the SDK behavior, you must define your desired SDK parameters by setting the related properties values on the FollowAnalyticsConfiguration
object passed to the SDK initialization method:
Common
Parameter | Type | Default Value | Description |
---|---|---|---|
apiKey |
string | - | Your app api key. You can find it on the FollowAnalytics platform in the Administration section. |
isVerbose |
boolean | false | true to see internal logs made by the SDK in the console. Note that setting isVerbose to true will automatically set apiMode to .dev . So make sure to isVerbose to false for production build. More information in the Analytics section. |
apiMode |
enum | FollowAnalytics.APIMode.Prod | Value can be FollowAnalytics.APIMode.Prod or FollowAnalytics.APIMode.Dev . In Dev apiMode, logs, attributes and crashes sent by the SDK will be ignored by the platform, but you still can see them in the Device Observer. More information in the Analytics section. |
optInAnalyticsDefault |
boolean | true | true to make the user opt-in analytics by default. More information in the Opt-Out Analytics section. |
optInNotificationsDefault |
boolean | true | true to make the user opt-in notifications by default. More information in the Opt-in Notifications section. |
archivePushMessages |
boolean | false | true to archive Push campaigns messages. More information in the Archiving messages section. |
archiveInAppMessages |
boolean | false | true to archive In-App campaigns messages. More information in the Archiving messages section. |
maxBackgroundTimeWithinSession |
int | 120 | To determine the lifetime of a session when in background (between 15 and 3600). |
onNotificationReceived |
callback | - | Called when device receives a message from a Push campaign that contains custom parameters (i.e. at least one key/value pair). |
iOS
Parameter | Type | Default Value | Description |
---|---|---|---|
appGroup |
string | - | An app group identifier to link the extension target to the app. |
crashReportingEnabled |
boolean | true | true to enable FollowAnalytics crash reporting. |
onNotificationTapped |
callback | - | Called when user taps on a notification. |
onNativeInAppButtonTapped |
callback | - | Called when user taps on a custom button of a Native Alert InApp campaign. |
shouldOpenUrl |
callback | true | Called when user taps on a notification or in-app containign url, true for the SDK to open URLs automatically when user taps a Push campaign notification or a Native Alert custom button. More information in the Handling Links section. |
Updating from older versions
Updating from 6.5 to 6.6
Android
- Now there is no more need to implement a class derived from
FirebaseInstanceIdService
. You have to delete this class and implement theOnNewToken
method of your FirebaseMessagingService derived class. More details in the Setting up push notifications section.