Once signed up, set up an iOS source in the dashboard. You should be able to see a Write Key for this source, as shown below:
You also need a data plane URL. Refer to the Glossary for more information on the data plane URL and where to find it.
The Setup tab in the RudderStack dashboard (seen above) has an SDK installation snippet containing both the write key and the data plane URL. You can use it to integrate the iOS SDK into your project.
Finally, you need a Mac with the latest version of Xcode.
Installing the RudderStack iOS SDK
You can install the iOS SDK through Cocoapods and Carthage. The recommended and easiest way to add the SDK to your project is through Podfile. To do so, follow these steps:
Add the RudderStack SDK to your Podfile:
pod'Rudder'
Then, run the following command:
pod install
Add the RudderStack SDK to your Cartfile:
github"rudderlabs/rudder-sdk-ios"
Run the following command:
carthage update
Remember to include the following code in all .m and .h files or your .swift files where you want to refer to or use RudderStack SDK classes.
#import <Rudder/Rudder.h>
importRudder
RudderStack uses SQLite to store events locally before sending them to the RudderStack data plane. Making calls like SQLite.shutdown() which is not thread-safe might lead to unexpected crash.
Swift Package Manager
You can also install the iOS SDK through Swift Package Manager (SPM) via one of the following methods:
To add the RudderStack package in Xcode:
Go to File > Add Package.
In the search bar, enter the package repository: https://github.com/rudderlabs/rudder-sdk-ios.git.
In Dependency Rule, select Up to Next Major Version and enter the value as 1.8.0 as shown:
Select the project to which you want to add the package and click Add Package.
To leverage the RudderStack Swift package, include the following snippet in your project:
// swift-tools-version:5.5// The swift-tools-version declares the minimum version of Swift required to build this package.importPackageDescriptionletpackage=Package(name:"RudderStack",products:[// Products define the executables and libraries a package produces, and make them visible to other packages..library(name:"RudderStack",targets:["RudderStack"]),],dependencies:[// Dependencies declare other packages that this package depends on..package(url:"git@github.com:rudderlabs/rudder-sdk-ios.git",from:"1.8.0")],targets:[// Targets are the basic building blocks of a package. A target can define a module or a test suite.// Targets can depend on other targets in this package, and on products in packages this package depends on..target(name:"RudderStack",dependencies:[.product(name:"Rudder",package:"rudder-sdk-ios")]),.testTarget(name:"RudderStackTests",dependencies:["RudderStack"]),])
Initializing the SDK
Put this code in your AppDelegate.m file under the method didFinishLaunchingWithOptions:
You can disable these events using the withTrackLifecycleEvents method of RSConfigBuilder and passing false. However, it is highly recommended to keep them enabled.
RudderStack supports all major API calls across all iOS devices via the SDK. These include the track, identify, and screen calls.
OneTrust consent
The iOS SDK integrates with the OneTrust consent manager and lets you specify the user’s consent during initialization. For more information, refer to the OneTrust Consent Management for iOS guide.
Configuring the RudderStack client
You can configure your client based on the following parameters using RSConfigBuilder:
Parameter
Type
Description
Default Value
logLevel
int
Controls how much of the log you want to see from the SDK.
RSLogLevelNone
dataPlaneUrl
string
Your Data Plane URL.
https://hosted.rudderlabs.com
flushQueueSize
int
Number of events in a batch request sent to the server.
30
dbThresholdCount
int
Number of events to be saved in the SQLite database. Once the limit is reached, older events are deleted from the database.
10000
sleepTimeout
int
Minimum waiting time to flush the events to the server.
10 seconds
configRefreshInterval
int
Fetches the config from dashboard after the specified time.
2 hours
trackLifecycleEvents
boolean
Specify whether the SDK will capture application life cycle events automatically.
true
collectDeviceId
boolean
Determines if the SDK should automatically collect the device ID. If set to NO, it does not send context.device.id as a part of the event payload. See Disabling device ID collection for more information.
true
autoSessionTracking
boolean
Determines if the SDK automatically tracks the user sessions. Refer to Tracking user sessions for more information.
true
sessionTimeout
int
Maximum inactivity period before the session expires.
Specify whether the SDK should send the events for some time when the app is moved to the background. Currently it is available only for iOS & tvOS.
false
gzip
boolean
Gzips the event requests.
true
dbEncryption
object
Specify whether to encrypt/decrypt the database using your desired key. See Encrypting RudderStack databases for more information.
-
controlPlaneUrl
string
This parameter should be changed only if you are self-hosting the control plane. See our control plane lite documentation on GitHub for details. The iOS SDK will add /sourceConfig along with this URL to fetch the required configuration.
https://api.rudderlabs.com
Self-hosted control plane
If you are using a device mode destination like Adjust, Firebase, etc., the iOS SDK needs to fetch the required configuration from the control plane. If you are using the Control plane lite utility to host your own control plane, then follow the steps in this section and specify controlPlaneUrl in RSConfigBuilder that points to your hosted source configuration file.
Do not pass the controlPlaneUrl parameter during SDK initialization if you are using RudderStack Cloud. This parameter is supported only if you are using our open-source Control plane lite utility to self-host your control plane.
Gzipping requests
The Gzip feature is enabled by default in the iOS SDK.
The iOS SDK automatically gzips event requests. To disable this feature, set the Gzip parameter to NO while initializing the SDK:
Gzip requires rudder-serverv1.4 or higher. Otherwise, your events might fail.
Identify
The identify call lets you identify a visiting user and associate them to their actions. It also lets you record the traits about them like their name, email address, etc. Once you identify the user, the SDK persists all the user information and passes it on to the subsequent track or screen calls. To reset the user identification, you can use the reset method.
Note that:
For older SDK versions (< v1.19.0), the iOS SDK captures the device ID and uses that as anonymousId for identifying the user. This helps the SDK to track the users across the application installation.
According to the Apple documentation, if the device has multiple apps from the same vendors, all those apps will be assigned the same device ID. If all applications from a vendor are uninstalled, then on next install the app will be assigned a new device ID.
Starting from v1.19.0, the SDK uses a UUID as anonymousId instead of the device ID. If you are upgrading from a previous SDK version, see How RudderStack sets anonymous ID for more information on how the SDK collects and sets anonymousId.
If you are upgrading to the latest SDK from a previous version (< v1.19.0) and disabling device ID collection using withCollectDeviceId:NO:
Make sure your user transformations are not dependent on context.device.id as the SDK will not send this value in the event payload.
The context.device.id column in your warehouse destination will not be populated henceforth (it will still contain data populated by the previous SDK version).
How SDK sets anonymous ID
For direct/fresh SDK installation
For a fresh installation of the iOS SDK v1.19.0 and later, RudderStack uses UUID as anonymousId regardless of whether withCollectDeviceId is set to YES or NO.
For updating SDK from older version
If you are updating your iOS SDK from an older version (< v1.19.0), then:
RudderStack will continue to use the device ID as anonymousId - it will not break the existing SDK behavior until you set withCollectDeviceId to NO.
If you set withCollectDeviceId to NO, the SDK checks if the existing anonymousId is a device ID. If yes, it sets a new UUID as the anonymousId.
If you have used the putAnonymousId method to set your own anonymousId, then the SDK will not modify it even if you set withCollectDeviceId to NO.
Setting a custom ID
You can pass a custom ID along with the standard userId in your identify calls. RudderStack adds this value under context.externalId.
RudderStack supports passing externalId only in the identify events. You must not pass this ID in other API calls like track, page, etc.
The following snippet shows how to add an externalId to your identify event:
The track method accepts the following parameters:
Name
Data Type
Required
Description
eventName
NSString
Yes
Name of the event you want to track
properties
NSDictionary
No
Extra data properties you want to send along with the event
options
RudderOption
No
Extra event options
Screen
You can use the screen call to record whenever the user sees a screen on the mobile device. You can also send some extra properties along with this event.
Note that if automatic screen recording is enabled, RudderStack removes every instance of ViewController in the screen event.
For example, if automatic screen recording is enabled and you set the ViewController class name to HomeViewController, then the SDK sets the screen event name to Home.
For more details related to this implementation, refer to the iOS SDK repository.
Group
The group call associates a user to a specific organization. A sample group call for the API is below:
Alternatively, you can use the following method signature
Name
Data Type
Required
Description
groupId
String
Yes
An ID of the organization with which you want to associate your user
traits
NSDictionary
No
Any other property of the organization you want to pass along with the call
options
RudderOption
No
Event level options
RudderStack does not persist the traits for the group across the sessions.
Alias
The alias call associates the user with a new identification. A sample alias call for the API is below:
[[RSClientsharedInstance]alias:@"new_user_id"];
RSClient.sharedInstance()?.alias("new_user_id")
natively, you can use the following method signature
Name
Data Type
Required
Description
newId
String
Yes
The new userId you want to assign to the user
options
RudderOption
No
Event level option
RudderStack replaces the old userId with the newUserId and we persist that identification across the sessions.
Reset
You can use the reset method to clear the persisted user traits. It also resets the anonymousId with a new UUID if you call it with YES (for SDK v1.19.0 and later). To clear only user traits, call reset with NO.
In session tracking, calling the reset method clears the current sessionId and generates a new one.
A sample reset call is shown:
[[RSClientsharedInstance]reset:NO];
RSClient.sharedInstance()?.reset(false)
Encrypting RudderStack databases
This feature is available in the iOS SDK v1.20.0 and later.
The iOS SDK uses a SQLite database to store events before sending them to the RudderStack backend (data plane).
By default, SQLite databases created by RudderStack are not encrypted but they are still protected by iOS - similar to data in any iOS application. To add an extra level of security, you can use the SQLCipher extension to encrypt the database content and SQLite metadata.
Using CocoaPods
This feature is supported for SQLCipher v4.0 and later.
Step 1: Integrate SDK with SQLCipher
RudderDatabaseEncryption is available through CocoaPods. To install it, add the following line to your Podfile:
pod'RudderDatabaseEncryption','~> 1.0.0'
Run the pod install command.
Step 2: Import the iOS SDK
@importRudderDatabaseEncryption;
importRudderDatabaseEncryption
Step 3: Initialize the SDK
Place the following snippet in your app’s AppDelegate under didFinishLaunchingWithOptions method:
The standard SQLite library does not support encryption out of the box. Hence, you need to integrate a third-party option into your codebase. RSDatabaseProvider acts as a bridge between this third-party code and RudderStack, and uses SQLCipher for the implementation.
To integrate SQLCipher with your application, see the instructions for the community or commercial editions.
Once SQLCipher is correctly set up, add the below implementation of the RSDatabaseProvider protocol in your project.
Copy-paste the code exactly as given below and change the class names as per your requirement.
The iOS SDK is now configured to support database encryption.
After you encrypt the database:
If no key is provided, then the SDK deletes the current database with unsent events and creates a new unencrypted database instead.
If a wrong key is provided, then the SDK deletes the current database with unsent events and creates a new encrypted database with the given key.
The SDK does not store the key, so it cannot determine whether the entered key is right or wrong. Hence, if the key cannot decrypt the database, the SDK assumes it to be incorrect and deletes the old events and database.
Instructions for linking issues
The Cocoapod RudderDatabaseEncryption uses the SQLCipher Cocoapod under the hood to perform encryption. This Cocoapod requires the removal of any references to the standard SQLite system library for it to function as expected.
If you set up a project to inadvertently include a linking reference against the standard SQLite library before SQLCipher, it is possible that the application builds and runs correctly but does not use SQLCipher for encryption. This is not a problem for most projects but there are certain cases where unintentional SQLite linking can occur.
One such example is when using CocoaPods or some other sub-project that declares a dependency on the SQLite3 library. In this case, adding a pod to a project can silently modify the project settings in such a way that SQLCipher is not properly linked.
You can identify and fix the above linking issue during the development stage by looking for the below error log from the SDK:
RSDBPersistentManager: createDB: Cannot encrypt the Database as SQLCipher wasn't linked correctly.
To fix the linking issue, add a linker flag to your project settings to ensure that the Xcode links SQLCipher before SQLite. Follow these steps:
Open the project-level build settings. These are the global project settings, not for the individual application target.
Locate the Other Linker Flags setting and add one of the following commands depending on how you are integrating SQLCipher into the app.
If you are not adding SQLCipher into the app on your own and only using RudderDatabaseEncryption, then see only the points 3 and 4 in the below table - depending on whether you are using use_frameworks! in your app’s ios/Podfile.
Scenario
Command
Notes
When using SQLCipher commercial edition static libraries
Adjust according to the path to the libsqlcipher-ios.a you received as a part of the package.
When using the sqlcipher.xcodeproj included in the SQLCipher Git repository
$(BUILT_PRODUCTS_DIR)/libsqlcipher.a
-
When using the SQLCipher CocoaPod with the use_frameworks Podfile setting enabled
-framework SQLCipher
-
When using the SQLCipher CocoaPod without the use_frameworks Podfile setting enabled
-lSQLCipher
-
Once the linker flag is added to the project-level build settings, you should see something like the below image:
After adding the linker flag to your project-level build settings, check the target-level build settings to ensure SQLCipher is shown first, as seen below:
Enabling/disabling user tracking via the optOut API (GDPR)
RudderStack gives users (e.g., an EU user) the ability to opt out of tracking any user activity until the user gives their consent. You can do this by leveraging RudderStack’s optOut API.
The optOut API takes YES or NO as a Boolean value to enable or disable tracking user activities. This flag persists across device reboots.
The following snippet highlights the use of the optOut API to disable user tracking:
[[RSClientsharedInstance]optOut:YES];
RSClient.sharedInstance()?.optOut(true)
the user grants their consent, you can enable user tracking once again by using the optOut API with NO or false as a parameter sent to it:
[[RSClientsharedInstance]optOut:NO];
RSClient.sharedInstance()?.optOut(false)
The optOut API is available in the RudderStack iOS SDK starting from version 1.0.24.
Setting custom context
You can set custom contextual information in the iOS SDK by using either of the following ways:
During SDK initialization
You can set custom context during SDK initialization as follows:
This feature is available in the iOS SDK v1.26.0 and later.
The iOS SDK persists the contextual information set during SDK initialization for subsequent events but not across sessions.
Calling the reset method clears all the contextual information set during SDK initialization.
The contextual information passed at the event level gets precedence over the context set during SDK initialization.
Using putCustomContext method
You can use the putCustomContext method on an instance of RSOption to set custom contextual information as a nested object within context while sending the events.
An example of setting custom context using an instance of RSOption and passing it in a track call:
The SDK does not persist the contextual information set using putCustomContext for subsequent events. Hence, you must use this method every time you want to set custom context for an event.
Setting the device token
You can pass your device-token for Push Notifications to be passed to the destinations which support Push Notification. We set the token under context.device.token.
Follow the instructions below:
[RSClientputDeviceToken:@"your_device_token"];
RSClient.putDeviceToken("your_device_token")
Setting the advertisement ID
To set the advertisement ID, you can use the static method putAdvertisingId and call it before or after the SDK initialization:
[RSClientputAdvertisingId:@"sampleAdvertId"];
RSClient.putAdvertisingId("advertId")
Once set, the advertisement ID persists and gets attached to all the events until it is cleared using the clearAdvertisingId method.
To clear the advertisement ID, use the clearAdvertisingId method:
[[RSClientsharedInstance]clearAdvertisingId];
RSClient.sharedInstance()?.clearAdvertisingId()
The clearAdvertisingId method is not static and hence can be called only after the SDK initialization.
-(BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions{// Override point for customization after application launch.
RSConfigBuilder*builder=[[RSConfigBuilderalloc]init];[builderwithDataPlaneUrl:DATA_PLANE_URL];[RSClientgetInstance:WRITE_KEYconfig:[builderbuild]];[[[RSClientsharedInstance]context]putAppTrackingConsent:RSATTAuthorize];returnYES;}
You can pass the following options to the putAppTrackingConsent method:
RSATTNotDetermined
RSATTRestricted
RSATTDenied
RSATTAuthorize
Filtering events
When sending events to a destination via device mode, you can explicitly specify which events should be discarded or allowed to flow through - by allowlisting or denylisting them.
Enabling/disabling events for specific destinations
The RudderStack iOS SDK allows you to enable or disable event flow to a specific destination or all destinations to which the source is connected. You can specify these destinations by creating a RSOption object as shown:
RSOption*option=[[RSOptionalloc]init];//default value for `All` is true
[optionputIntegration:@"All"isEnabled:YES];// specifying destination by its display name
[optionputIntegration:@"Amplitude"isEnabled:YES];[optionputIntegration:@"<destination display name>"isEnabled:<BOOL>];// specifying destination by its Factory instance
[optionputIntegrationWithFactory:[RudderMoengageFactoryinstance]isEnabled:NO];[optionputIntegrationWithFactory:[<RudderIntegrationFactory>instance]isEnabled:<BOOL>];
letoption:RSOption=RSOption();//default value for `All` is trueoption.putIntegration("All",isEnabled:true)// specifying destination by its display nameoption.putIntegration("Amplitude",isEnabled:true)option.putIntegration(<DESTINATIONDISPLAYNAME>,isEnabled:<BOOL>)// specifying destination by its Factory instanceoption.putIntegration(with:RudderMoengageFactory.instance(),isEnabled:true);option.putIntegration(with:<RudderIntegrationFactory>.instance(),isEnabled:<BOOL>);
The keyword All in the above snippet represents all destinations the source is connected to. Its value is set to true by default.
Make sure the destination display name you pass while specifying the custom destinations should exactly match the destination name as shown here.
You can pass the destination(s) specified in the above snippet to the SDK in two ways:
1. Passing destinations while initializing the SDK
This is helpful when you want to enable/disable sending the events across all event calls made using the SDK to the specified destinations.
RSConfigBuilder*builder=[[RSConfigBuilderalloc]init];[builderwithDataPlaneUrl:DATA_PLANE_URL];[builderwithLoglevel:RSLogLevelDebug];[builderwithTrackLifecycleEvens:YES];[builderwithRecordScreenViews:YES;[RSClientgetInstance:WRITE_KEYconfig:[builderbuild]options:option];// passing the rudderoption object containing the list of destinations you specified
letbuilder:RSConfigBuilder=RSConfigBuilder().withLoglevel(RSLogLevelDebug).withDataPlaneUrl(DATA_PLANE_URL).withTrackLifecycleEvens(true).withRecordScreenViews(true)RSClient.getInstance(WRITE_KEY,config:builder.build(),options:option)// passing the rudderoption object containing the list of destination(s) you specified
2. Passing destinations while making event calls
This approach is helpful when you want to enable/disable sending only a particular event to the specified destination(s) or if you want to override the specified destinations passed with the SDK initialization for a particular event.
[[RSClientsharedInstance]track:@"simple_track_with_props"properties:@{@"key_1":@"value_1",@"key_2":@"value_2"}options:option];// passing the rudderoption object containing the list of destination(s) you specified
letrudder:RSClient?=RSClient.sharedInstance()rudder?.track("track_with_props",properties:["key_1":"value_1","key_2":"value_2",],options:option)// passing the rudderoption object containing the list of destination(s) you specified
If you specify the destinations both while initializing the SDK as well as making an event call, then the destinations specified at the event level only will be considered.
Tracking user sessions
The iOS SDK supports session tracking starting v1.7.0.
By default, the iOS SDK automatically tracks the user sessions. This means that RudderStack automatically determines the start and end of a user session depending on the inactivity time configured in the SDK (default time is 5 minutes).
To automatically track sessions in the iOS SDK, withTrackLifecycleEvents should also be set to true. This is because RudderStack considers the Application Opened, Application Installed, or Application Updated events as the start of a new session.
RSConfigBuilder*builder=[[RSConfigBuilderalloc]init];[builderwithDataPlaneUrl:DATA_PLANE_URL];[builderwithAutoSessionTracking:YES];// Set to No to disable automatic session tracking
[builderwithSessionTimeoutMillis:(5*60*1000)];[RSClientgetInstance:WRITE_KEYconfig:[builderbuild]];
letbuilder:RSConfigBuilder=RSConfigBuilder().withDataPlaneUrl(DATA_PLANE_URL).withAutoSessionTracking(true)// Set to false to disable automatic session tracking.withSessionTimeoutMillis(5*60*1000)RSClient.getInstance(WRITE_KEY,config:builder.build())
To disable automatic session tracking, set withAutoSessionTracking to false.
For more information on the user sessions and how to track them using the iOS SDK, refer to the Session Tracking guide.
Tracking deep links
Starting from version 1.27.0, the iOS SDK supports tracking deep links. Deep links provide direct access to specific content and features within your app. See the Apple documentation for more information on configuring deep links in your iOS app.
After completing the setup, call the SDK’s deep link API from either your AppDelegate or SceneDelegate depending on the below scenarios:
When you only have a URL to pass:
[[RSClientsharedInstance]openURL:url];
RSClient.sharedInstance()?.open(url)
When you have URL and custom properties to pass along with the deep link event:
The deep link method accepts the below parameters:
Name
Data type
Description
url Required
NSURL
Represents a Uniform Resource Locator used to identify a location on the network and a mechanism for retrieving it. URLs are used to open web pages, access APIs, and deep link into specific parts of the app.
For example, com.ruddertestappswift://.
options
NSDictionary
Additional data properties to send along with the deep link event.
The Deep Link Opened event schema is shown below:
Property name
Data type
Description
url
String
The url parameter described above. It is a string of characters used to identify a location on the network and a mechanism for retrieving it.
For example, com.ruddertestappswift://.
The iOS SDK also adds the query parameters as the deep link event properties.
Adding callback support for mobile device mode integrations
Note the following:
This feature is supported in the iOS SDK v1.24.0 and later.
Currently, the callback support is only available for the Braze mobile device mode integration. It will be implemented for other integrations over time.
The iOS SDK supports a onIntegrationReady callback functionality that returns the instance of the mobile device mode integration after the destination SDK is initialized.
You can use this feature to obtain the Braze SDK instance and use it for registering to Braze’s in-app messaging feature.
Starting from iOS SDK v1.25.0, you can send the context.device.model in a more detailed format to your downstream destinations. The SDK sends the device model information in the standard Apple format like iPhone 13,1 instead of the earlier format iPhone. Here, iPhone 13,1 corresponds to the human-readable format iPhone 12 Mini.
While most destinations are able to recognize the standard Apple format, there might some cases where the destination is unable to comprehend it. For such cases, you can use the Localize Apple Device Model transformation to convert the standard Apple device model into a human-readable format.
You can easily develop a device mode destination if RudderStack doesn’t support it already. Follow these steps:
Create a CustomIntegration class by extending RSIntegration.
#import <Rudder/Rudder.h>
@interfaceCustomIntegration : NSObject<RSIntegration>@property(nonatomic,strong)NSDictionary*config;@property(nonatomic,strong)RSClient*client;-(instancetype)initWithConfig:(NSDictionary*)configwithAnalytics:(RSClient*)client;@end@implementationCustomIntegration-(instancetype)initWithConfig:(NSDictionary*)configwithAnalytics:(RSClient*)client{if(self==[superinit]){}returnself;}-(void)processRuderEvent:(nonnullRSMessage*)message{NSString*type=message.type;if([typeisEqualToString:@"identify"]){// Do something
}elseif([typeisEqualToString:@"track"]){// Do something
}elseif([typeisEqualToString:@"screen"]){// Do something
}else{[RSLoggerlogWarn:@"MessageType is not supported"];}}-(void)dump:(nonnullRSMessage*)message{[selfprocessRuderEvent:message];}-(void)reset{}-(void)flush{}@end
classCustomIntegration:NSObject,RSIntegration{letconfig:[AnyHashable:Any]letanalytics:RSClientinit(config:[AnyHashable:Any],analytics:RSClient){self.config=configself.analytics=analytics}funcdump(_message:RSMessage){processRudderEvent(message)}funcprocessRudderEvent(_message:RSMessage){lettype=message.typeswitchtype{case"identify"://Do somethingbreakcase"track"://Do somethingbreakcase"screen"://Do somethingbreakdefault:RSLogger.logWarn("MessageType is not supported")}}funcreset(){}funcflush(){}}
RudderStack’s iOS SDK dumps every event it receives to the dump() method of the CustomFIntegration class. From here, you can process the event and hand it over to the native SDK of the device mode destination.
The SDK also triggers the reset() method of the CustomFactory class on every reset() call made via the SDK. You can use this to handle the destination-specific reset logic.
Make sure you do not duplicate the value of KEY present inside CustomFactory, across multiple CustomFactory that you develop.
Flushing events using flush API
The iOS SDK supports the flush() API. RudderStack retrieves all messages present in the database, divides them into individual batches based on the specified queue size, and flushes them to the RudderStack server/backend.
For example, if the flushQueueSize is 30 and there are 180 events in the database when the flush() API is called, the SDK will retrieve all those events and divide them into batches of 30 messages each, that is, into 6 batches.
If a batch fails for some reason, RudderStack drops the remaining batches to maintain the sequence of the messages. A batch is considered as failed if it isn’t sent to the RudderStack server after 3 retries.
In device mode, the flush() API also calls the destination SDK’s flush() API (if applicable).
For every flush() call made via the iOS SDK, the flush() method of the CustomFactory class is also triggered, which can be used to handle the destination-specific reset logic. You can make a flush call using the SDK as shown:
[[RSClientsharedInstance]flush];
RSClient.sharedInstance()?.flush()
Debugging
If you run into any issues regarding the RudderStack iOS SDK, you can turn on the VERBOSE or DEBUG logging to find out what the issue is. To turn on the logging, change your RudderClient initialization to the following:
Google Chromecast is a device that plugs into your TV or monitor with an HDMI port, and can be used to stream content from your phone or computer.
RudderStack supports integrating the iOS SDK with your Cast app. Follow these instructions to build your iOS sender app. Then, add the iOS SDK to it. Follow the Google Cast developer guide for more details.
Privacy manifest
Your apps and third-party SDKs (usually distributed as Swift packages, XCFrameworks, or framework bundles) contain a privacy manifest file named PrivacyInfo.xcprivacy. It records the data collected by your app/third-party SDK and the associated required reason API.
You need to record the reasons in your privacy manifest for each data type your app/SDK collects along with the category of required reasons API that it uses.
Starting Spring 2024, you are required to include an approved reason in your app’s privacy manifest that accurately reflects how your app uses the API.
This is a mandatory requirement to upload a new app/app update to the App Store Connect. For more information, see this Apple update.
Privacy Accessed API Types
NSPrivacyAccessedAPITypes is an array of dictionaries describing the API types your app/third-party SDK accesses that have been designated as APIs that require reasons to access.
The RudderStack iOS SDK only uses the userDefaults API to store user and context information and it is declared in the privacy manifest in the iOS SDK repository.
Privacy tracking domains
NSPrivacyTrackingDomains is an array of strings listing the internet domains that your app/third-party SDK connects to for tracking purposes. If the user has not granted the tracking permissions through the App Tracking Transparency framework, the network requests to these domains fail and you get an error on your app.
If your application utilizes data for tracking users as outlined by Apple, it is important to seek the user’s consent first. Also, make sure to include the following domain in your app’s privacy manifest under the purpose NSPrivacyTrackingDomains:
rudderstack.com/
Privacy Nutrition Label Types
NSPrivacyCollectedDataTypes is an array of dictionaries that describe the data types your app/third-party SDK collects.
The RudderStack iOS SDK includes an array of Privacy Nutrition Label Types for the following automatically-collected fields:
I’m facing issues building with Carthage on XCode 12. What should I do?
If you’re facing an issue with Carthage and XCode 12, you can follow this workaround suggested by the Carthage team.
Does the SDK support tvOS ?
As of version 1.1.0, the iOS SDK supports the tvOS platform.
Does the SDK support watchOS ?
As of version 1.3.0, the iOS SDK supports the watchOS platform.
How do I migrate from v1.0.2?
Update the usage of the following classes as per the table below:
Previous Name
Updated Name
RudderClient
RSClient
RudderConfig
RSConfig
RudderConfigBuilder
RSConfigBuilder
RudderLogLevelDebug
RSLogLevelDebug Other LogLevels follow the same nomenclature.
How do I ensure the events tracked just before closing/backgrounding the app are sent immediately and not on the next app launch?
To ensure that the events tracked just before closing/backgrounding the app are sent to RudderStack immediately, you can set withEnableBackgroundMode to YES while creating the RSConfigBuilder object as shown below:
Currently, this feature is available only for iOS & tvOS platforms.
By doing so, your app requests iOS for some additional background run time to run the app, which in turn allows the SDK to immediately send the events tracked just before the app is closed/backgrounded, instead of waiting till the next app launch.
This SDK feature relies on the background mode capability offered by the iOS. There is no set number on the background run time the apps get, as it is completely abstracted by iOS. For more information, refer to this guide.
How can I get the user traits after making the identify call?
You can get the user traits after making an identify call in the following way:
How does the SDK handle different client/server errors?
In case of client-side errors, e.g. if the source write key passed to the SDK is incorrect, RudderStack gives you a 400 Bad Request response and aborts the operation immediately. For other types of network errors (e.g. Invalid Data Plane URL), the SDK tries to flush the events to RudderStack in an incremental manner (every 1 second, 2 seconds, 3 seconds, and so on).
Why is there a larger difference between timestamp and received_at for iOS events vs. Android events?
This scenario is most likely caused by the default behavior of iOS apps staying open in the background for a shorter period of time after a user closes them.
When a user closes an iOS or Android app, events will still continue to be sent from the queue until the app closes in the background as well. Any events still in the queue will remain there until the user reopens the app. Due to this lag, there are some scenarios where there can be significant differences between timestamp (when the event was created) and received_at (when RudderStack actually receives the events).
For Android apps, events can be sent from the background after apps close for a longer period of time than iOS apps, therefore, more of the events coming from the Android SDK have closer timestamp and received_at times.
Does RudderStack integrate with SKAdNetwork?
RudderStack does not integrate with SKAdNetwork. However, SKAdNetwork can be directly integrated into an iOS application alongside RudderStack.
Can I disable event tracking until the user gives their consent?
Yes, you can.
RudderStack gives you the ability to disable tracking any user activity until the user gives their consent, by leveraging the optOut API. This is required in cases where your app is audience-dependent (e.g. minors) or where you’re using the app to track the user events (e.g. EU users) to meet the data protection and privacy regulations.
The optOut API takes true / false (in case of Swift) or YES / NO (in case of Objective-C) as a value to enable or disable tracking user activities. So, to disable user tracking, you can use the optOut API as shown:
[[RSClientsharedInstance]optOut:YES];
RSClient.sharedInstance()?.optOut(true)
the user gives their consent, you can enable user tracking again:
Can I remove encryption from an encrypted database?
Yes, you can. When passing the RSDBEncryption object, configure the object with the encryption key and set enable to false. It will remove the encryption from the encrypted database.
How does the iOS SDK handle events larger than 32KB?
The iOS SDK drops any events greater than 32KB.
How long does the iOS SDK retain the events in the database? Do the events expire and get removed after a certain period?
The iOS SDK stores all the events in the database before flushing them to the RudderStack backend. The SDK never deletes events based on the time period, that is, how long the events are in the database.
However, note that the SDK removes the older events once the database threshold (dbThresholdCount, 10000 events by default) is reached.
Why am I getting a warning in Points of Interest instruments?
You may get a warning in your Points of Interest instrument if rudderstack.com/ is not listed in your app’s NSPrivacyTrackingDomain key in any privacy manifest. It may be following users across multiple apps and websites to create user profiles for apps that contact this domain.
To resolve this issue, make sure to:
Seek user consent, especially if your app utilizes data for tracking users as outlined by Apple.
Include the rudderstack.com/ domain in your app’s privacy manifest under the purpose NSPrivacyTrackingDomains.
This site uses cookies to improve your experience while you navigate through the website. Out of
these
cookies, the cookies that are categorized as necessary are stored on your browser as they are as
essential
for the working of basic functionalities of the website. We also use third-party cookies that
help
us
analyze and understand how you use this website. These cookies will be stored in your browser
only
with
your
consent. You also have the option to opt-out of these cookies. But opting out of some of these
cookies
may
have an effect on your browsing experience.
Necessary
Always Enabled
Necessary cookies are absolutely essential for the website to function properly. This
category only includes cookies that ensures basic functionalities and security
features of the website. These cookies do not store any personal information.
This site uses cookies to improve your experience. If you want to
learn more about cookies and why we use them, visit our cookie
policy. We'll assume you're ok with this, but you can opt-out if you wish Cookie Settings.