This guide outlines how developers can migrate from older versions of our SDK to newer ones.
- We have removed the PascalCase names in the
Event.EventName
enum, leaving only the camelCase names. You will need to remove any references to the old PascalCase names. See Migrating to v3.3.0 below for more details. - We have removed the
.OpenedPush
case (there is no camelCase replacement), as this is intended for internal use only. You will need to remove any references to the.OpenedPush
case.
We've updated the case names in the Event.EventName
enum from PascalCase to camelCase, to be consistent with Swift naming conventions.
The old case PascalCase names are currently still in place and have the same functionality as the new camelCase names, but will be removed in a future release. Any direct references to the old PascalCase names will now show a deprecation warning, along with an option to "fix" the name by replacing it with the camelCase version.
This update is non-breaking for most use-cases, but any consumers who are switch
ing over the Event.EventName
enum will need to make minor changes. There are two scenarios:
-
If the existing
switch
statement does not include adefault
case, the compiler will throw a "Switch must be exhaustive" error. You may click "Fix" to have Xcode automatically add the missing cases, but we recommend that you add the new camelCase names alongside the old ones in your branching logic. For example:switch event { case .OpenedPush: <...> case .OpenedAppMetric, .openedAppMetric: <...> case .ViewedProductMetric, .viewedProductMetric: <...> case .AddedToCartMetric, .addedToCartMetric: <...> case .StartedCheckoutMetric, .startedCheckoutMetric: <...> case .CustomEvent(let string), .customEvent(let string): <...> }
-
If the existing
switch
statement does include adefault
case, any logic touching the new camelCase names will be branched into thedefault
case unless theswitch
statement is updated. We recommend updating theswitch
statement as described in (1) above to address this situation.
Deprecated event type enum cases have been removed. The reasoning is explained below, see Migrating to v2.4.0 for details and code samples.
It was recently discovered that the Swift SDK was using legacy event names for some common events, like "Viewed Product" and some events that are associated with server actions, like "Ordered Product." As a result, if your account used these enum cases, they were being logged with names like "$viewed_product" in contrast to website generated events which are logged as "Viewed Product."
In order to bring the Swift SDK in line with Klaviyo's other integrations, we've deprecated the incorrect enum cases and introduced new cases to correct spellings where appropriate. The deprecated cases will be removed in the next major release.
// Old code: using one of the legacy enum cases
let event = Event(name: .ViewedProduct)
// New code: update to new case with -Metric suffix
let event = Event(name: .ViewedProductMetric)
If you are using any of the old names and need to continue using them, you can use the custom enum e.g.
let event = Event(name: .Custom("$viewed_product"))
Version 2.0.0 of the iOS SDK updates the API to take advantage of modern swift language features to make it easier to integrate
into your Swift applications. This means our old Klaviyo
has been deprecated and it will be completely removed in a future SDK version.
The newer API no longer requires use of the singleton pattern. So any code that references the shared instance like this:
Klaviyo.sharedInstance
Can be converted to look like this:
KlaviyoSDK()
Our previous SDK used dictionary as input to track a profile like so:
let klaviyo = Klaviyo.sharedInstance
let personInfoDictionary : NSMutableDictionary = NSMutableDictionary()
personInfoDictionary[klaviyo.KLPersonEmailDictKey] = "[email protected]"
personInfoDictionary[klaviyo.KLPersonZipDictKey] = "02215"
klaviyo.trackPersonWithInfo(personDictionary: personInfoDictionary)
Instead now the same thing can be acheived as follows:
let profile = Profile(email: "[email protected]", location: .init(zip: "02215"))
KlaviyoSDK().set(profile: profile)
Tracking an event is similar to before except again we are using stronger types. In our previous API you did this:
let klaviyo = Klaviyo.sharedInstance
let customerDictionary : NSMutableDictionary = NSMutableDictionary()
customerDictionary[klaviyo.KLPersonEmailDictKey] = "[email protected]"
customerDictionary[klaviyo.KLPersonFirstNameDictKey] = "John"
customerDictionary[klaviyo.KLPersonLastNameDictKey] = "Smith"
let propertiesDictionary : NSMutableDictionary = NSMutableDictionary()
propertiesDictionary["Total Price"] = 10.99
propertiesDictionary["Items Purchased"] = ["Milk","Cheese", "Yogurt"]
Klaviyo.sharedInstance.trackEvent(
eventName: "Completed Checkout",
customerProperties: customerDictionary,
properties: propertiesDictionary
)
This now becomes:
let klaviyo = KlaviyoSDK()
let event = Event(name: .StartedCheckout, properties: [
"Total Price": 10.99,
"Items Purchased": ["Hot Dog", "Fries", "Shake"]
], identifiers: .init(email: "[email protected]"),
profile: [
"$first_name": "Blob",
"$last_name": "Jr"
], value: 10.99)
klaviyo.create(event: event)
Setting push tokens has not changed very much between versions. Where previously this was done:
Klaviyo.sharedInstance.set(deviceToken: "your-token-here")
Now you can do this:
KlaviyoSDK().set(pushToken: "your-token-here")
Tracking push opens is also a bit different from before. You can now remove the code from application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
. Also under your app delegate you now need the following code:
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let handled = KlaviyoSDK().handle(notificationResponse: response, completionHandler: completionHandler)
if not handled {
// not a klaviyo notification should be handled by other app code
}
}
}
Handling deep link is very similar to how it was done in earlier versions however if you use universal links you may want to update your code as follows:
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let handled = KlaviyoSDK().handle(notificationResponse: response, completionHandler: completionHandler) { url in
// parse deep link and navigate here.
}
if not handled {
// not a klaviyo notification should be handled by other app code
}
}
}
We've also updated the test app to include examples of all the above. If you have more questions feel free to drop us a line in the discussion section of this repo.