Overview
iOS SDK enables you to track user interactions within the iOS app and manage its configuration via the console.
The initialized iOS SDK source will automatically collect the following events with data-rich properties:
- Interaction event. Aggregates all action events within the app. For example, the user clicks on a link, or button, or types text into a form.
- Launch event - gathers data on the launch time (timestamp when the iOS app was opened), app name (e.g., Intempt Demo Shop App), iOS device (OS version, device name), geolocation (city, country) screen size (e.g., 667 x 376 px) also records unique visitorId and eventId values.
- Scene event - gets all the data from the UI structure - how and when (timestamp) your user transitions from one view to another. For example, the user goes from the main app view (Intemp_Demo_Shop.ViewController) to the login view (log_in.ViewController) – the event records this transition.
- Consent. Get user consent for using his data for specified purposes (e.g., marketing).
- Location- get the user's country and city - if the user provides permission.
You can also track custom events following the guide below.
How to setup iOS SDK
- iOS 12.0+
- Minimum Xcode 10.0
Getting Started
Integration
- First, download SDK from https://github.com/intempt/intempt-intemptios. Then open the folder frameworks.

- Copy
Intempt.xcframework
into your project directory and then Drag & DropIntempt.xcramework
in your iOS app.


Intempt.xcframework
must set toEmbed & Sign
, Select your projectTraget -> Build Phase
expandEmbed Framework
and press+
addIntempt.xcframework


make sure in Target ->General->Framework, Libraries and Embded Contents
Embed & Sign
is selected.
If you have followed the above steps then you will be able to compile without any error.
Swift :
If Xcode 11.3 or above
Go to AppDelegate.swift file
import Intempt
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
///Your code here
//Initialize Intempt SDK
let intemptConfig = IntemptConfig(queueEnabled: true, withItemsInQueue: 7, withTimeBuffer: 15, withInitialDelay: 0.3, withInputTextCaptureDisabled: false)
IntemptTracker.tracking(withOrgId: "Your Organization Id", withProjectId: "Your project Id", withSourceId: "Your Source ID", withToken: "Your Token", withConfig: intemptConfig) { (status, result, error) in
if(status) {
if let dictResult = result as? [String: Any] {
print(dictResult)
}
}
else {
if let error = error {
print(error.localizedDescription)
}
}
}
return true
}
Access the ViewController.swift
file and then paste the copied source snippet into the viewDidLoad
function:
import Intempt
override func viewDidLoad() {
super.viewDidLoad()
//Initialize Intempt SDK
let intemptConfig = IntemptConfig(queueEnabled: true, withItemsInQueue: 7, withTimeBuffer: 15, withInitialDelay: 0.3, withInputTextCaptureDisabled: false)
IntemptTracker.tracking(withOrgId: "Your Organization Id", withProjectId: "Your Project Id", withSourceId: "Your Source ID", withToken: "Your Token", withConfig: intemptConfig) { (status, result, error) in
if(status) {
if let dictResult = result as? [String: Any] {
print(dictResult)
}
}
else {
if let error = error {
print(error.localizedDescription)
}
}
}
}
Objective C :
If you are using Xcode 11.3 or above, go to AppDelegate.m
file and paste the copied source snippet like the following:
@import Intempt;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Your code here
//initalize intempt SDK
IntemptConfig *intemptConfig = [[IntemptConfig alloc]initWithQueueEnabled:YES withItemsInQueue:7 withTimeBuffer:15 withInitialDelay:0.3 withInputTextCaptureDisabled:NO];
[IntemptTracker trackingWithOrgId:@"Your Organization Id" withProjectId:@"Your Project ID" withSourceId:@"Your Source ID" withToken:@"Your Token" withConfig:intemptConfig onCompletion:^(BOOL status, id result, NSError *error) {
}];
return YES;
}
Else you will have the ViewController.m
file and then paste the copied source snippet like the following:
@import Intempt
- (void)viewDidLoad {
[super viewDidLoad];
//initalize intempt SDK
IntemptConfig *intemptConfig = [[IntemptConfig alloc]initWithQueueEnabled:YES withItemsInQueue:7 withTimeBuffer:15 withInitialDelay:0.3 withInputTextCaptureDisabled:NO];
[IntemptTracker trackingWithOrgId:@"Your Organization Id" withProjectId:@"Your Project ID" withSourceId:@"Your Source ID" withToken:@"Your Token" withConfig:intemptConfig onCompletion:^(BOOL status, id result, NSError *error) {
}];
}
Get Organization ID, Project ID, API key and Source ID
Copy the Source ID, Project Id, Organization Id, and API Key in your Xcode app for the iOS SDK initialization.



Events Tracking
iOS SDK supports both auto-tracked and custom events. Auto-tracked events are automatically tracked when SDK is initialized; for custom events, you must write a custom event tracking code for your app.
These are the auto-tracked events supported by the SDK:
- Application Launch Tracking
- Screen tracking
- Interaction tracking
- Consent
- Location (depends on the application, if a user of the app has allowed location permission, then country and city-level location is tracked)
Get VisitorId from framework
let visitorId = IntemptClient.shared()?.getVisitorId()
Identifying visitors
Provide email or phone number.
IntemptTracker.identify("[email protected]", withProperties: nil) { (status, result, error) in
if(status) {
//Do something
}
}
You can record your app consent with builtin consent events.
Accept Consent
let config = IntemptConsentConfig(acceptWithValildUntil: "unlimited", userId: IntemptClient.shared().getVisitorId(), category:"offers")
config.message = "Yes email me offers, styles and promotions"
config.email = "\(emailTxt.text!)"
IntemptTracker.consent(config) { status, result, error in
}
for valid_until either 'unlimited' can be passed or future timestamp e.g. '1528114618'.
There are more options and alternate methods for accepting consent, please read the documentation or explore SDK.
Please read more about consent and available categories https://app.intempt.com/privacy/consents
Reject Consent
let config = IntemptConsentConfig(rejectWithUserId: IntemptClient.shared().getVisitorId()), category:"offers")
config.message = "Yes email me offers, styles and promotions"
config.email = "\(emailTxt.text!)"
IntemptTracker.consent(config) { status, result, error in
}
There are more options and alternate methods for rejecting consent, please read the documentation or explore SDK.
Please note that before you call consent, Intempt SDK should be initalized.
NOTE: It is necessary to set user identity before calling consent events. It can be done like this
IntemptTracker.identify("[email protected]", withProperties: nil) { (status, result, error) in
if(status) {
//Do something
}
}
Tracking custom events
Depending on the project requirements, you can create custom events to track any user action within the app.
To add a custom event, follow these steps:
- Select Organization -> Source -> Collections
- "Add collection" from the right panel to the existing collections list

- "Add field" to the added collection (add as many fields as required)

- Set field type (the data from the app needs to match - if an app has a string field and you create an integer field in the schema builder, the data will not be ingested).

Important
If you want to link the events with the visitor session, then add "sessionId" as the foreign key of the "Session" collection into that collection.
Every custom event schema must have timestamp of type long
and eventId of type string
fields; otherwise, your custom event will not be saved, and you will get a bad request error.
Be careful!
Please be careful when renaming - collection and field names
always start with lowercase.
The schema of the example event 'flight-booking' looks like this:
let arrayData = [{
"flightId" : 1,
"bookingDate" : "2020-05-26",
"bookingId": 2,
"bookingStatus" : "booked"
}]
IntemptTracker.track("flight-booking", withProperties: arrayData as? [Any]) { (status, result, error) in
if(status) {
if let dictResult = result as? [String: Any] {
print(dictResult)
}
}
else {
if let error = error {
print(error.localizedDescription)
}
}
}
}

Important
eventId, sessionId, timestamp values are automatically added with the payload - you don't need to include while sending custom event.
Disable Text Capture
Call this method if you want to disable capturing input texts like UItextField, UItextView. By default its false
. Secure entries are also excluded for privacy.
IntemptTracker.disableTextInput(true)
Disable auto-tracked events
Call this method if you want to disable default tracking. This action is persistent; once disabled, the developer must enable it again to track default events.
IntemptClient.disableTracking()
Enable auto-tracked events
Call this method if you disabled tracking and want to enable it again.
IntemptClient.enableTracking()
Enable event logging
Call this method if you want to see the logs of all generated events, and errors for debugging purposes. By default, logging is disabled
IntemptClient.enableLogging()
Disable event logging
Call this method if you don't want to see any log output in the console.
IntemptClient.disableLogging()
Reset tracking session
Call this method to reset the tracking session. It will end the previous session and start a new session.
IntemptClient.shared().validateTrackingSession()
End tracking session
Call this method to end the tracking session.
IntemptClient.shared().endTrackingSession()
Start tracking session
Call this method in order to start a new tracking session.
IntemptClient.shared().startTrackingSession()
Tracking iOS14 & later and ATT Security Framework
Our iOS SDK does not require enabling IDFA because data is not forwarded to any external services or linked with third-party data. Analytics is captured to observe the user behavior and visualizations of app usage and improve user experience based on their activities. So with the default configuration, there is no need to add Apple Tracking Transparency permission in info.plist and ask for user consent. However, if your app has other external integrations or you have implemented custom events that track users or share user data with 3rd party services, then you have to include it.
Privacy - Location Permission
iOS SDK itself doesn't ask the user for location permission and doesn't fetch the user's location. However, the SDK has reference to CoreLocations framework, and if the app (where SDK is integrated) has obtained user consent for Location then SDK will track the user's location of the city, region, and country.
As the SDK has reference to the CoreLocations framework so it is required to add Privacy - Location
in info.plist with explaining the purpose of location fetch and usage.
Go to the app's Info.plist file and add the privacy keys.
Key | Value |
---|---|
Privacy - Location Always Usage Description | Location used to track where you are and showing most relevant content to you. |
Privacy - Location When In Use Usage Description | Location used to track where you are and showing most relevant content to you |
Privacy - Location Always and When In Use Usage Description | Location used to track where you are and showing most relevant content to you |
An Experiment is essentially just changes. With the A/B Testing so you can run experiments to test ideas and see the impact they have on key metrics. Want to see if your new checkout screen is actually driving more purchases? Want to try out a new ad format to see if it increases revenue? Use Experiments with A/B Testing to get insight into which changes are helping you achieve your goals.
Required:
1: a key from API keys menu; example 36e82934fff945278268971cd3b4d32e.8911b9bc1e3f469a863a7e047cd51fdc
2: an existing experiment; example id: 99afebd5-885e-48de-9789-704f7ff12437
3: organization id and project id
4: add our sdk
Before you go for coding, you need to setup your experiment with the variants. It can be done with experiment builder https://help.intempt.com/docs/experiment-builder. E.g if you want to experiment different profiles for different users, You can add variants as simple key value pair each.
Instantiate the experiments API
First of all instantiate the experiments SDK.
let experiment = IntemptExperiments.sharedClient()
experiment?.initWithOrgId(<YOUR_INTEMPT_ORG_ID>, withProjectId: <YOUR_INTEMPT_PROJECT_ID>, withSourceId: <YOUR_INTEMPT_SOURCE_ID>, withToken: IntemptOptions.token, onCompletion: { status, result, error in
})
Choose variant with the user identifier
Pass a user identifier (email, phone, any unique value which you has set as identity) to below method. It will return the response in the completion handler. 'result' is the key value dictionary which can be wraped to NSDictioary or as? [String:Any].
let experiment = IntemptExperiments.sharedClient()
experiment?.chooseVariant(withUserIdentifier: <User Identifier>, experimentId: <Experiment ID>, device: "MOBILE", uri: "", onCompletion: { status, result, error in
})
Based on experiment setup, above method will return result or error. E.g in example of profile case below will be response. In the application/game set profie based on the resutl.
{
"profile_shape": "circle"
}
Choose variant with the profile identifier
Pass a profile identifier (email, phone, any unique value which you has set as identity) to below method. It will return the response in the completion handler. 'result' is the key value dictionary which can be wraped to NSDictioary or as? [String:Any].
let experiment = IntemptExperiments.sharedClient()
experiment?.chooseVariant(withProfileIdentifier: IntemptClient.shared().getVisitorId(), experimentId: <Experiment ID>,device: nil, uri: nil, onCompletion: { status, result, error in
})
Based on experiment setup, above method will return result or error. E.g in example of profile case below will be response. In the application/game set profie based on the resutl.
{
"profile_shape": "round"
}
if error code is 204, it means no variant available; Possible reasons: 1. the user is not in the target audiance 2. not yet active, out of schedule
NOTE: It is necessary to set user identity before calling experiements. It can be done like this. If you are going to set identity and call experiement method simultaneously, then first identitty should be set and in completion handler experiment method call should be made. Its because if you call experiment before the identity, experiment will return 204 error code.
IntemptTracker.identify("[email protected]", withProperties: nil) { (status, result, error) in
if(status) {
//Do something
}
}
Troubleshooting
Building failed because the linked and embedded framework 'Intempt.xcframework' was built for iOS + iOS Simulator
You may face this error if you have used the Intempt universal framework. To resolve this, please follow the below steps.
Select your project Target -> Build Settings
and search Validate Workspace
Set Value to NO; if its already NO, then set it to YES once and then set it again to NO. This is a workaround as sometimes xcode doesn't understand, so toggling the value between YES/NO solves it.

Apple App Store uploading issue of invalid unsupported architectures
If you have added intempt.framework
as universal
then, when submitting to the Apple App Store, it will show the error of simulator architectures. To resolve this issue, please select your project Target -> Build Phase
and select +
sign and add New Run Script Phase
. It will add an empty script below.
Expand it and put the below script, as shown in the screenshot below
# skip if we run in debug
if [ "$CONFIGURATION" == "Debug" ]; then
echo "Skip frameworks cleaning in debug version"
exit 0
fi
APP_PATH="${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/"
# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
EXTRACTED_ARCHS=()
for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done
echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"
echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
done

dyld: Library not loaded: @rpath/Intempt.framework/Intempt
Intempt.xcframework
must set to Embed & Sign

Intempt no such module found
Sometimes xcode behaves strangely and does not link properly, so first delete Intempt.xcframework
from your project, clean build
and delete Drived Data
then again, follow the steps to add the framework:
Copy Intempt.xcramework
into your project directory and then Drag & Drop Intempt.xcframework
in your iOS app.
Intempt.xcframework
must set to Embed & Sign
, Select your project Traget -> Build Phase
expand Embed Framework
and press +
add Intempt.xcframework


make sure in Target ->General->Framework, Libraries and Embded Contents
Embed & Sign
is selected.

No data visible on app.intempt.com console dashboard
For performance and efficiency purposes, the iOS SDK sends events as batch periodically; it may take a few seconds to appear your events on the console.
Events not sending, taking too long
if you see your events are captured and shown in debug mode but sent too late on the intempt server, then you need to check these configurations:
TimeBuffer
its value is in seconds - SDK sends data to the server periodically based on the value of this parameter.ItemsInQueue
its value is the number of events; if you set the value to 10, SDK will wait until 10 or more events are captured then it sends
Updated about 2 months ago