Swift and UIKit SDK reference

This is a reference guide for all Swift and UIKit SDK requirements, known limitations, API reference, and performance impact information.

The Swift and UIKit SDKs are distributed through Swift Package Manager and Cocoapods.

For notes on the latest SDK versions, see our iOS changelog.

❗️

If you're using Heap's Classic iOS SDK and thinking about switching to our newest offerings, please note that some event definitions might need to be repaired after upgrade.

Need help with this process? Please post in Community or contact us via the Get support page in Heap.

📘

This reference is exclusive to Heap's current Swift and UIKit SDK offerings. For information about Heap's Classic iOS SDK, you can visit its documentation here.

Heap Swift Core Reference

Requirements + Known Limitations

  • This SDK requires the following minimum OS versions:
    • macOS 10.14
    • iOS 12.0
    • watchOS 5.0
    • tvOS 12.0
  • The SDK requires Xcode 14.0 or later.
  • The SDK depends on SwiftProtobuf, a Swift package developed by Apple.
  • watchOS support is currently limited to Swift Package Manager implementations.
  • watchOS devices will have separate sessions and user IDs from the paired iOS device. Tracking a user across both will require the use of Heap.shared.identify to combine the users under a single identity.
  • macOS apps require the "Outgoing Connections (Client)" permission in the App Sandbox settings.

Installation

Add the Heap SDK to your application with Swift Package Manager

  1. In Xcode, open the package manager however you are accustomed to. The most direct path is navigating to File → Add Packages… in the menu.
  2. Paste https://github.com/heap/heap-swift-core-sdk.git into the Search or Enter Package URL text field at the top right corner of the dialog.
  3. Select a Dependency Rule. We recommend Up to Next Major Version.
  4. Click Add Package.
  5. In the next dialog, check the checkbox next to HeapSwiftCore and confirm that it will be added to your app target.
  6. Click Add Package.
  7. After the dialog closes, you can optionally confirm that HeapSwiftCore and SwiftProtobuf now appear in the Package Dependencies section of the Project Navigator.
  8. Before continuing, build your app target to help Swift resolve the modules.

Add the Heap SDK to your application with CocoaPods

  1. Add pod 'HeapSwiftCore', '~> 0.6' to your app target in your Podfile.
  2. Run pod install within your project directory.
  3. Before continuing, build your app target to help Swift resolve the modules.

API Reference

HeapSwiftCore.Heap

The publicly-facing API for the Heap Swift Core SDK.

Note: The Heap object follows the singleton convention and all methods are accessible through Heap.shared in Swift and Heap.sharedInstance in Objective-C.

startRecording(_ environmentId: String, with options: [Option: Any] = [:])

Description
Initializes the Heap SDK and enables Heap to start recording data.

If Heap is already recording and the options have changed, Heap will restart tracking with the new options, creating a new session. Otherwise, calling this method multiple times with the same value has no effect.

Parameters

  • environmentId: The environment ID to which data should be attributed.
  • options: (optional) A dictionary of configuration options for use starting the SDK. See Swift Custom Configuration for available options.

Objective-C method signatures

- (void)startRecording:(NSString * _Nonnull)environmentId;
- (void)startRecording:(NSString * _Nonnull)environmentId
           withOptions:(NSDictionary<HeapOption *, id> * _Nonnull)options;

Examples

// Without options
Heap.shared.startRecording("YOUR_APP_ID")

// With options
Heap.shared.startRecording("YOUR_APP_ID", with: [
  .uploadInterval: 60, // Upload every 60 seconds instead of every 15.
])
// Without options
[Heap.sharedInstance startRecording:@"YOUR_APP_ID"];

// With options
[Heap.sharedInstance startRecording:@"YOUR_APP_ID" withOptions:@{
  HeapOption.uploadInterval: @60, // Upload every 60 seconds instead of every 15.
}];

stopRecording()

Description
Shuts down the Heap SDK and prevents any further data collection.

Examples

Heap.shared.stopRecording()
[Heap.sharedInstance stopRecording];

track(_ event: String, properties: [String: HeapPropertyValue] = [:], timestamp: Date = Date(), sourceInfo: SourceInfo? = nil, pageview: Pageview? = nil)

Description
Creates an event message to be tracked and sent to the Heap API.

Parameters

  • event: The string name of the event.
  • properties (optional): The Dictionary of properties to associate with the event. Keys are represented by strings and values can be any type described in Supported Property Values.
  • timestamp (optional): The non-null Date of when the event occurs. Defaults to the current time. Customer implementations should not assign values for this parameter.
  • sourceInfo (optional): The nullable SourceInfo object if this event was generated by an autocapture SDK. Defaults to null. Customer implementations should not assign values for this parameter.
  • pageview (optional): The Pageview to associate with the tracked event. This is most commonly the case if the event was generated by an autocapture SDK. Defaults to null. Customer implementations should not assign values for this parameter.

Objective-C method signatures

- (void)track:(NSString * _Nonnull)event;
- (void)track:(NSString * _Nonnull)event
   properties:(NSDictionary<NSString *, id <HeapObjcPropertyValue>> * _Nonnull)properties;

The Objective-C method accepts NSString and NSNumber property values, as well as any type that conforms to the HeapObjcPropertyValue protocol.

🚧

Due to runtime limitations, booleans of @YES and @NO are stored as “true” and “false”, while non-Objective-C boolean types are rendered as 1 and 0. If this affects analysis, the booleans should be converted to strings before calling the method. For example: @{ @"isDiscounted": isDiscounted ? @"true" : @"false" }

Examples

// Without properties
Heap.shared.track("Added to cart")

// With properties
Heap.shared.track("Added to cart", properties: [
  "product_category": self.product.category,
])
// Without properties
[Heap.sharedInstance track:@"Added to cart"];

// With properties
[Heap.sharedInstance track:@"Added to cart" properties: @{
  @"product_category": self.product.category,
}];

identify(_ identity: String)

Description
Assigns an identity to be associated with the current user ID, used for combining users across multiple implementations.

If the identity is already set and different from the past identity, this will have the effect of resetting the user ID and session while setting the identity.

Parameters

  • identity: The string value representing the identity to associate with events. This should uniquely identify the person using the app and never a hard-coded value.

Examples
In this example, the app has a method userAuthenticated which is called when the user logs into the app.

Heap.shared.identify("some_identity")
[Heap.sharedInstance identify:@"some_identity"];

resetIdentity()

Description
Resets the state for a user that was previously identified with identify, creating a new user and session while clearing event properties. If the user was not previously identified, this method has no effect.

Examples
In this example, the app has a method userLoggedOut which is called when the user logs out of the app.

func userLoggedOut() {
  ...
  Heap.shared.resetIdentity()
}
- (void)userLoggedOut
{
  ...
  [Heap.sharedInstance resetIdentity];
}

addUserProperties(_ properties: [String: HeapPropertyValue])

Description
Add a collection of properties to be associated with the current user.

Parameters

  • properties: The Dictionary of properties to associate with the current user. Keys are represented by strings and values can be any type described in Supported Property Values.

Objective-C method signatures

- (void)addUserProperties:(NSDictionary<NSString *, id <HeapObjcPropertyValue>> * _Nonnull)properties;

The Objective-C method has the same considerations as track. It accepts NSString and NSNumber property values, as well as any type that conforms to the HeapObjcPropertyValue protocol.

Examples
In this example, the app has a method userAuthenticated which is called when the user logs into the app.

func userAuthenticated(user: AppUser) {
  ...
  Heap.shared.addUserProperties([
    "membership_tier": user.membershipTier,
    "team_name": user.team.name,
  ])
}
- (void)userAuthenticated:(AppUser * _Nonnull)user
{
  ...
  [Heap.sharedInstance addUserProperties:@{
    @"membership_tier": user.membershipTier,
    @"team_name": user.team.name,
  }];
}

addEventProperties(_ properties: [String: HeapPropertyValue])

Description
Add a collection of properties to be associated with all future events from the current user.

Parameters

  • properties: The Dictionary of properties to associate with future events. Keys are represented by strings and values can be any type described in Supported Property Values.

Objective-C method signatures

- (void)addEventProperties:(NSDictionary<NSString *, id <HeapObjcPropertyValue>> * _Nonnull)properties;

The Objective-C method has the same considerations as track. It accepts NSString and NSNumber property values, as well as any type that conforms to the HeapObjcPropertyValue protocol.

Examples
In this example, the app has a method contentLoaded which is called when a view controller loads data and we want to group future events based on the hero banner that was displayed.

func contentLoaded(content: HomeScreenContent) {
  ...
  if let heroName = content.hero?.name {
    Heap.shared.addEventProperties([
      "home_screen_hero": heroName,
    ])
  }
}
- (void)userAuthenticated:(AppUser * _Nonnull)user
{
  ...
  NSString *heroName = content.hero.name;
  if (heroName != nil) {
    [Heap.sharedInstance addEventProperties:@{
      @"home_screen_hero": heroName,
    }];
  }
}

removeEventProperty(_ name: String)

Description
Removes a single event-wide property that was previously added with addEventProperties.

Parameters

  • event: The string name of the event.

Examples
In this example, we want to track a property on all events while a view controller is on screen:

override func viewDidAppear(_ animated: Bool) {
  super.viewDidAppear(animated)
  Heap.shared.addEventProperties([
    "chat_popup_is_visible": true,
  ])
}

override func viewDidDisappear(_ animated: Bool) {
  super.viewDidDisappear(animated)
  Heap.shared.removeEventProperty("chat_popup_is_visible")
}
- (void)viewDidAppear:(BOOL)animated
{
  [super viewDidAppear: animated];
  [Heap.sharedInstance addEventProperties:@{
    @"chat_popup_is_visible": @YES,
  }];
}

- (void)viewDidDisappear:(BOOL)animated
{
  [super viewDidDisappear: animated];
  [Heap.sharedInstance removeEventProperty:@"chat_popup_is_visible"];
}

clearEventProperties()

Description
Removes all event-wide properties that were previously added with addEventProperties.

Examples
In this example, the app has a method checkoutComplete which is called when the finishes a purchase.

func checkoutComplete() {
  ...
  Heap.shared.clearEventProperties()
}
- (void)checkoutComplete
{
  ...
  [Heap.sharedInstance clearEventProperties];
}

userId: String? { get }

Description
Returns the current user ID if Heap is recording, otherwise nil.

Return Value
The current Heap-generated user ID used for tracking events, or nil if Heap is not recording.

Examples

let heapUserId = Heap.shared.userId
NSString *heapUserId = Heap.sharedInstance.userId;

identity: String? { get }

Description
Returns the identity if Heap is recording and the user has been identified, otherwise nil.

Return Value
The value that was provided to identify for the current user, or nil if Heap is not recording or identify has not been called.

Examples

let heapIdentity = Heap.shared.identity;
NSString *heapIdentity = Heap.sharedInstance.identity;

sessionId: String? { get }

Description
Returns the current session ID if Heap is recording and the session has not expired, otherwise nil.

This method is useful for reading the current state for purposes such as logging. If you are using the session ID for server-side events, it is recommended that you use fetchSessionId(), which will create a new session if needed.

Return Value
The current Heap-generated session ID, or nil if Heap is not recording.

Examples

let heapSessionId = Heap.shared.sessionId;
NSString *heapSessionId = Heap.sharedInstance.sessionId;

fetchSessionId() -> String?

Description
Returns the current session ID if Heap is recording, otherwise nil.

If the previous session has expired, this will start a new session.

Return Value
The current Heap-generated session ID, or nil if Heap is not recording.

Examples

let heapSessionId = Heap.shared.sessionId;
NSString *heapSessionId = Heap.sharedInstance.sessionId;

Supported property values

By default, track, addUserProperties and addEventProperties accept properties of the following types in Swift:

  • Bool
  • Int, Int64, Int32, Int16, Int8
  • Double, Float
  • String, Substring
  • Literals of the above types.
  • NSString, NSNumber

Objective-C accepts just NSString and NSNumber because its dictionaries only accept objects.

If you have a custom type you would like to pass as a property value, you can learn more about the HeapPropertyValue and HeapObjcPropertyValue types in Swift Custom Configuration.

Heap UIKit Autocapture Reference

Requirements + Known Limitations

  • This SDK requires iOS 13.0 or later.
  • The SDK is built with the Swift 5.7 toolchain with module stability and requires Xcode 14.0 or later.
  • The SDK depends on HeapSwiftCore 0.1.2 or later.
  • HeapIOSAutocapture methods that reference Heap directly, like registration, are not available from Objective-C and will need to be called from Swift. A small bridging file can be used to expose the methods.
  • The HeapIOSAutocapture SDK does not currently support automatically capturing interactions from UI elements built with SwiftUI. To capture interactions on UI elements built with SwiftUI, use the track method described above.

Installation

Add the Heap Autocapture SDK to your application with Swift Package Manager

  1. In Xcode, open the package manager however you are accustomed to. The most direct path is navigating to File → Add Packages… in the menu.
  2. Paste https://github.com/heap/heap-ios-autocapture-sdk.git into the Search or Enter Package URL text field at the top right corner of the dialog.
  3. Select a Dependency Rule. We recommend Up to Next Major Version.
  4. Click Add Package.
  5. In the next dialog, check the checkbox next to HeapIOSAutocapture and HeapSwiftCore and confirm that it will be added to your app target.
  6. Click Add Package.
  7. After the dialog closes, you can optionally confirm that HeapIOSAutocapture, HeapSwiftCore, and SwiftProtobuf now appear in the Package Dependencies section of the Project Navigator.
  8. Before continuing, build your app target to help Swift resolve the modules.

Add the Heap Autocapture SDK to your application with CocoaPods

  1. Add pod 'HeapIOSAutocapture', '~> 0.6' to your app target in your Podfile.
  2. Run pod install within your project directory.
  3. Before continuing, build your app target to help Swift resolve the modules.

API Reference

Registration

When the UIKit autocapture library is added to an app, it doesn't automatically start instrumenting the app or capturing events. For touch events and pageviews to be captured, you first need to register the source and start recording. This is done using Heap.iOSAutocaptureSource in Swift and HeapIOSAutocapture in Objective-C.

fun register(isDefault: Boolean = false)

Description
Registers the Heap iOS Autocapture SDK. Once registered, the SDK will autocapture UI interactions and source pageviews.

Parameters

  • isDefault (optional): Whether or not the Heap UIKit Autocapture SDK should be the default source. This setting informs the Heap Swift Core SDK to use the Heap UIKit Autocapture SDK as a fallback for assigning pageview information to events if those events do not have a currently registered source or if their source fails to return a valid pageview. Defaults to false.

Examples

Heap.iOSAutocaptureSource.register(isDefault: true)
[HeapIOSAutocapture registerAsDefault:YES];

Track enhancements

In an app with multiple visible view controllers, like an iPad app with a UISplitViewController, custom events triggered by track will typically be assigned to the last active pageview rather than the view controller it originated from. To support this use case, the Heap UIKit Autocapture SDK adds an additional overload to track that allows you to set a sender. If this sender is an on-screen view, the sender will be used to select the most appropriate pageview for the event.

track(_ event: String, properties: [String: HeapPropertyValue] = [:], timestamp: Date = Date(), sender: Any?)

Description
Creates an event message to be tracked and sent to the Heap API.

Parameters

  • event: The string name of the event.
  • properties (optional): The Dictionary of properties to associate with the event. Keys are represented by strings and values can be any type described in Supported Property Values.
  • timestamp (optional): The non-null Date of when the event occurs. Defaults to the current time. Customer implementations should not assign values for this parameter.
  • sender (optional): The UIView or UIViewController that originated the event, used for selecting the appropriate pageview. If called from an @IBAction, the action's sender or view controller can be used.

Examples

// With a sender
@IBAction func addToCart(_ sender: UIButton) {
  Heap.shared.track("Added to cart", sender: sender)
}

// Without a sender
@IBAction func addToCart() {
  Heap.shared.track("Added to cart", sender: self)
}

View Extensions for Suppressing Sensitive Data

By default, Heap attempts to capture most non-input text from an interaction, including things like button labels, accessibility properties, and the full hierarchy from the touched view. Depending on how your app is designed, some sensitive information may be exposed to events:

  • Pageview titles or on-screen labels may contain usernames or email addresses.
  • Custom inputs like a pin input or calendar can receive individual touches.

In apps with a higher amounts of sensitive data or more restrictive requirements, there are global settings available through autocapture configuration options in startRecording. For apps with certain views or controls that need to be restricted, there are view-specific options below.

For example, in the case of a custom pin input, the following would change events from SecretPinView UIButton[tt=1] to SecretPinView[tt=****]:

pinView.heapIgnoreInnerHierarchy = true
pinView.heapRedactText = true

heapIgnoreInteractions (Bool)

If set on a view or view controller, all touches inside that control will be ignored.

Examples

secretButton.heapIgnoreInteractions = true
secretViewController.heapIgnoreInteractions = true

heapIgnoreInteractionsDefault (Class property, Bool)

This has the same effect as heapIgnoreInteractions but is applied at the class level through an overridable class property. If defined, heapIgnoreInteractions can still be used to override an individual instance.

Examples

class SecretButton: UIButton {
  override class var heapIgnoreInteractionsDefault: Bool { true }
}

heapIgnoreInnerHierarchy (Bool)

If set on a view or view controller, all touches inside that control will be attributed to it rather than child views. This can be helpful in blocking sensitive parts of an interaction and keeping implementation details out of a view hierarchy. For example, Heap uses this property internally to suppress inner touches on UIDatePicker.

Examples

viewWithSecrets.heapIgnoreInnerHierarchy = true

heapIgnoreInnerHierarchyDefault (Class property, Bool)

This has the same effect as heapIgnoreInnerHierarchy but is applied at the class level through an overridable class property. If defined, heapIgnoreInnerHierarchy can still be used to override an individual instance.

Examples

class ViewWithSecrets: UIView {
  override class var heapIgnoreInnerHierarchyDefault: Bool { true }
}

heapRedactText (Bool)

If set on a view or view controller, all views inside that element will have their target text redacted, appearing as "****" in events. When building view text recursively, if a child has heapRedactText == true while the parent has heapRedactText == false

Examples

userNameLabel.heapRedactText = true

📘

Because text can be copied over to accessibility labels when accessibility services are enabled, you may also want to set heapRedactAccessibilityLabel if using this property.

heapRedactAccessibilityLabel (Bool)

If set on a view or view controller, all views inside that element will have their accessibility label redacted, appearing as "****" in events.

Examples

userNameLabel.heapRedactAccessibilityLabel = true

Performance Impact FAQ

Performance

  • Question: What is the performance impact of Heap on a Mobile app?
    • Answer: Heap adds virtually zero performance overhead. Heap never blocks the UI thread of the application and memory is only allocated to process events right before they’re persisted or sent to the server.
  • Question: Does Heap do a ton of main thread writes that could impact the responsiveness of the application?
    • Answer: Heap does not perform any data persistence or networking activity on the main thread. All data persistence and networking operations take place on a background thread.
    • Answer: Heap does perform a very small amount of view traversal on the UI thread to fetch event properties from the corresponding UI objects. This operation is very fast and only involves simple property access. All data that is gathered on the UI thread is sent to a background thread for processing.

Network

  • Question: Are events stored if there is no internet connection or are they dropped? and how many events get stored?
    • Answer: All event data is stored in an SQLite database in application private storage. While online, this database should never grow to more than a few dozen events. While offline, all events are stored in the database until they’re able to be uploaded to the server. However, all data more than 6 days old will be routinely pruned from the database to prevent the database from growing endlessly.
  • Question: Does this behavior differ between core & autocapture SDKs?
    • Answer: No. Autocapture data is sent to Core for storage.
  • Question: How does Heap's event tracking impact network bandwidth?
    • Answer: Heap sends event data in small batches every 15 seconds while connected to the internet. While offline, network data remains in storage and no uploads are attempted.
  • Question: What about network data consumption?
    • Answer: Events on Swift/iOS are roughly 0.5KB in size. Even if we estimate that a typical user produces 2,000 events per day, this only amounts to a single megabyte of data consumption.
  • Question: How does Heap mitigate impacting bandwidth?
    • Answer: Heap batches event data to be sent to the server every 15 seconds to prevent constant network access. Heap also only sends a maximum of 100 events at a time, amounting to roughly 100KB of data per upload. Additionally, if any network errors occur, Heap pushes back the upload process for a full minute to wait for network conditions to improve.

Device

  • Question: Is the user battery life impacted because Heap is running?
    • Answer: Heap should not impact battery life in any meaningful way. Events are batched to be sent periodically to prevent constant network access. This upload frequency should closely match the frequency of network activity of regular app usage for connected applications. If the target application doesn’t not routinely access the network, Heap’s upload interval can be increased to reduce network access and mitigate any unnecessary battery usage.

Storage

  • Question: How much memory does the Heap SDK add to app IPA’s?
    • Answer: Swift Core adds about 860KB to app bundles. iOS Autocapture adds an additional 105KB.
  • Question: Where does Heap store user ID and session ID information?
    • Answer: Heap stores all event data in a SQLite database in private application storage. Some event metadata, such as environment ID, is stored in a file in private application storage.

Build Features

  • Question: What is the expected build-time impact of adding the Heap SDK?
    • Answer:
      • Swift Core adds around 4 seconds of build time on clean builds
      • iOS Autocapture adds around 0.25 seconds of build time on clean builds
      • Swift Core + iOS AutoCapture together add around 4.25 seconds of build time on clean builds.