Configure the Tealeaf iOS SDK

Modify your application to capture controls, events, and screen views. You configure several items for your application, including how screen layouts are logged, Target page location, kill switch location, and whether gestures will be logged.

Before you begin

Install the Tealeaf SDK for iOS development in your app. For information, see Add the iOS SDK to your project

Implement auto-instrumentation

By default, the iOS SDK automatically instruments your application for a set of predefined events. You can disable auto-instrumentation and then apply custom instrumentation for elements in your application. Auto-instrumentation is set with the DisableAutoInstrumentation field. You should leave this setting as YES.

If you choose to use custom instrumentation, see Custom instrumentation for more information.

Configure Tealeaf for your application

All of the configuration in this task involves modifying settings in the TealeafBasicConfig.plist file in the Acoustic Tealeaf Resources folder that you added to your Xcode project.

  1. In your project in Xcode, open the TealeafBasicConfig.plistfile.
  2. Set the GetImageDataOnScreenLayout to NO to log MD5 checksum and png or jpg images. This option creates smaller payloads in production and is the recommended setting.

📘

Note:

You can set GetImageDataOnScreenLayout to YES to capture base 64 data.

  1. Set the PostMessageUrl to the URL of the Target page for your app.

📘

Note

All events that are captured are sent in JSON format to a Target page. The Target page acknowledges the receipt of the JSON message and forwards the client-side events to Acoustic Tealeaf.

  1. Set the KillSwitchUrl to the URL for the kill switch for your app.

📘

Note:

The Kill Switch is used to control logging. When the kill switch is enabled, it must have a URL to check before the framework initializes. When the page is reachable, the framework initializes. If the page is not reachable, because of network problems or because you disabled it on your server, the framework does not initialize.

  1. Save and exit the TealeafBasicConfig.plist file.

Capture gestures

You can capture gestures that the user makes on your application. Gesture capture is set with the SetGestureDetector field. Gestures are logged as Type 11 JSON messages.

For information about the types of Gesture events captured, see Capture gestures. To configure gestures for your application:

  1. Modify the TealeafBasicConfig.plist file and set the SetGestureDetector field to YES to log gestures.
  2. If you are using your own gestures, modify the delegate for your Gesture Recognizer to work with Acoustic Tealeaf Capture. See Modify the Gesture Recognizer.

📘

Note:

You only need to do this if you are using your own gestures in your application. If you are using the Acoustic Tealeaf gestures, you do not need to do this.

Modify the Gesture Recognizer

If you have your own gestures recognizer in your application, the code might affect the Acoustic Tealeaf gesture capture feature. To ensure that your gestures and Acoustic Tealeaf capture work together, you add a method to the delegate for your Gesture Recognizer.

📘

Note:

Do this task only if you use your own gesture recognizer.

  1. Locate the delegate for your Gesture Recognizer.

  2. Add this method to the delegate:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
    shouldRecognizeSimultaneouslyWithGestureRecognizer:
        (UIGestureRecognizer *)otherGestureRecognizer

{
  return YES;
}
  1. Enable geolocation capture.

Modify the TealeafBasicConfig.plist file to enable geolocation capture for your application.

All of the configuration in this task involves modifying settings in the TealeafBasicConfig.plist file in the Acoustic Tealeaf Resources folder that you added to your Xcode project.

It is up to you to prompt the user for permission to collect geolocation information for your application according to Apple guidelines.

  1. In your project in Xcode, open the TealeafBasicConfig.plist file.
  2. Set the LogLocationEnabled field to YES to log gestures.
  3. Save TealeafBasicConfig.plist.
  4. Edit the info.plist file that is used with your project and the following geolocation keys:
KeyValue (String)
NSLocationAlwaysUsageDescriptionEnter a description that explains why you want the user to allow the application to access the user location information.
NSLocationWhenInUseUsageDescriptionEnter a description that explains why you want the user to allow the application to access the user location information.

Chrome browser is deprecating the support for API getCurrentPosition() and watchPosition() on insecure origins (http url). To capture geolocation data, you must use secure origins.
By adding the geolocation keys, iOS prompts the user to allow geolocation tracking within the application.

  1. Save and exit the info.plist file.

📘

Note:

The Web SDK typically tracks geolocation information within the Web application. When geolocation is enabled in a hybrid mobile application, the geolocation tracking feature in the Web application should be disabled and the application should use the native SDK capture the geolocation information.

To disable geolocation capture in the Web application:

  1. Locate the Web SDK configuration. The configuration is typically at the end of the Web SDK file as part of the call to the TLT.init() API.
  2. Locate the geolocation configuration section in the replay module configuration object (modules.replay.geolocation).
  3. If the geolocation configuration section does not exist, the feature is disabled automatically. If the section exists, ensure that the enabled setting is set to false. The following example shows the geolocation section for the Web SDK with geolocation disabled.
geolocation: {
    enabled: false,
    triggers: [{
        event: "load"
    }]
},
  1. Remove the NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription geolocation keys from the info.plist file that is associated with your project.

Capture screen layouts

Screen logging for a native mobile application can be enabled by configuring the AutoLayout controller instead of adding custom code to enable screen logging in your application.

The Acoustic Tealeaf iOS SDK can use the settings that are defined in TealeafLayoutConfig.json to log type 10 screen layouts for screenviews of native mobile application sessions. The AutoLayout controller also enables the application to automatically continue logging type 10 screen layouts when it resumes to the foreground. You can replay a mobile app session as an HTML web session instead of viewing the mobile app session as a series of screen captures. TealeafLayoutConfig.json is packaged with TLFResources.bundle and is formatted as a JSON file.

Edit TealeafLayoutConfig.json to configure Autolayout to log screen layouts. For more information, see Auto layout.

The following snippet shows an example of the TealeafLayoutConfig.json file.

{
  "AutoLayout": {
      "GlobalScreenSettings":{
          "ScreenChange": true,
          "DisplayName": "",
          "CaptureLayoutDelay": 0,
          "ScreenShot": false,
          "NumberOfWebViews": 0,
          "CaptureUserEvents": true,
          "CaptureScreenVisits": true,
          "CaptureLayoutOn": 2,
          "CaptureScreenshotOn": 0
      },
      "PaymentViewController":{
          "ScreenChange": false,
          "DisplayName": "The Payment Screen",
          "CaptureLayoutDelay": 0,
          "ScreenShot": false,
          "NumberOfWebViews": 0,
          "CaptureUserEvents": false,
          "CaptureScreenVisits": true,
          "CaptureLayoutOn": 0,
          "CaptureScreenshotOn": 0
      }
  },
  "AppendMapIds": {
      "[w,9290],[v,0]": {
          "mid": "ASimpleUIView"
      },
      "tag2999999": {
          "mid": "giveAdditionalId1"
      },
      "idxPathValue": {
          "mid": "giveAdditionalId2"
      }
  }
}

Capture specific pages by pausing and resuming the library

There are two ways of pausing and resuming the library:

  • EditTealeafLayoutConfig.json. This is the preferred method.
  • Call TealeafLayoutConfig.json.

Option A: Editing TealeafLayoutConfig.json

By default, if you are missing the GlobalScreenSettings section, you have the following defaults, which capture all pages, events, and gestures, but no screenshots:

{
    "AutoLayout": {
        "GlobalScreenSettings":{
            "ScreenChange": true,
            "DisplayName": "",
            "CaptureLayoutDelay": 1,
            "ScreenShot": true,
            "NumberOfWebViews": 0,
            "CaptureUserEvents": true,
            "CaptureScreenVisits": false,
            "CaptureLayoutOn": 2,
            "CaptureScreenshotOn": 2,
            "Masking": {
                "HasMasking": true,
                "HasCustomMask": true,
                "Sensitive": {
                    "capitalCaseAlphabet": "X",
                    "number": "9",
                    "smallCaseAlphabet": "x",
                    "symbol": "#"
                },
                "MaskIdList": [
                ],
                "MaskValueList": [
                ]
            }
        },
        "ExampleMaskingPage":{
            "ScreenChange": false,
            "DisplayName": "",
            "CaptureLayoutDelay": 0,
            "ScreenShot": false,
            "NumberOfWebViews": 0,
            "CaptureUserEvents": false,
            "CaptureScreenVisits": false,
            "CaptureLayoutOn": 0,
            "CaptureScreenshotOn": 0,
            "Masking": {
                "HasMasking": true,
                "HasCustomMask": true,
                "Sensitive": {
                    "capitalCaseAlphabet": "X",
                    "number": "9",
                    "smallCaseAlphabet": "x",
                    "symbol": "#"
                },
                "MaskIdList": [
                    "^9[0-9][0-9][0-9]$",
                    "^\\[wvv,0\\],\\[dddv,0\\],\\[v,0\\],\\[v,0\\],\\[v,0\\],\\[b,0\\](.)*$"
                ],
                "MaskValueList": [
                    "^4[0-9]{12}(?:[0-9]{3})?$",
                    "^3[47][0-9]{13}$",
                    "^65[4-9][0-9]{13}|64[4-9][0-9]{13}|6011[0-9]{12}|(622(?:12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|9[01][0-9]|92[0-5])[0-9]{10})$",
                    "^(5[1-5][0-9]{14}|2(22[1-9][0-9]{12}|2[3-9][0-9]{13}|[3-6][0-9]{14}|7[0-1][0-9]{13}|720[0-9]{12}))$"
                ]
            }
        }
    },
    "AppendMapIds": {
        "[w,9290],[v,0]": {
            "mid": "ASimpleUIView"
        },
        "tag2999999": {
            "mid": "giveAdditionalId1"
        },
        "idxPathValue": {
            "mid": "giveAdditionalId2"
        }
    }
}

You use CaptureUserEvents to indicate that you want to pause the library and no longer capture information on a page. To pause the library, set CaptureUserEvents to false. To resume the library, set CaptureUserEvents to true. Remember that pausing the library pauses only capture of user events. If you do not want to capture screens at all, set ScreenChange to false. If you do not want to capture screen visits, set CaptureScreenVisits to false.

For example, to capture all data except for user events on "FirstViewController", which is the first page, enable the library to resume on "SecondViewController", which is the second page.

{
    "AutoLayout": {
        "GlobalScreenSettings":{
            "ScreenChange": true,
            "DisplayName": "",
            "CaptureLayoutDelay": 1,
            "ScreenShot": true,
            "NumberOfWebViews": 0,
            "CaptureUserEvents": true,
            "CaptureScreenVisits": false,
            "CaptureLayoutOn": 2,
            "CaptureScreenshotOn": 2,
            "Masking": {
                "HasMasking": true,
                "HasCustomMask": true,
                "Sensitive": {
                    "capitalCaseAlphabet": "X",
                    "number": "9",
                    "smallCaseAlphabet": "x",
                    "symbol": "#"
                },
                "MaskIdList": [
                ],
                "MaskValueList": [
                ]
            }
        },
        "ExampleMaskingPage":{
            "ScreenChange": false,
            "DisplayName": "",
            "CaptureLayoutDelay": 0,
            "ScreenShot": false,
            "NumberOfWebViews": 0,
            "CaptureUserEvents": false,
            "CaptureScreenVisits": false,
            "CaptureLayoutOn": 0,
            "CaptureScreenshotOn": 0,
            "Masking": {
                "HasMasking": true,
                "HasCustomMask": true,
                "Sensitive": {
                    "capitalCaseAlphabet": "X",
                    "number": "9",
                    "smallCaseAlphabet": "x",
                    "symbol": "#"
                },
                "MaskIdList": [
                    "^9[0-9][0-9][0-9]$",
                    "^\\[wvv,0\\],\\[dddv,0\\],\\[v,0\\],\\[v,0\\],\\[v,0\\],\\[b,0\\](.)*$"
                ],
                "MaskValueList": [
                    "^4[0-9]{12}(?:[0-9]{3})?$",
                    "^3[47][0-9]{13}$",
                    "^65[4-9][0-9]{13}|64[4-9][0-9]{13}|6011[0-9]{12}|(622(?:12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|9[01][0-9]|92[0-5])[0-9]{10})$",
                    "^(5[1-5][0-9]{14}|2(22[1-9][0-9]{12}|2[3-9][0-9]{13}|[3-6][0-9]{14}|7[0-1][0-9]{13}|720[0-9]{12}))$"
                ]
            }
        },
        "FirstViewController": {
            "ScreenChange": false,
            "DisplayName": "First Screen",
            "CaptureLayoutDelay": 0,
            "ScreenShot": false,
            "NumberOfWebViews": 0,
            "CaptureUserEvents": false,
            "CaptureScreenVisits": false,
            "CaptureLayoutOn": 0,
            "CaptureScreenshotOn": 0
       },
       "SecondViewController": {
            "ScreenChange": true,
            "DisplayName": "Second Screen",
            "CaptureLayoutDelay": 0,
            "ScreenShot": false,
            "NumberOfWebViews": 0,
            "CaptureUserEvents": true,
            "CaptureScreenVisits": true,
            "CaptureLayoutOn": 2,
            "CaptureScreenshotOn": 0
       }
    },
    "AppendMapIds": {
        "[w,9290],[v,0]": {
            "mid": "ASimpleUIView"
        },
        "tag2999999": {
            "mid": "giveAdditionalId1"
        },
        "idxPathValue": {
            "mid": "giveAdditionalId2"
        }
    }
}

Additionally, you can disable capture of all data except for specific pages, as shown in the following example.

{
    "AutoLayout": {
        "GlobalScreenSettings":{
            "ScreenChange": true,
            "DisplayName": "",
            "CaptureLayoutDelay": 1,
            "ScreenShot": true,
            "NumberOfWebViews": 0,
            "CaptureUserEvents": true,
            "CaptureScreenVisits": false,
            "CaptureLayoutOn": 2,
            "CaptureScreenshotOn": 2,
            "Masking": {
                "HasMasking": true,
                "HasCustomMask": true,
                "Sensitive": {
                    "capitalCaseAlphabet": "X",
                    "number": "9",
                    "smallCaseAlphabet": "x",
                    "symbol": "#"
                },
                "MaskIdList": [
                ],
                "MaskValueList": [
                ]
            }
        },
        "ExampleMaskingPage":{
            "ScreenChange": false,
            "DisplayName": "",
            "CaptureLayoutDelay": 0,
            "ScreenShot": false,
            "NumberOfWebViews": 0,
            "CaptureUserEvents": false,
            "CaptureScreenVisits": false,
            "CaptureLayoutOn": 0,
            "CaptureScreenshotOn": 0,
            "Masking": {
                "HasMasking": true,
                "HasCustomMask": true,
                "Sensitive": {
                    "capitalCaseAlphabet": "X",
                    "number": "9",
                    "smallCaseAlphabet": "x",
                    "symbol": "#"
                },
                "MaskIdList": [
                    "^9[0-9][0-9][0-9]$",
                    "^\\[wvv,0\\],\\[dddv,0\\],\\[v,0\\],\\[v,0\\],\\[v,0\\],\\[b,0\\](.)*$"
                ],
                "MaskValueList": [
                    "^4[0-9]{12}(?:[0-9]{3})?$",
                    "^3[47][0-9]{13}$",
                    "^65[4-9][0-9]{13}|64[4-9][0-9]{13}|6011[0-9]{12}|(622(?:12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|9[01][0-9]|92[0-5])[0-9]{10})$",
                    "^(5[1-5][0-9]{14}|2(22[1-9][0-9]{12}|2[3-9][0-9]{13}|[3-6][0-9]{14}|7[0-1][0-9]{13}|720[0-9]{12}))$"
                ]
            }
        },
        "FirstViewController": {
            "ScreenChange": false,
            "DisplayName": "First Screen",
            "CaptureLayoutDelay": 0,
            "ScreenShot": false,
            "NumberOfWebViews": 0,
            "CaptureUserEvents": false,
            "CaptureScreenVisits": false,
            "CaptureLayoutOn": 0,
            "CaptureScreenshotOn": 0
       },
       "SecondViewController": {
            "ScreenChange": true,
            "DisplayName": "Second Screen",
            "CaptureLayoutDelay": 0,
            "ScreenShot": false,
            "NumberOfWebViews": 0,
            "CaptureUserEvents": true,
            "CaptureScreenVisits": true,
            "CaptureLayoutOn": 2,
            "CaptureScreenshotOn": 0
       }
    },
    "AppendMapIds": {
        "[w,9290],[v,0]": {
            "mid": "ASimpleUIView"
        },
        "tag2999999": {
            "mid": "giveAdditionalId1"
        },
        "idxPathValue": {
            "mid": "giveAdditionalId2"
        }
    }
}

For more information about configuring properties in TealeafLayoutConfig.json for pausing and resuming the library, see Table 1.

Option B: Calling TealeafLayoutConfig.json programmatically

Use IBMGlobalScreenSettings to set values for all view controllers in TealeafLayoutConfig.json that are not documented. If you want to call TealeafLayoutConfig.json programmatically, go to the page where you want to start pausing the library on viewWillAppear. viewWillAppear is always called when view controller is displayed.

📘

Note:

viewDidLoad is called only the first time it is created.

- (void)viewWillAppear:(BOOL)animated {
  [[TLFApplicationHelper sharedInstance] pauseTealeaf];
  [super viewWillAppear:animated];
}

Next, go to the page where you want to start resuming the library on viewWillAppear.

- (void)viewWillAppear:(BOOL)animated {
  [[TLFApplicationHelper sharedInstance] resumeTealeaf];
  [super viewWillAppear:animated];
}

Configure exception logging

Exceptions are the way that a system or framework communicates to the application that something has gone wrong and not to continue with the execution of the program unless the exception is one of the expected ones. You can manually and automatically log caught exceptions using the Acoustic Tealeaf SDKs so that the exception information can be used for analytics.

Ways to log exceptions

In the Tealeaf SDK there are three ways to log exceptions that are trapped by your application exception handler. These methods do not use the Cocoa SDK, which is not exception-safe. This table lists the methods used to log exceptions and the parameters used in each method:

MethodParameters

- (BOOL)logNSExceptionEvent:(NSException *)exception;

Where:

  • @param exception - The caught NSException instance.
  • @return if the event was successfully logged or not.

- (BOOL)logNSExceptionEvent:(NSException
You set the NSSetUncaughtExceptionHandler of your AppDelegate.m inside of: - (BOOL)application:(UIApplication

Where:

  • @param exception - The caught NSException instance.
  • @param dataDictionary - Additional data about the exception.
  • @return if the event was successfully logged or not.

- (BOOL)logNSExceptionEvent:(NSException

Where:

  • @param exception - The caught NSException instance.
  • @param dataDictionary - Additional data about the exception.
  • @param unhandled - Indicates whether the exception was caught by an exception handler or not.
  • @return if the event was successfully logged or not.

In this example, we have a method that causes an exception:

- (void)aMethod {
  [self causesAnException];
}

You add an @try
  , @catch,
      and the [[TLFCustomEvent sharedInstance] logNSExceptionEvent:exception];
method to handle the exception :

    -(void)aMethod {
  @try {
    [self causesAnException];

  }

  @catch (NSException *exception) {
    [[TLFCustomEvent sharedInstance] logNSExceptionEvent:exception];
  }
}

You can log uncaught exceptions by setting up and adding an NSUncaughtExceptionHandler.

Logging exceptions

Use the examples in this task as a guide to adding exception logging to your application. You might want to use the top-level NSSetUncaughtExceptionHandler(&SampleAutoUncaughtExceptionHandler);to identify bugs in your application.

The current iOS SDK catches some exceptions and prevents them from being logged to the target page. In some cases this may prevent an application from catching the exception.

  1. Determine the method for which you want to log exceptions. For example, you have a method:
- (void)aMethod {
  [self causesAnException];
}
  1. Optional: Add the exception method that you want to use to the method for which you want to Add @try , @catch, and the [[TLFCustomEvent sharedInstance] logNSExceptionEvent:exception]; method to handle the exception:
- (void)aMethod {
  @try {
    [self causesAnException];

  }

  @catch (NSException *exception) {
    [[TLFCustomEvent sharedInstance] logNSExceptionEvent:exception];
  }
}
  1. Optional: Set up an NSUncaughtExceptionHandler for logging for uncaught exceptions. The application library needs the application to set NSUncaughtExceptionHandler. The application library saves the reference to the application's NSUncaughtExceptionHandler; then, sets its own NSUncaughtExceptionHandler, which is called after the application library reporting exception.

For example:

- (void)MyAppsUncaughtExceptionHandler(NSException *exception)

{
  NSLog(@"My Application Uncaught Exception Handler");
}

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  // Override point for customization after application launch.

  NSSetUncaughtExceptionHandler(&MyAppsUncaughtExceptionHandler);

  [[TLFApplicationHelper sharedInstance] enableTealeafFramework];

  return YES;
}

Instrument the Tealeaf SDK with a Cordova mobile application

More configuration is needed to instrument the Acoustic Tealeaf iOS SDK with mobile applications that are created using Cordova.

Logging can experience issues due to delays with screen loading in Cordova-based applications. The TealeafAdvancedConfig.json configuration file contains the property IsCordovaApp and CordovaLayoutDelay, which delays logging for Cordova-based applications when it is enabled. IsCordovaApp is a Boolean property and can be set to true or false. The amount of time for the delay is stored in the CordovaLayoutDelay property. CordovaLayoutDelay is a numeric property and is configured for milliseconds.

TealeafAdvancedConfig.json is included with TLFResources.bundle in the assets folder.

The following table describes the Acoustic Tealeaf SDK instrumentation properties that must be configured to log user interaction with a mobile application that is created in Cordova.

Instrumentation propertyDescription
IsCordovaAppTo enable the logging delay for a Cordova application, edit TealeafAdvancedConfig.json and set IsCordovaApp to true.
Example: "IsCordovaApp": trueTo disable the logging delay for a Cordova application, edit TealeafAdvancedConfig.json and set IsCordovaApp to false. By default, IsCordovaApp is disabled.
Example: "IsCordovaApp": false
CordovaLayoutDelayWhen IsCordovaApp is enabled, you also need to set the logging delay by assigning a numeric value, in milliseconds, to CordovaLayoutDelay. The value is used to define the amount of time that must pass between when the screen loads and when Acoustic Tealeaf begins logging user interaction with the screen.
Example: "CordovaLayoutDelay": 750 sets the logging delay to 750 ms.

In addition to configuring the properties in TealeafAdvancedConfig.json, include the following project files to your Cordova application:

  • Tealeaf/CordovaDependencies/NSObject+TealeafEarlyLoads.h
  • Tealeaf/CordovaDependencies/NSObject+TealeafEarlyLoads.m

NSObject+TealeafEarlyLoads.h and NSObject+TealeafEarlyLoads.m are used to initialize the iOS SDK when the Cordova application loads.

Configure code injection

Tealeaf SDK injects into some Apple base classes, such as UIViewController, UITableViewController. These injections help Tealeaf SDK capture data automatically. You can disable code injection by following the instructions in this step.
The CordovaDependencies folder in the Tealeaf iOS SDK contains two files:

  • NSObject+TealeafEarlyLoads.m
  • NSObject+TealeafEarlyLoads.h

NSObject+TealeafEarlyLoads.m contains following methods:

  • +(void)tealeafEarlyLoadWebView;
  • +(void)tealeafDoNotInjectForUIViewController;
  • +(void)tealeafDoNotInjectForUITableView;
  • +(void)tealeafDoNotInjectForUITableViewCell;
  • +(void)tealeafDoNotInjectForUIImage;
  • +(void)tealeafDoNotInjectForUIAlertAction;
  • +(void)tealeafDoNotInjectForUIPageControl;
  • +(void)tealeafDoNotInjectForUIPickerView;
  • +(void)tealeafDoNotInjectForUIDatePicker;
  • +(void)tealeafDoNotInjectForNSData;
  • +(void)tealeafDoNotInjectForUIWebView;
  • +(void)tealeafDoNotInjectForWKWebView;

These methods are commented out in the NSObject+TealeafEarlyLoads.m file.

To disable code injecton in the above classes:

  1. Add the NSObject+TealeafEarlyLoads.m file into <Your Project Settings> >> <Your Target> >> Compile Sources.
  2. Open NSObject+TealeafEarlyLoads.m and uncomment the method for the class that you do not want Tealeaf to inject. For example, if you do not want Tealeaf to inject to NSData, uncomment the tealeafDoNotInjectForNSData method in NSObject+TealeafEarlyLoads.m.

The classes to which Tealeaf injects by default corresponds to the list of methods in the NSObject+TealeafEarlyLoads.m file.