iOS Swift SDK
Version: 1.0.1
SDK Support and Compatibility
- The minimum iOS version supported is iOS 13
Install SDK
Integrate with Swift Package Manager
Swift Package manager repo - https://gitlab.com/zeta-crm/zetakit-swift
Steps to integrate with Swift Package Manager
- Enter our Swift Package Manager URL in Project Package Dependency
- Select Product ZetaCore and ZetaNotification Service to add to your target app
Integrate with Cocoapods
- Zeta Kit is available with two pods ZetaCore and ZetaNotificationService
- Add both of these pods to your target app in Podfile
-
target 'YourAppTarget' do pod 'ZetaCore' pod ZetaNotificationService end
Initialize SDK
import ZetaCore
//create a zeta config object, pass in below details
let zetaConfig = ZTConfig(
isLoggingEnabled: true,
clientSiteId: Environment.clientSiteId,
clientSecret: Environment.clientSecret,
region: .US,
appGroupId: "group.xyz.app",
optin: true
)
//call initialize method from shared instance of ZetaClient
ZetaClient.shared.initialize(config: zetaConfig)
ZTConfig parameters
isLoggingEnabled : set to true if we want logging enabled, logs will be present and can be viewed in console app (console app )
clientSecret: will be provided from ZMP portal post App registration
clientSiteId: will be provided from ZMP portal post App registration
region: Is the region your ZMP Account is configured for, it can be either US or EU, region cannot be interchanged for same ZMP Account
appGroupId: appGroupdId is used to track notification delivery status, please look into Push Notification for more details
optin: pass optin as true to continue SDK tracking and false to stop SDK from tracking
Fetch BSIN from SDK
BSIN uniquely identifies the user in ZMP
To get cached BSIN use ZetaClient.shared.getCachedBSIN()
To listen to lifecycle changes of BSIN, you can set delegate ZetaClient.shared.user?.setIdentityDelegate(delegate: self)
Notes
- Intialisation can be called on main thread as heavy work is scheduled in background thread
- clientSecret can be set separately via
ZetaClient.shared.setClientSecret(Environment.clientSecret)
Tracking Opt-in and Opt-out
When the application does not require the SDK to track events and user properties, it can utilize the opt-out feature. The application sends the opt-out configuration as part of its initialization or can call a separate opt-out method. If the application is using SDK-exposed methods for opting in or out, the same status should be sent through the SDK initialization configuration during the next launch. Otherwise, the configuration value may overwrite the opt-in/out status. Once the SDK receives the opt-out request, it will immediately stop all communication with the back end, and any data cached in the database will also be cleared. Until the application opts back in, the SDK will neither collect data from the application nor send data to the server. The application can opt in or out at any time during its lifecycle. After opting out, if the application opts back in, the SDK will consider it a fresh launch.
Tracking opt-out
Tracking of SDK can be disabled in two ways:
- Pass opt-in as false during initialization
//create a zeta config object, pass in below details let zetaConfig = ZTConfig( isLoggingEnabled: true, clientSiteId: Environment.clientSiteId, clientSecret: Environment.clientSecret, region: .US, appGroupId: "group.xyz.app", optin: false ) //call initialize method from shared instance of ZetaClient ZetaClient.shared.initialize(config: zetaConfig)
- Call stop tracking method
-
ZetaClient.shared.optOutFromTracking()
Tracking opt-in
To start tracking again you can pass optin as true during ZetaClient.shared.initialize or call ZetaClient.shared.optInForTracking(userId: userId)
You can pass current user id to help SDK fetch correct profile of the user from ZMP.
User Identification
Update User Properties
ZTUserBuilder is used to update multiple properties of user at once
//ZTUserBuilder provides client app to update user details in form of
//builder pattern
//This will automaticall call API in background to update user details
ZetaClient.shared.user.build { user in
user.userId = "userid"
user.firstName = "User1"
user.lastName = "last-name"
user.name = "name"
user.signedUpAt = "2024-09-17T05:54:58.000Z"
user.source = "source"
user.email = ZTUserEmail(email: "[email protected]")
user.phone = ZTUserPhone(phone: "1234")
}
// we can update contacts with additional properties if needed
ZetaClient.shared.user?.build({ user in
let ztAdditionalInfo = ZTContactAdditionalInfo()
ztAdditionalInfo.subscriptionStatus = ZTContactSubscriptionStatus.active
ztAdditionalInfo.inactivityReason = "reason"
ztAdditionalInfo.signedUpAt = "2024-09-17T05:54:58.000Z"
ztAdditionalInfo.lastOpened = "2024-09-17T05:54:58.000Z"
ztAdditionalInfo.doubleOptInStatus = "single"
ztAdditionalInfo.phoneType = "mobile"
ztAdditionalInfo.lastSent = "2024-09-17T05:54:58.000Z"
ztAdditionalInfo.lastOpened = "2024-09-17T05:54:58.000Z"
ztAdditionalInfo.lastClicked = "2024-09-17T05:54:58.000Z"
ztAdditionalInfo.properties = ["key": "value"]
user.email = ZTUserEmail(email: value, additionalInfo: ztAdditionalInfo)
})
Notes
- All date-time should be in ISO 8601 format in UTC
- preference of contact defaults to standard but other preferences can be added/customized within the settings menu in ZMP. Only those defined values can be passed in preference
- double_opt_in_status optional field to track double opt ins - default value is null, but will accept single or double values
- phone_type optional field for phone contact types. default value is null, accepts mobile or landline values
To pass device details and push token
//pass device token to SDK
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
ZetaClient.shared.user?.updateDeviceToken(token: deviceToken)
}
//pass IDFA
ZetaClient.shared.user?.updateIDFA(idfa)
//pass IDFV
ZetaClient.shared.user?.updateIDFV(idfv)
To clear session when user logs out
ZetaClient.shared.user?.clear()
Event Tracking
Auto Tracked Events
first_open
generate only once, when initialize is called for the first timeapp_active
generated when: the app enters active stateapp_inactive
generated when: the app enters inactive or background stateapp_terminate
generated when: the app is closed
Defined Events - pre defined event that can be called from App
screen
event can be called from App when navigating to a new screen- this screen name is cached in-memory in sdk, and will be used in subsequent events as a property
ZetaClient.shared.event?.trackScreenName(screen: "Events Screen")
location
event can be called by passing latitude and longitude in Double, with optional parameter if App is in foreground
ZetaClient.shared.event?.trackLocation(location: ZTLocation(
latitude: 12.933663251837913,
longitude: 77.62168405034637,
isForeground: true))
Custom Events
- We can send custom events with properties from app
- name is string type
- properties is a dictionary of type
[String: Any]
, properties should be valid JSON object or event will not be tracked, an error will be logged to system logger if logging is enabled
ZetaClient.shared.event?.send(
name: "EventTest",
properties: ["events-array": ["screen1", "screen2"],
"events-dict": ["screen": "events"]])
Push Notification Setup
To update device token
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
ZetaClient.shared.user?.updateDeviceToken(token: deviceToken)
}
To track Zeta notification clicked by user
- Call
ZetaClient.shared.push?.userNotificationCenter
from did receive response delegate function ofUNUserNotificationCenterDelegate
- This helps in tracking of user click events
- When it returns true than do not call completion handler as this is taken care by SDK
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
if ZetaClient.shared.push?.userNotificationCenter(center, didReceive: response, withCompletionHandler: completionHandler) == true {
//return without calling completion handler
return
}
completionHandler()
}
}
///
/// ```
/// userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void)
/// ```
/// call this func when same is called in UNUserNotificationCenterDelegate
/// This returns true if Zeta can handle notification, in that case client app does not need to call completion handler
/// ```
/// extension AppDelegate: UNUserNotificationCenterDelegate {
/// func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive /// response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
/// let info = response.notification.request.content.userInfo
/// if ZetaClient.shared.push?.userNotificationCenter(center, didReceive: response, withCompletionHandler: completionHandler) == true {
/// //return without calling completion handler
/// return
/// }
///
/// // handle not Zeta notification clicks
/// completionHandler()
/// }
/// }
/// ```
/// - Parameters:
/// - center: UNUserNotificationCenter
/// - response: UNNotificationResponse
/// - completionHandler: notification completion handler
/// - Returns: true if Zeta SDK can handle notification
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: (() -> Void)?) -> Bool
We can also track notification clicked by directly calling below function
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
ZetaClient.shared.push?.trackNotificationClicked(response: response)
completionHandler()
}
}
To get notified when zeta notification with deeplink is clicked
- Call
ZetaClient.shared.push?.userNotificationCenter
as highlighted above - Pass an instance that confirms to
ZTDeeplinkDelegate
func receivedDeeplink(deeplink: String, extraInfo: [String: String]?)
deeplink
param will be thedeeplink
in notification payload passed from Zeta CampaignextraInfo
param will be theextraInfo
in notification payload passed from Zeta Campaign
//set deeplink delegate after initializing Zeta SDK
ZetaClient.shared.push?.setDeeplinkDelegate(deeplinkDelegate: self)
// self in above needs to confirm to ZTDeeplinkDelegate
// you will get a callback with deeplink and any extra-info sent from ZMP Campaign
public protocol ZTDeeplinkDelegate: AnyObject {
func receivedDeeplink(deeplink: String, extraInfo: [String: String]?)
}
To get delivery status of notification
- Create notification service extension
- Import
ZetaNotificationService
from ZetaKit Package and add it to notification service extension target - use
ZTNotificationService
as suggested below in documentation - Create a app group id and pass it in
ZTNotificationService.trackNotificationDelivered(request, appGroupId: "group.com.abc.xyzproduct")
- you can use
ZTNotificationService.canHandle(request, withContentHandler: contentHandler)
to check ifZetaNotificationService
can handle notification
/**
# ZTNotificationService is used to provide rich notification extension
# There are 2 ways to use ZTNotificationService
#1 - Make ZTNotificationService to super class of NotificationService extension class
*/
import ZetaNotificationService
import UserNotifications
class NotificationService: ZTNotificationService {
}
// 2 - Use ZTNotificationService only for Zeta Notification Message
// and custom handling for other notifications
// To track notification delivery status, call trackNotificationDelivered with app group id,
// AppGroupId is used to store notification id in shared user default to be synced with server when app will be launched
import ZetaNotificationService
import UserNotifications
class NotificationService: UNNotificationServiceExtension {
public override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
if ZTNotificationService.canHandle(request, withContentHandler: contentHandler) {
ZTNotificationService.trackNotificationDelivered(request, appGroupId: "group.com.abc.xyzproduct")
ZTNotificationService.handleNotification(request, withContentHandler: contentHandler)
return
}
//custom handling
contentHandler(request.content)
}
}
Updated 14 days ago