Swift Core Installation
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 parent iOS device. Tracking a user across both will require using
Heap.shared.identify
to combine the users under a single identity.
For notes on the latest SDK versions, see our iOS changelog.
Installation
Heap Swift Core can be installed using Swift Package Manager or CocoaPods.
Swift Package Manager Installation
- In Xcode, open the package manager by either navigating to File → Add Packages… in the menu, or, by opening the Package Dependencies tab of the project file and clicking the "+" button.
- In the top right corner of the control, paste
https://github.com/heap/heap-swift-core-sdk.git
into the Search or Enter Package URL text field.
- Select a Dependency Rule. We recommend "Up to Next Major Version".
- Click Add Package in the lower right corner of the dialog.
- Once the next dialog finishes loading, select the checkbox next to HeapSwiftCore, confirm you're adding to the app target, and click Add Package.
- Confirm that “HeapSwiftCore” and “SwiftProtobuf” now appear in the Package Dependencies section of the Project Navigator.
- Before continuing to Initializing Heap Swift Core, build the app to help Swift resolve the modules.
CocoaPods Installation
CocoaPods is a Ruby-based dependency manager for iOS projects. Heap requires CocoaPods 1.11.0 or later.
- To get started, follow the instructions for installing CocoaPods at https://cocoapods.org.
- Save the following line to your Podfile:
pod 'HeapSwiftCore', '~> 0.1'
- Run
pod install
within your project directory. - If you weren't already using CocoaPods or a Workspace, close your project and open the new file with the
.xcworkspace
extension. - Before continuing to Initializing Heap Swift Core, build the app to help Swift resolve the modules.
macOS Considerations
If you are developing a macOS app that doesn't currently allow outgoing network connections, you'll need to enable the feature in your app sandbox using the following steps.
- Select your project file in the Project Navigator.
- Select your app target under Targets.
- Select the Signing & Capabilities tab.
- Scroll down to the App Sandbox section.
- Check Outgoing Connections (Client).
Manual Installation
Because Heap depends on SwiftProtobuf, there's currently no manual installation option.
Initializing Heap Swift Core
The Heap Swift SDK is always either recording or not recording. When the SDK isn't recording, the APIs for tracking events, managing users, and setting user and event properties are no-ops. To avail yourself of these APIs, you'll need to do the following:
When you want to start recording, call Heap.shared.startRecording
in the manner shown in the code snipped below. We typically recommend invoking this in application(_:,didFinishLaunchingWithOptions:)
to capture the whole lifecycle of the app, but this can be called at a later point if you need to wait for conditions to be met.
import HeapSwiftCore
...
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Replace YOUR_APP_ID with your Heap app ID of the environment you wish to send data to.
Heap.shared.startRecording("YOUR_APP_ID")
return true
}
@import HeapSwiftCore
...
- (BOOL)application:(UIApplication _)application didFinishLaunchingWithOptions:(NSDictionary _)launchOptions
{
// Replace YOUR_APP_ID with your Heap app ID of the environment you wish to send data to.
[Heap.sharedInstance startRecording:@"YOUR_APP_ID"];
return YES;
}
If you are developing a pure SwiftUI app, one place to start Heap would be in the init method of a state object:
import SwiftUI
final class StateStore: NSObject, ObservableObject {
init() {
...
Heap.shared.startRecording("YOUR_APP_ID")
}
...
}
@main
struct ExampleApp: App {
@StateObject var stateStore = StateStore()
...
}
Using logs to validate the install
By default, Heap logs a minimal amount of data to the console, with the aim of providing appropriate information for a production install. Once Heap is running, you should see a message with the text [Heap] Heap started recording with environment ID YOUR_APP_ID.
. This will be followed by messages about uploads succeeding or failing.
It may be helpful to increase the log level during initial deployment to validate events are getting fired. To do this, add the following line in your app.
import HeapSwiftCore
...
HeapLogger.shared.logLevel = .debug
@import HeapSwiftCore
...
HeapLogger.sharedInstance.logLevel = HeapLogLevelDebug;
This will provide even more detailed messages about Heap usage, typically with about one or two messages per API call.
Another option, .trace / HeapLogLevelTrace
is available for more complex debugging situations, but these messages are noisier and intended primarily for Heap developers to review.
API Methods
HeapSwiftCore.Heap
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] = [:])
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.
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()
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
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): TheDictionary
of properties to associate with the event. Map keys are represented by strings and values can be any combination of anyInt
,Double
,Bool
,String
, or type that implements theHeapPropertyValue
protocol.timestamp
(optional): The non-nullDate
of when the event occurs. Defaults to the current time. Your implementation shouldn't assign values for this parameter.sourceInfo
(optional): The nullableSourceInfo
object if this event was generated by an autocapture SDK. Defaults tonull
. Your implementation shouldn't assign values for this parameter.pageview
(optional): ThePageview
to associate with the tracked event. This is most commonly the case if the event was generated by an autocapture SDK. Defaults tonull
. Your implementations shouldn't 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 as1
and0
. 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)
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 reset 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.
// 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,
}];
resetIdentity()
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 wasn't 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])
addUserProperties(_ properties: [String: HeapPropertyValue])
Description
Add a collection of properties to be associated with the current user.
Parameters
properties
: TheDictionary
of properties to associate with the current user. Map keys are represented by strings and values can be any combination of anyInt
,Double
,Bool
,String
, or type that implements theHeapPropertyValue
protocol.
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])
addEventProperties(_ properties: [String: HeapPropertyValue])
Description
Add a collection of properties to be associated with all future events from the current user.
Parameters
event
: The string name of the event.properties
: TheDictionary
of properties to associate with future events. Map keys are represented by strings and values can be any combination of anyInt
,Double
,Bool
,String
, or type that implements theHeapPropertyValue
protocol.
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)
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()
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 }
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 }
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 }
sessionId: String? { get }
Description
Returns the current session ID if Heap is recording and the session hasn't 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's 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 isn't recording.
Examples
let heapSessionId = Heap.shared.sessionId;
NSString *heapSessionId = Heap.sharedInstance.sessionId;
fetchSessionId() -> String?
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 isn't recording.
Examples
let heapSessionId = Heap.shared.sessionId;
NSString *heapSessionId = Heap.sharedInstance.sessionId;
HeapSwiftCore.Option
HeapSwiftCore.Option
A collection of options used for initializing Heap.
Note: In Swift, this can typically be used with .
shorthand syntax. In Objective-C, the type name is HeapOption
.
The Option
dictionary accepts any value type and values are validated and copied during startRecording
. To confirm which values are applied, use LogLevel.debug
before startRecording
.
baseUrl
(String
or URL
)
baseUrl
(String
or URL
)The base URL to upload data to while Heap is running. This follows relative link mechanics must end with a /
for paths to resolve correctly.
This parameter primarily exists for testing and proxying purposes, and in most use cases this parameter shouldn't be set.
uploadInterval
(TimeInterval
or Int
or Double
literal)
uploadInterval
(TimeInterval
or Int
or Double
literal)The interval at which event batches should be uploaded to the API. Defaults to 15 seconds.
For apps with limited connectivity, it may make sense to increase this interval. Note: Shorter upload intervals may impact device battery life but improve the experience while using live data feed to create events.
captureAdvertiserId
(Bool
)
captureAdvertiserId
(Bool
)Whether or not to track advertisingIdentifier
in events. Defaults to false
.
This has no effect if AdSupport hasn’t been linked in the app and will only provide a valid value if the user has authorized the app to read it.
messageBatchByteLimit
(Bool
)
messageBatchByteLimit
(Bool
)The maximum size of message batches to send to the server in a single request, in bytes. Significantly smaller sizes will result in more requests. The default is 1MB.
This parameter primarily exists for testing purposes, and in most use cases, this parameter shouldn't be set.
messageBatchMessageLimit
(Bool
)
messageBatchMessageLimit
(Bool
)The maximum size of message batches to send to the server in a single request, in messages. Significantly smaller sizes will result in more requests. The default is 200.
This parameter primarily exists for testing purposes, and in most use cases, this parameter shouldn't be set.
Examples
// Without options
Heap.shared.startRecording("YOUR_APP_ID")
// With options
Heap.shared.startRecording("YOUR_APP_ID", with: [
.uploadInterval: 60,
.captureAdvertiserId: true,
])
// Without options
[Heap.sharedInstance startRecording:@"YOUR_APP_ID"];
// With options
[Heap.sharedInstance startRecording:@"YOUR_APP_ID" withOptions:@{
HeapOption.uploadInterval: @60,
HeapOption.captureAdvertiser: @YES,
}];
HeapSwiftCore.HeapPropertyValue
and HeapSwiftCore.HeapObjcPropertyValue
HeapSwiftCore.HeapPropertyValue
and HeapSwiftCore.HeapObjcPropertyValue
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.
Types are limited here to avoid issues where developers may accidentally pass object types to the methods which have no clear path to resolution. If you wish to pass an object as a property, Heap provides two protocols to do this: HeapPropertyValue
for use in Swift and HeapObjcPropertyValue
for use in Objective-C. Both require a single property definition: var heapValue: String { get }
Examples
struct Book {
let title: String
let author: String
let year: Int
}
extension Book: HeapPropertyValue {
var heapValue: String { title }
}
@interface Book: NSObject
@property (nonatomic, nonnull, copy) NSString *title;
@property (nonatomic, nonnull, copy) NSString *author;
@property (nonatomic) NSInteger year;
@end
@interface Book (PropertyValue) <HeapObjcPropertyValue>
@end
@implementation Book (PropertyValue)
- (nonnull NSString *)heapValue
{
return self.title;
}
@end
HeapSwiftCore.HeapLogger
HeapSwiftCore.HeapLogger
A logging utility for use by Heap and libraries built on top of it. This class provides several logging methods not described here, and two configuration properties that are useful for tailoring the log experience.
logLevel: LogLevel { get; set }
logLevel: LogLevel { get; set }
Description
Gets and sets the current log level. The default value is LogLevel.info
(HeapLogLevelInfo
in Objective-C).
Example
HeapLogger.shared.logLevel = .debug
HeapLogger.sharedInstance.logLevel = HeapLogLevelDebug;
Description
Gets and sets the current log channel used for printing logs. The default log channel prints all messages to the Xcode console and all levels except LogLevel.trace
to the system console using OSLog
using the bundle identifier as the subsystem and “Heap” as the category.
This property can be set to a custom implementation that reroutes logs to another logging tool, such as SwiftLog or CocoaLumberjack.
This property is not available in Objective-C.
Example
HeapLogger.shared.logChannel = MyCustomLogChannel()
HeapSwiftCore.LogLevel
HeapSwiftCore.LogLevel
This enum defines the different log levels available in Heap.
LogLevel.none
(HeapLogLevelNone
)
LogLevel.none
(HeapLogLevelNone
)Description
Heap won't print any log messages.
LogLevel.error
(HeapLogLevelError
)
LogLevel.error
(HeapLogLevelError
)Description
Heap will only print the most critical log messages, such as when the SDK encounters an error and needs to shut down.
LogLevel.warn
(HeapLogLevelWarn
)
LogLevel.warn
(HeapLogLevelWarn
)Description
Heap will print warning messages that are useful in a production environment, such as when an event is invalid or an upload fails.
This level is recommended for production environments so that developers are aware of failures that can impact data.
This level also includes error
messages.
LogLevel.info
(HeapLogLevelInfo
)
LogLevel.info
(HeapLogLevelInfo
)Description
Heap will print messages that are useful in a production environment, such as when recording starts/stops, when a batch of events is successfully sent, or when a new session has begun.
This level is recommended for production environments so that developers can see Heap lifecycle messages in their own logging environment.
This level also includes error
and warn
messages.
LogLevel.debug
(HeapLogLevelDebug
)
LogLevel.debug
(HeapLogLevelDebug
)Description
Heap will print messages that the implementing developer may find helpful. Messages may include things such as invalid environment ID value, truncated event names, or attempting to track an event before recording has started.
This level is recommended for developers implementing Heap during the development process to help with debugging normal installation and tracking issues.
This level also includes error
, warn
, and info
messages.
LogLevel.trace
(HeapLogLevelTrace
)
LogLevel.trace
(HeapLogLevelTrace
)Description
Heap will print messages that help the Heap team diagnose SDK issues. Heap support may ask the implementing developers to enable this log level to gain better insight into issues developers may have encountered when implementing the Heap SDK.
Full event details are also printed at this level.
This level is recommended when gathering information to send to Heap support personnel. Heap support may also ask that this level be turned on to help debug installation and tracking issues that require extra investigation.
This level also includes error
, warn
, info
, and debug
messages.
HeapSwiftCore.LogChannel
HeapSwiftCore.LogChannel
This protocol provides a single method for consuming Heap logs.
printLog(logLevel: HeapSwiftCore.LogLevel, message: () -> String, source: String?, file: String, line: UInt)
printLog(logLevel: HeapSwiftCore.LogLevel, message: () -> String, source: String?, file: String, line: UInt)
Description
Logs a message. Heap will have already filtered log messages based on LogLevel
so the method is solely responsible for rendering the message.
Parameters
logLevel
: TheLogLevel
associated with this message.message
: An unevaluated closure for rendering the log message.source
: A nullable string name of the source library that produced the message. This will benil
for messages coming from HeapSwiftCore, but will have a value for messages originating from bridging and autocapture libraries.file
: The file the message originated from, either#fileID
or#file
depending on the Swift version used.line
: The line in the file the message originated from,#line
.
Example
The following is an example of a logger that sends messages through apple/swift-log:
import Logging
class SwiftLogChannel: LogChannel {
let logger: Logger
func printLog(logLevel: HeapSwiftCore.LogLevel, message: () -> String, source: String?, file: String, line: UInt) {
switch logLevel {
case .trace:
logger.trace(message(), file: file, line: line)
case .debug:
logger.debug(message(), file: file, line: line)
case .info:
logger.info(message(), file: file, line: line)
case .warn:
logger.warn(message(), file: file, line: line)
case .error:
logger.error(message(), file: file, line: line)
default:
break
}
}
}
...
HeapLogger.shared.logChannel = SwiftLogChannel(logger: logger)
Updated over 1 year ago