Initial SDK setup

This document will cover app setup and the component installation process, as well as basic integration steps for iOS and Android.

For an example, check out our PhoneGap sample integration code on Github.

For more information, please read the iOS and Android FollowAnalytics SDK documentations.

Install the SDK

  1. Download the FollowAnalytics SDK from the developer portal.

  2. Use the cordova CLI to add the plugin to your app:

    cordova plugin add /path/to/fa-sdk-phonegap-plugin
    

Initialize with your API keys

Prepare your API keys

Be sure to have your API keys for this step of the configuration. If you are not sure where to find them, please reach out to your Customer Success Manager or message support@followanalytics.com

iOS

Android

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

Declare a URL Scheme in the info tab of your Xcode project using the bundleId of your app as URL Scheme:

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).

Android

Where %YOUR_APP_PACKAGE_NAME% should be replaced by the Android package name of your app.

Register for notifications

iOS

If your app code is already registered to send push notifications, nothing to do here. Otherwise, simply add a call to registerForPush, either from your HTML code, or in the native iOS code after the SDK initialization.

HTML

<a href="#" onclick="FAFollowApps.registerForPush()">register for push</a>

Objective-C

[FAFollowApps configureWithId:@"API_KEY_STRING" debugStateOn:FADEBUG options:launchOptions];
[FAFollowApps registerForPush];

Android

Build in release mode

The app must be built on release mode in order to receive push notifications

The FollowAnalytics SDK supports push notifications based on Google Cloud Messaging.

  1. Add the following permissions to your manifest:

    <permission android:name="%YOUR_APP_PACKAGE_NAME%.permission.C2D_MESSAGE"
                    android:protectionLevel="signature" />
     <uses-permission android:name="%YOUR_APP_PACKAGE_NAME%.permission.C2D_MESSAGE" />
    
  2. Add the GCM Receiver to your manifest

    <receiver
            android:name="com.google.android.gms.gcm.GcmReceiver"
            android:exported="true"
            android:permission="com.google.android.c2dm.permission.SEND"
            >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE"/>
            <!-- for Gingerbread GSF backward compat -->
            <action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
            <category android:name="%YOUR_APP_PACKAGE_NAME%"/>
        </intent-filter>
     </receiver>
    
  3. In your Application subclass, ensure you've added the registerGCM() call

    public class MyAwesomeApplication extends Application {
          [...]
          @Override
          public void onCreate() {
              super.onCreate();
              FollowApps.init(this);
              FollowApps.registerGcm();
              [...]
          }
          [...]
    }
    

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

The SDK allows you to log events happening in your code. These are the two methods you can call on the SDK:

<a href="#" onclick="FAFollowApps.logEvent('My event', 'My event details')">Log an event</a>
<a href="#" onclick="FAFollowApps.logError('My error', 'My error details')">Log an error</a>

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 way:

FAFollowApps.logEvent('Product view', Product reference);

FAFollowApps.logEvent('Add product to cart', {'product_id': 'ABCD123',
                                              'product_category': 'Jeans'});

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:

FAFollowApps.setUserId("user_id@email.com");

If you want to remove the user identifier (in case of a sign out for instance) use the following method:

FAFollowApps.unsetUserID();

Predefined attributes

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

For predefined attributes, the SDK has the following properties:

FAFollowApps.setUserFirstName("Peter");
FAFollowApps.setUserLastName("Jackson");
FAFollowApps.setUserCity("San Francisco");
FAFollowApps.setUserRegion("California");
FAFollowApps.setUserCountry("USA");
FAFollowApps.setUserGender(FollowAnalytics.Gender.Male);
FAFollowApps.setUserEmail("mail@mail.com");
FAFollowApps.setUserBirthDate("2001-02-22");
FAFollowApps.setUserProfilePicture("https://picture/picture");

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

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:

FAFollowApps.setNumberAttribute('key', "1");
FAFollowApps.setStringAttribute('key', "A custom string attribute");
FAFollowApps.setBooleanAttribute('key', "true");
FAFollowApps.setDateAttribute('key', "2016-10-26");
FAFollowApps.setDateTimeAttribute('key', "2016-10-26T11:22:33+01:00");

For example, to set the user's job:

FAFollowApps.setStringAttribute("job", "Taxi driver");
Delete a custom attribute value

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

FollowApps.deleteUserAttribute("job");
Set of Attributes

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

To add an item:

FAFollowApps.addToUserAttributeSet("fruits", "apple");
FAFollowApps.addToUserAttributeSet("fruits", "banana");

To remove an item:

FAFollowApps.removeFromUserAttributeSet("fruits", "apple");

And to clear a set:

FAFollowApps.emptyUserAttributeSet("fruits");

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.

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.

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.).

iOS: Incoming notification

In order to be able to receive the custom parameters sent within a Push Notification or an In App message payload, you'll need to implement the followAppsShouldHandleParameters:actionIdentifier:actionTitle:completionHandler:method. Inside your javascript files you'll have to implement a method that will be called from this Objective-C method. If you implement, or instance, a method called doAmazingThings() as follows:

function doAmazingThings(args) {
    console.log(args);
    var currentdate = new Date();
    var datetime = "Last Sync: " + currentdate.getDate() + "/"
    + (currentdate.getMonth()+1)  + "/"
    + currentdate.getFullYear() + " @ "
    + currentdate.getHours() + ":"
    + currentdate.getMinutes() + ":"
    + currentdate.getSeconds();
    document.getElementById('some_element').innerHTML = (datetime);
    console.log('done');
}

You'll be able to call the doAmazingThings() method using the following Objective-C code:

- (void)followAppsShouldHandleParameters:(NSDictionary *)openingParameters
                        actionIdentifier:(NSString *)actionIdentifier
                             actionTitle:(NSString *)actionTitle
                       completionHandler:(void (^)())completionHandler
{
    if (actionIdentifier)
    {
      // here you'll have the identifier for custom push notification actions
    }
    if (completionHandler != nil) {
      // always call the completionHandler, if any
        completionHandler();
    }
    NSData *data = [NSJSONSerialization dataWithJSONObject:openingParameters
                                                   options:NSJSONWritingPrettyPrinted
                                                     error:nil];
    NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSString *functionCall = [NSString stringWithFormat:@"doAmazingThings(%@)", jsonString];
    [YOUR_WEBVIEW_INSTANCE stringByEvaluatingJavaScriptFromString:functionCall];
}
iOS: Last notification

Some applications might not be able to receive the notification custom parameters. Although unlikely, you can call lastPushCampaignParams form the native code to get the latest JSON containing the custom parameters passed by the Notification.

If you need to fetch this data from your javascript, use FALastPushMessageContent, in response to the deviceready event from Cordova/PhoneGap.

Please note that this is a one shot call, as a second call to this method will return an empty JSON.

Android: Default behavior

By default, when the user clicks on a Push notification shown by the FollowAnalytics SDK, an Intent starting a new instance of your main activity is launched. You can retreive any custom parameter in the Java code by adding the following lines in your onCreate method.

@Override
protected void onCreate(Bundle savedInstanceState) {
    Bundle extras = getIntent().getExtras();
    if (extras != null) {
        String value1 = extras.getString("a_custom_param_key");
        String value2 = extras.getString("another_key");
        // or retrieve all the pairs
        for (String key : extras.keySet()) {
            Object value = extras.get(key);
              // …
          }

        // Do what you want with the custom values
      }
}
Android: Handle deeplinking from Java

If you want more control, you can implement in your Java code the MessageHandler interface, and declare it in your application class, like in the following example.

public class MyAwesomePushMessageHandler implements MessageHandler {

    @Override
    public void onPushMessageClicked(Context context, Map<String, String> data) {
        String value1 = data.get("a_custom_param_key");
        String value2 = data.get("another_key");

        // Silently do stuff ...
        // .. or start an activity

        Intent intent = new Intent(context, SpecificActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }

    @Override
    public void onInAppMessageClicked(Context context, String buttonText, Map<String, String> data) {
        // Same as the above method, but from a in-app message !
    }
}

If you define a custom MessageHandler, you must declare it in your Application, after the FollowApps.init(this) line:

FollowApps.setMessageHandler(new MyAwesomePushMessageHandler());
Android: Handle deeplinking from javascript

To handle the deeplinking from your javascript code, have this run when the device is ready:

    onDeviceReady: function() {
            ...
            window.FAFollowApps = cordova.require("com/cordova/followapps/plugin");
            FAFollowApps.handleDeeplink();
            FAFollowApps.on("onPushMessageClicked",function(data){
                      console.log(JSON.stringify(data));

            });
             FAFollowApps.on("onPushDeeplinkingClicked",function(data){
                      console.log(JSON.stringify(data));

                            });
             FAFollowApps.on("onInAppMessageClicked",function(data){
                      console.log(JSON.stringify(data));

               });

              ....
    },

As you can notice here, the plugin provides the following events : onPushMessageClicked , onPushDeeplinkingClicked and onInAppMessageClicked.

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.

iOS

For campaigns where the content is not handled by FollowAnalytics, implement the following FAFollowAppsDelegate method in your AppDelegate:

- (void)followAppsShouldHandleWebViewUrl:(NSURL *)url withTitle:(NSString *)webviewTitle;
Android

For campaigns where the content is not handled by FollowAnalytics, you will need to extend com.followapps.android.CustomRichCampaignBaseReceiver and declare it in your AndroidManifest.xml. You'll need to use an intent-filter on BROADCAST_RICH_CAMPAIGNS_ACTION. For instance:

<receiver android:name=".RichCampaignDataReceiver" >
    <intent-filter>
        <action android:name="%YOUR_APP_PACKAGE_NAME%.BROADCAST_RICH_CAMPAIGNS_ACTION" />
    </intent-filter>
</receiver>

Where %YOUR_APP_PACKAGE_NAME% is your application package name.

The method onRichCampaignDataReceived must be overridden. Rich campaign parameters are provided as method arguments:

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:

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 when a view appears, and the resume one when it disappears.

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 is initialized, and then resuming where the messages can be shown. Just pause again when the user leaves that "safe" area of your app.

Opening an external webview

The plugin allows you to launch a native web view with a given url and be able to performs logs from that external resource. In order to do so, if you want to open url https://s3-eu-west-1.amazonaws.com/fa-sdk-files/index.html in a native web view launched from your html code, call the following method from your PhoneGap HTML:

FAFollowApps.openWebView(URL, TITLE, CLOSE_BUTTON_TEXT);

Somethign like:

<a href="#" onclick="FAFollowApps.openWebView('https://s3-eu-west-1.amazonaws.com/fa-sdk-files/index.html', 'Test Log', 'Close'); return false;">Open WebView with title</a>

The URL argument will contain the url of the page to display (required), the TITLE argument will be shown as the title for the NavigationBar (optional, iOS only), and the CLOSE_BUTTON_TEXT will contain the text for the close button (optional, iOS only, defaults to “close”).

Please check the html at https://s3-eu-west-1.amazonaws.com/fa-sdk-files/index.html to see how to tag your external pages.

Current available methods are:

NOTE: if you're tagging from a link and the link has a real href set, the sdk will handle that for you, performing the onclick action and redirecting you right after.

Migration and troubleshooting

Migration to 4.1.0

Since version 4.1.0, the FollowAnalytics plugin is updated to respect cordova plugin standard.

So to call a method, you have to init FAFollowApps instance and call the method on it. However, you can always continue to use the deprecated methods.

All methods have been renamed. For example :

FALogEvent('My event', 'My event details')

became

FAFollowApps.logEvent('My event', 'My event details')

Troubleshooting

If you eventually run into an error like:

Refused to execute inline event handler because it violates the following Content Security Policy directive: "default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'". Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.

Be sure to replace the line

<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">

on your index.html by

<meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'" >

This will enable the logging of events. 0