Blue Triangle Help Center
Auto Light Dark
Auto Light Dark

Blue Triangle SDK for iOS Installation Guide

Introduction

The Blue Triangle SDK for iOS enables application owners to track their users’ experience so they can focus on user experience issues that impact their business outcomes.

PLEASE read through the mandatory instrumentation instructions to ensure that 

  • Mobile native views are reported for views and performance

  • User sessions are properly stitched between mobile native views and webviews

  • Network details are reported (detailed backend interaction, errors etc.)

  • Checkout events are reported

Instrumenting Your App with the Blue Triangle SDK

iOS SDK Default Values

Feature

Required (For installation),
Recommended,
Optional

Configuration property name

Default Value

Notes

Site ID

Required (Set parameter)

siteID

 

This will ensure data from the SDK is sent to the correct account in Blue Triangle

Native View Tracking

Required (Add Code)

enableScreenTracking

TRUE

This will enable automatic mobile view tracking.

Webview Capture

Required (Add Code)

webView(_:didCommit:)

TRUE

This will enable session stitching

Network Capture

Required (Add Code, change setting for debugging)

networkSampleRate

0.05 (5%)
Min = 0.0 (Disabled)
Max = 1.0 (100%)

This sample rate defines the percentage of user sessions for which network calls will be captured. A value of 0.05 = 5%, 0.0 = no tracking, and 1.0 means that all  network requests will be captured for any user sessions. It is recommended to set to 1.0 (100%) when installing or debugging the SDK.

Campaign Configuration Parameters

Recommended

abTestID

 

These fields can be used to identify and segment users for optimized analytics contextualization. They can be set in advance and changed in real time.

campaignMedium

campaignName

campaignSource

dataCenter

trafficSegmentName

Offline Caching

Optional, changes to default values are not recommended

cacheMemoryLimit

30 Mb
Min = 0Mb
Max = 100MB

The amount of memory the cache uses (in bytes) to store Blue Triangle data when the device is offline

cacheExpiryDuration

48 Hours
Min = 0 Hours
Max = 120 Hours

The amount of time (in milliseconds) the data is kept in the cache before it expires

Memory Warning

Optional, changes to default values are not recommended

enableMemoryWarning

TRUE

This will enable memory warnings

Performance Monitoring CPU and Memory

Optional, changes to default values are not recommended

isPerformanceMonitorEnabled

TRUE

This will enable or disable CPU and Memory performance metrics

performanceMonitorSampleRate

1000ms

Set the sampling interval for performance monitoring in milliseconds

ANR Detection

Optional, changes to default values are not recommended

ANRMonitoring

TRUE

This will enable ANR tracking

ANRWarningTimeInterval

5 seconds
Min = 3s
Max = 10s

Use this configuration property to configure the interval duration that qualifies as an ANR state

Track Crashes

Optional, changes to default values are not recommended

crashTracking

TRUE

*see note

Set this property to TRUE to enable crash tracking; leave FALSE on iOS if another crash tracking tool is in use

Network State Capture

Optional, changes to default values are not recommended

enableTrackingNetworkState

TRUE

Network interfaces include wifi, ethernet, cellular, etc. This enables Netowkr state, (associated with all Timers, Errors, and Network Requests captured by the SDK)

Application Hot/Cold Launch Time

Optional, changes to default values are not recommended

enableLaunchTime

TRUE

Report on the application hot/cold launch time

Mandatory Installation Steps

SDK Installation

To download the latest iOS SDK, please visit https://github.com/blue-triangle-tech/btt-swift-sdk

Installation using Swift Packages Manager

To integrate Blue Triangle using Swift Packages Manager into your iOS project, follow these steps:

Xcode 11-12:

Installation using CocoaPods

To integrate BlueTriangle using CocoaPods into your iOS project, you need to follow these steps:

  • Open 'Podfile' in text mode and add the following:

pod 'BlueTriangleSDK-Swift'    

  •  Save the Podfile and run the following command in the terminal to install the dependencies:

pod install    

Site ID Configuration

In order to use Blue Triangle, the Site ID needs to be configured in the SDK.

Find your site ID by:

  • Login to https://portal.bluetriangletech.com 

  • Click on "Settings" icon

  • Open the Sites page under the Settings Modal. (Logged in user needs to have access to Sites page)

  • Get the value for Site ID from the "Tag Prefix" column for the desired "Site Name"

  • Replace <BTT_SITE_ID> with your site ID in the following areas:

    • It is recommended to do this in:

      • AppDelegate.application(_:didFinishLaunchingWithOptions:)

               OR

    • SceneDelegate.scene(_ scene:, willConnectTo session:, options,connectionOptions:) 

               method:

BlueTriangle.configure { config in
    config.siteID = "<MY_SITE_ID>"
}

If you are using SwiftUI, add an init() constructor in your App struct and add configuration code there as shown below:

import BlueTriangle
import SwiftUI

@main
struct YourApp: App {
    init() {
          //Configure BlueTriagle with your siteID
          BlueTriangle.configure { config in
               config.siteID = "<MY_SITE_ID>"
           }
           //...
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Native View Automated Performance Tracking

All UIKit UIViewControllers view counts will be tracked automatically. You can see each view controller name with their count on our dashboard.

SwiftUI views are not captured automatically. You need to call bttTrackScreen() modifier on each view that you want to track. The below example shows the usage of "bttTrackScreen(_ screenName: String)" to track the "About Us" screen.

struct ContentView: View {
    var body: some View {
        VStack{
            Text("Hello, world!")
        }
        .bttTrackScreen("Demo_Screen")
    }
}
Disabling native view tracking

To disable mobile view tracking, you need to set the enableScreenTracking configuration to false during configuration like below, This will ignore UIViewControllers activities and bttTrackScreen() modifier calls.

 BlueTriangle.configure { config in
         ...
         config.enableScreenTracking = false
 }

To disable a named view

BlueTriangle.configure { config in
        ...
        config.ignoreViewControllers = ["UIViewController"]
}

Native View/WebView Tracking/Session Stitching

Websites shown in webview that are tracked by BlueTriangle can be tracked in the same session as the native app. To achieve this, follow the steps below to configure the WebView:

Implement WKNavigationDelegate protocol and call BTTWebViewTracker.webView(webView, didCommit: navigation) in 'webView(_:didCommit:)' delegate method as follows.

  import BlueTriangle

  //....

 extension YourWebViewController: WKNavigationDelegate{

  //....

  func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {

      //....

      //Call BlueTringles 'webView(_:didCommit:)' method
      BTTWebViewTracker.webView(webView, didCommit: navigation)
    }

 }

For more clarity, here is a Webview with UIViewController full example:

import UIKit
import WebKit
//Need to import BlueTriangle
import BlueTriangle

class YourWebViewController: UIViewController {
  @IBOutlet weak var webView: WKWebView!

  override func viewDidLoad() {
      super.viewDidLoad()

      //Set navigationDelegate
      webView.navigationDelegate = self

      //Load Url
      if let htmlURL = URL(string: "https://example.com"){
          webView.load(URLRequest(url: htmlURL))
      }
  }
}

//Implement Navigation Delagate
extension YourWebViewController: WKNavigationDelegate {

  func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {

      //...

      //Call BlueTringles 'webView(_:didCommit:)' method
      BTTWebViewTracker.webView(webView, didCommit: navigation)
  }
}

Webview with SwiftUI full example:

import SwiftUI
import WebKit
//Need to import BlueTriangle
import BlueTriangle

struct YourWebView: UIViewRepresentable {

  private let webView = WKWebView()

  func makeCoordinator() -> YourWebView.Coordinator {
      Coordinator()
  }

  func makeUIView(context: Context) -> some UIView {

      //Set navigationDelegate
      webView.navigationDelegate = context.coordinator

      //Load Url
      if let htmlURL = URL(string: "https://example.com"){
          webView.load(URLRequest(url: htmlURL))
      }
      return webView
  }
}

extension YourWebView {

  //Implement Navigation Delagate  Coordinator

  class Coordinator: NSObject, WKNavigationDelegate {

      func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {

          //...

          //Call BlueTringles 'webView(_:didCommit:)' method
          BTTWebViewTracker.webView(webView, didCommit: navigation)
      }
  }
} 

Network Capture

The Blue Triangle SDK supports capturing network requests using either the bt-prefixed URLSession methods or the NetworkCaptureSessionDelegate.

Network requests using a URLSession with a NetworkCaptureSessionDelegate or made with one of the bt-prefixed URLSession methods will be associated with the last main timer to have been started at the time a request completes. Note that requests are only captured after at least one main timer has been started and they are not associated with a timer until the request ends.

NetworkCaptureSessionDelegate

You can use NetworkCaptureSessionDelegate or a subclass as your URLSession delegate to gather information about network requests when network capture is enabled:

let session = URLSession(
    configuration: .default,
    delegate: NetworkCaptureSessionDelegate(),
    delegateQueue: nil)

let timer = BlueTriangle.startTimer(page: Page(pageName: "MY_PAGE"))
...
let (data, response) = try await session.data(from: URL(string: "https://example.com")!)

If you have already implemented and set URLSessionDelegate to URLSession, you can call NetworkCaptureSessionDelegate objects urlSession(session: task: didFinishCollecting:) method:

func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {

     //Your code ...

    let sessionDelegate = NetworkCaptureSessionDelegate()
    sessionDelegate.urlSession(session, task: task, didFinishCollecting: metrics)
}
URLSession Methods

Alternatively, use bt-prefixed URLSession methods to capture network requests:

Standard

Network Capture

URLSession.dataTask(with:completionHandler:)

URLSession.btDataTask(with:completionHandler:)

URLSession.data(for:delegate:)

URLSession.btData(for:delegate:)

URLSession.dataTaskPublisher(for:)

URLSession.btDataTaskPublisher(for:)

Use these methods just as you would their standard counterparts:

let timer = BlueTriangle.startTimer(page: Page(pageName: "MY_PAGE"))
...
URLSession.shared.btDataTask(with: URL(string: "https://example.com")!) { data, response, error in
    // ...
}.resume()
Manual Network Capture

For other network capture requirements, captured requests can be manually created and submitted to the tracker.

If you have the URL, method, and requestBodyLength in the request, and httpStatusCode, responseBodyLength, and contentType in the response

let tracker = NetworkCaptureTracker.init(url: "https://example.com", method: "post", requestBodylength: 9130)
tracker.submit(200, responseBodyLength: 11120, contentType: "json")

If you have urlRequest in request and urlResponse in response

let tracker = NetworkCaptureTracker.init(request: urlRequest)
tracker.submit(urlResponse)

where urlRequest and urlResponse are of URLRequest and URLResponse types, respectively.

If you encounter an error during a network call

let tracker = NetworkCaptureTracker.init(url: "https://example.com", method: "post", requestBodylength: 9130)
tracker.failed(error)

        OR

let tracker = NetworkCaptureTracker.init(request: urlRequest)
tracker.failed(error)

Checkout Event Data

Upon a customer checkout, it is possible to configure the following data parameters for the event:

Brand Value

let timer = BlueTriangle.startTimer( page: Page( pageName: "SignUp", brandValue: 100.0)) 
BlueTriangle.endTimer(timer)

Cart Value, Order Number, Order Time, Cart Count, Cart Checkout Count

let timer = BlueTriangle.startTimer( 
        page: Page( 
                pageName: "Confirmation")) 
BlueTriangle.endTimer( 
        timer, 
        purchaseConfirmation: PurchaseConfirmation( 
                cartValue:99.0, 
                cartCount: 2,
                cartCountCheckout: 5, 
                orderNumber: "ORD-123345")) 

Network Capture Sample Rate

Network sample rate indicates the percentage of session network requests that are captured. For example a value of 0.05 means that network capture will be randomly enabled for 5% of user sessions. Network sample rate value should be between 0.0 to 1.0 representing fraction value of percent 0 to 100. The default networkSampleRate value is 0.05, i.e only 5% of sessions network request are captured.

To change network capture sample rate set value of the 'config.networkSampleRate' to 0.5 to set is to 50%.

BlueTriangle.configure { config in
    config.siteID = "<MY_SITE_ID>"
    config.networkSampleRate = 0.5
    ...
}

To disable network capture set 0.0 to 'config.networkSampleRate' during configuration.

It is recommended to have 100% sample rate while developing/debugging. By setting 'config.networkSampleRate' to 1.0 during configuration.

Blue Triangle Campaign Configuration Fields

The following fields can be used to identify and segment users for optimized analytics contextualization. They can be configured in the SDK and modified in the app in real time, and they show in the Blue Triangle portal as parameters for reporting.

abTestID="MY_AB_TEST_ID"

Capture a variable that allows us to understand a live AB test of two variants in the app.

campaignMedium="MY_CAMPAIGN_MEDIUM"

Understand the general reason the journey started (email, paid search, organic search, etc)

campaignName="MY_CAMPAIGN_NAME"

Understand the campaign name that started the journey. 

campaignSource="MY_CAMPAIGN_SOURCE"

Understanding the type of marketing campaign. 

dataCenter="MY_DATA_CENTER"   

 

Understand if you have multiple data centers that serve your customers you can group data by them.

trafficSegmentName="MY_SEGMENT_NAME"

This can be used to segment environment type.  For instance, we can use this to understand if you have beta vs prod but both are live versions of the app.  

BlueTriangle.configure { config in
    config.abTestID = "MY_AB_TEST_ID"
    config.campaignMedium = "MY_CAMPAIGN_MEDIUM"
    config.campaignName = "MY_CAMPAIGN_NAME"
    config.campaignSource = "MY_CAMPAIGN_SOURCE"
    config.dataCenter = "MY_DATA_CANTER "
    config.trafficSegmentName = "MY_TRAFFIC_SEGEMENT_NAME"
} 

Custom Timers

While mobile Views are automatically tracked upon installation, Custom Timers can also be configured if needed.

NOTE: To enable application performance-oriented reporting, the timer duration is limited to 120 seconds.

To measure the duration of a user interaction, initialize a Page object describing that interaction and pass it to BlueTriangle.startTimer(page:timerType) to receive a running timer instance.

let page = Page(pageName: "MY_PAGE")
let timer = BlueTriangle.startTimer(page: page)

If you need to defer the start of the timer, pass your Page instance to BlueTriangle.makeTimer(page:timerType) and call the timer's start() method when you are ready to start timing:

let page = Page(pageName: "MY_PAGE")
let timer = BlueTriangle.makeTimer(page: page)
...
timer.start()

In both cases, pass your timer to BlueTriangle.endTimer(_:purchaseConfirmation:) to send it to the Blue Triangle server.

BlueTriangle.endTimer(timer)

Running timers are automatically stopped when passed to BlueTriangle.endTimer(_:purchaseConfirmation:), though you can end timing earlier by calling the timer's end() method.

timer.end()
...
// You must still pass the timer to `BlueTriangle.endTimer(_:)` to send it to the Blue Triangle server
BlueTriangle.endTimer(timer)

For timers that are associated with checkout, create a PurchaseConfirmation object to pass along with the timer to BlueTriangle.endTimer(_:purchaseConfirmation:):

timer.end()
let purchaseConfirmation = PurchaseConfirmation(cartValue: 99.00)
BlueTriangle.endTimer(timer, purchaseConfirmation: purchaseConfirmation)

Custom Variables 

In certain scenarios, a developer may need to include additional application-specific information with Timers. This can be achieved by setting custom variables within the BlueTriangle class on iOS (andTracker class on Android). These custom variables are global, meaning that once defined, they will automatically be included with every subsequent Timer payload.

To introduce a custom variable, the developer first needs to create it on the BlueTriangle portal. Follow the instructions provided here. Variables created in the portal have a unique variable name associated with them, e.g. CV1, CV2, etc. which are used while setting the custom variable values.

The custom variable values are sent in String format. The following overload functions are just for the convenience of the app developer. In case of boolean value, the custom variable on the portal should be of type “Text”. 

Setting a Single Custom Variable

Swift 

Swift
BlueTriangle.setCustomVariable(<VARIABLE NAME>, "Some Textual Information"") // String Overload
BlueTriangle.setCustomVariable(<VARIABLE NAME>, true) // Boolean Overload
BlueTriangle.setCustomVariable(<VARIABLE NAME>, 1.2349) // Numeric Overload

Objective-C 

Objective-C
[BlueTriangle setCustomVariable:<VARIABLE NAME> strValue:@"Some Textual Information")]; // String Overload
[BlueTriangle setCustomVariable:<VARIABLE NAME> numValue:true)]; // Boolean Overload
[BlueTriangle setCustomVariable:<VARIABLE NAME> boolValue:1.2349)]; // Numeric Overload
Setting Multiple Custom Variables

These methods take a map/dictionary as input, where all the key and values are of String type. The keys correspond to the custom variable names and the values are their respective custom variable values.

Swift

Swift
BlueTriangle.setCustomVariables(values)

Objective-C

Objective-C
[BlueTriangle setCustomVariables:values];
Getting a Single Custom Variable

There are no method overloads for different data types, as those values are converted to String when they are set. The app developer needs to use the correct data types are parsed after getting the value from getCustomVariable.

If there is no value stored against the provided variable name, this method will return null/nil.

Swift

Swift
var value = BlueTriangle.getCustomVariable(<VARIABLE NAME>)

Objective-C

Objective-C
NSString *value = [BlueTriangle getCustomVariable:<VARIABLE NAME>];
Getting All Custom Variables

These methods take a map/dictionary as input, where all the key and values are of String type. The keys correspond to the custom variable names and the values are their respective custom variable values.

Swift

Swift
var variables = BlueTriangle.getCustomVariables()

Objective-C

Objective-C
NSDictionary *values = [BlueTriangle getCustomVariables];
Clearing a Single Custom Variable

Swift 

Swift
BlueTriangle.clearCustomVariable(<VARIABLE NAME>)

Objective-C

Objective-C
[BlueTriangle clearCustomVariable:<VARIABLE NAME>];
Clearing All Custom Variables

Swift

Swift
BlueTriangle.clearAllCustomVariables()

Objective-C

Objective-C
[BlueTriangle clearAllCustomVariables] 

Optional Configuration Steps

ANR Detection

BlueTriangle tracks you app’s responsiveness by monitoring main THREAD USAGE. If any task blocking main thread for extended period of time causing app not responding, will be tracked as ANR Warning. By default, this time interval is 5 Sec I.e. if any task blocking main thread more then 5 sec will be triggered as ANRWarning. This timeinterval can be changed using "ANRWarningTimeInterval" Property below.

BlueTriangle.configure { config in
        ...
       config.ANRWarningTimeInterval = 3
}

You can disable it by setting "ANRMonitoring" configuration property to "false" during configuration.

BlueTriangle.configure { config in
        ...
        config.ANRMonitoring = false
}

Memory Warning

Blue Triangle tracks iOS reported low memory warnings by monitoring UIApplication.didReceiveMemoryWarningNotification notifications.

You can disable it by setting "enableMemoryWarning" configuration property to "false" during configuration.

BlueTriangle.configure { config in
        ...
        config.enableMemoryWarning = false
}

Memory Usage

Memory usage is the amount of memory used by the code during the Timer interval. This is measured in number of bytes.

Against each timer, 3 Memory measurements are being sent, minimum, maximum and average.

Memory usage refers to the amount memory (RAM) that is currently being used by application to store and manage data. In analytics.rcv payload data json, 'minMemory', 'maxMemory' and 'avgMemory' are being used to send the respective memory usage.

To set the interval (in s) at which the Memory usage is being captured, set the following field:

 BlueTriangle.configure { config in
         ...
         config.performanceMonitorSampleRate = 1
     }

To disable Memory usage set the following field:

BlueTriangle.configure { config in
       ...
       config.isPerformanceMonitorEnabled = false
   } 

CPU Usage

CPU Usage is the amount of CPU being used by the code during the Timer interval. This is measured in the form of 0-100%.

Against each timer, 3 CPU measurements are being sent, minimum, maximum and average.

CPU usage is being reported by xcode as X.100% format [where X is number of cores], it typically means that the system is utilizing the CPU resources heavily. To express this in a 0% to 100% format, Blue Triangle calculates the CPU usage by dividing number of CPU cores. This will give you a percentage value between 0% and 100%.

0% to 100% format = Total current CPU usage on Instruments / Number of CPU cores.

For example:, if you have 4 CPU cores and your current usage is 300%. then actual BTT CPU usage 300% / 4 = 75%. This indicates that CPU is being utilized at 75% of its total capacity.

To set the interval (in s) at which the CPU usage is being captured, set the following field in BlueTriangleConfiguration:

BlueTriangle.configure { config in
         ...
         config.performanceMonitorSampleRate = 1
     }

To disable CPU usage set the following field in BlueTriangleConfiguration:

BlueTriangle.configure { config in
       ...
       config.isPerformanceMonitorEnabled = false
   }

Track Crashes

Blue Triangle tracks app crashes - by default crash tracking is enabled. 

Crash tracking tools can interfere with each other, and not configuring the Blue Triangle SDK properly may result in conflicts that will not allow the Blue Triangle SDK to capture crashes. 

It is recommended to configure the Blue Triangle SDK before any other crash tracking tool to prevent conflicts with those tools. Additionally, testing the crash reporting before moving to production is advised in order to ensure crashes are reported to both Blue Triangle and your other crash tracking tool.

If it is not possible to configure the Blue Triangle SDK before your other crash tracking tool, please use  BlueTriangle.startCrashTracking(). This function allows Blue Triangle to start crash tracking earlier, which will help in scenarios where you wish to configure the Blue Triangle SDK after a different crash tracking tool is configured.

To disable blue triangle crash tracking use following configuration:

BlueTriangle.configure { config in
config.siteID = "<MY_SITE_ID>"
//Disable crash tracking
config.crashTracking = .none
} 

Offline Caching

Offline caching is a feature that allows the BTT SDK to keep track of timers and other analytics data while the app is in offline mode. i.e, the BTT SDK cannot send data back to Blue Triangle.

There is a memory limit as well as an expiration duration put on the cached data. If the cache exceeds the memory limit then additional tracker data will be added only after removing some older, cached data (first in, first out). Similarly, cache data that has been stored for longer than the expiration duration would be discarded and won't be sent to the tracker server.

Memory limit and Expiry Duration can be set by using configuration property cacheMemoryLimit and cacheExpiryDuration as shown below:

 BlueTriangle.configure { config in
         ...
            config.cacheMemoryLimit = 50 * 1024 (Bytes)
            config.cacheExpiryDuration = 50 * 60 * 1000 (Millisecond)
 }

By default, the cacheMemoryLimit is set to 48 hours and cacheExpiryDuration is set to 30 MB.

Network State Capture

BlueTriangle SDK allows capturing of network state data. Network state refers to the availability of any network interfaces on the device. Network interfaces include wifi, ethernet, cellular, etc. Once Network state capturing is enabled, the Network state is associated with all Timers, Errors and Network Requests captured by the SDK. This feature is enabled by default.

You can disable it by setting enableTrackingNetworkState property to "false" during configuration.

 BlueTriangle.configure { config in
         ...
         config.enableTrackingNetworkState = false
  }

Launch Time

Blue Triangle tracks app launch performance. Launch time refers to the duration it takes for an app to become ready for user interaction after it has been started. Blue Triangle automatically tracks both hot launch and cold launch.

Cold Launch

A cold launch occurs when the app process is not already stored in the main memory. This can happen because iOS or the user terminated your app's process or its first time launch after install/update/reboot.

The Blue Triangle SDK measures the cold launch latency, which is the time between the process start time and the end of 'applicationDidBecomeActive(:)'. The cold launch time is the cumulative time taken to load the process plus the time taken by 'application(:didFinishLaunchingWithOptions:)', 'applicationWillEnterForeground(:)' and 'applicationDidBecomeActive(:)'.

Hot Launch

A Hot Launch occurs when the app is already running in the background and is brought to the foreground. This type of launch is typically faster since the app's state is preserved in memory.

The Blue Triangle SDK measures the hot launch latency, which is the time between the end of 'applicationWillEnterForeground(:)' and end of 'applicationDidBecomeActive(:)'. The hot launch time is taken from 'applicationDidBecomeActive(:)'.

When the user locks the device while the app was on the screen and then unlocks it,  iOS gives a background and a foreground notification. Therefore, unlocking followed by locking while the app was active is tracked as a Hot Launch.

You can disable it by setting "enableLaunchTime" configuration property to "false" during configuration:

BlueTriangle.configure { config in
...
config.enableLaunchTime = false

}

How to Test your iOS SDK

Memory Warning

To test Memory Warning, In the iOS Simulator, you can generate a memory warning using the following steps:

        1. Launch Simulator

        2. Go to XCode 'Debug' menu

        3. Select 'Simulate Memory Warning' to generate memory warning

ANR Tracking

To test ANR Tracking, You can declare and call the following function on the main thread:

func testANRTracking(){ let startTime = Date() while true { 
  if (Date().timeIntervalSince1970 - startTime.timeIntervalSince1970) > 30 { 
      break } 
    } 
  }

Crash Tracking

To test Crash Tracking, you can declare and call the following function:

func testCrashTracking() {  let array = NSArray()  array.object(at: 99)  } 

Limitations/Known Issues

Crashes

The expiration timestamp is only updated when the app offscreen event is received and therefore the app offscreen events cannot be handled when a crash happens. Because of this, BTT is unable to renew the session expiration timestamp in crash scenarios. The potential impact of this scenario is that the session could expire in less than 30 minutes instead of 30 minutes. The exact duration of expiration would depend on the last time the user went offscreen since that was when the expiration timestamp was set. 

WebView Stitching

If a WebView was displaying in the app when the user went offscreen, when the user returns the session is updated. The Blue Triangle btt.js tag receives the new session id, however the btt.js tag manages its own session. Because of this, after the session is injected into the WebView, the btt.js tag itself renews its internal session, possibly resulting in the tag using a different session than the Native SDK.

General Information

Supported SDK Metrics

  • Performance & Network Timings

    • Main Timers

    • Network Timers

    • Custom Timers

  • Errors & Crashes

  • Application Not Responding (ANR)

  • HTTP Response Codes

  • App Crashes

  • Device Stats & Session Attributes

    • OS/OS Version

    • App Version

    • Device Type

    • Geographical/Country

    • CPU Usage

    • Memory Warnings

    • Memory/Out of Memory

    • Hot/Cold Launch

    • Network Type

    • Device Model

    • Custom variables

Release Notes

Version

Date

Notes

3.15.14

July 27, 2026

Combined repetitive SwiftUI view entries in breadcrumbs for cases like list and for each. Multiple view appear in a list will be shown as a single entry with a count

3.15.13

July 10, 2026

  • Introduced BTTInstrumentor command-line tool that automatically instruments SwiftUI views.

3.15.12

May 26, 2026

  • Added support for app install reporting.

  • Added support for force restart error reporting.

  • Added remote configuration support to enable or disable user action tap interception.

3.15.11

April 30, 2026

Bug Fixes and Improvement

  • Fixed an occasional concurrency crash while updating session ID.

3.15.10

Mar 23, 2026

Added breadcrumbs for ANRs, Crashes, and Memory Warnings

3.15.9

Feb 18, 2026

  • Add support for remote configuration of the SDK to report checkout events based on screen or API calls that represent a successful checkout. This is to maintain representation of conversion events in production in case such event was not instrumented as described in the quick start guide.

  • Added support for custom categories and additional parameters abTestID, campaignMedium, campaignName, campaignSource, and dataCenter.

  • Added support for Xcode 26 compatibility.

3.15.8

Jan 28, 2026

  • Removed redundant analytics beacons from errors/crashes in most cases

  • Network data and classes will be sent in the same sessions, following the set fidelity rate

  • Matching Page Group and Traffic Segment between error and analytics beacons

3.15.7

Jan 5, 2026

  • Added the ability to enable or disable SDK features through remote configuration, including CrashTracking, ANRTracking, MemoryWarning, LaunchTime, WebViewStitching, NetworkStateTracking, and GroupingTapDetection

  • Fixed a crash that occurred while reporting a signal crash when calling setCurrentPageName

  • Default grouped view sample rate set to 5% for automated timers

  • Fixed excessive Launch time values issue

3.15.6

Nov 24, 2025

Added Swift 6 strict concurrency compatibility by adding pre-concurrency and unchecked sendable.

3.15.5

Nov 21, 2025

Bug fixes and Improvements

  • Lowercased entry type value to lowercased "screen"

  • Changed remote config URL to use site prefix

  • Fixed network sample rate config parsing to accept decimal values e.g. 1.5%, 2.5%, etc.

3.15.4

Nov 19, 2025

Bug Fixes and Improvements

  • Fixed an occasional concurrency crash when a timer ended by calling end method.

  • Fixed a rare race condition that happens during very quick background foreground action.

3.15.3

Nov 4, 2025

Fixed crashes which could occur during ANR reporting and while grouping timers

3.15.2

Oct 8, 2025

Fixed edge case bug when rapidly switching network between Wi-Fi and cellular

3.15.1

Sep 16, 2025

Report CPU, Memory for classes and fragments

3.15.0

Sep 2, 2025

  • Automated Grouping of Activity/Fragments/Composables

  • Automated group name through screen title or class name.

  • Manual API to start a new group with setNewGroup().

  • Manual API to provide group name with setGroupName() method.

  • Grouping enabled by default

  • Calculation of page time for Group by doing a sum of all Fragments/Activities/Composables with discarding overlapped timings.

See here for more details.

3.14.2

Aug 1, 2025

  • Separate App and SDK versions

  • Added the ability to enable/disable screen tracking from the portal

3.14.0

Apr 8, 2025

No-code support for integrated Clarity (session playback) experience. The SDK will automatically detect the presence of Clarity, request a playback URL, which would show in the performance details page. To read more about Blue Triangle integration with Clarity, please click here.

3.13.2

Feb 5, 2025

Added the ability to disable or enable the SDK (in production) through remote configuration.

3.13.1

Dec 27, 2024

Added the ability to suppress reporting of native views from the SDK through a portal setting. This is beneficial to remotely control SDKs in production. At present this is an SDK capability only, customers wishing to use this feature should contact their account manager.

3.13.0

Dec 6, 2024

Remotely overwrite the Network Sample Rate from the portal

3.12.0

Oct 23, 2024

Custom Variables Support

3.11.0

Oct 7, 2024

Collection of network protocols

3.10.1

September 23, 2024

Collection of device models

3.10.0

September 4, 2024

Feature Improvements

  • Added session expiry after 30 minutes of inactivity

  • Session will now be maintained within 30 minutes duration across app background, app kills and system reboots

  • Automatically updates session in WebView on session expiry

3.9.0

July 17, 2024

Introduced Signal Crash Tracking alongside the existing crash support

3.8.0

June 17, 2024

Added Cart Count, Cart Count Checkout fields to support checkout workflow

3.7.0

May 22, 2024

Support for hot and cold application launch timers

3.6.0

May 2, 2024

Simplified and reduced instrumentation needs

3.5.1

April 26, 2024

Added privacy manifest

3.5.0

March 20, 2024

New features

  • Network state capture

  • WebView tracking

  • Memory Warning

Feature Improvements

  • Improved CPU and Memory Tracking feature

  • Improved offline caching mechanism with the inclusion of Memory limit and Expiration

3.4.0

July 24, 2023

New Features

  • Automated mobile View Tracking for view controllers and SwiftUI views

  • Application Not Responding tracking and reporting as "ANRWarnings"