### Installation Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/fastlane/README.md Instructions for installing the Fastlane SDK and its dependencies. ```APIDOC ## Installation Make sure you have the latest version of the Xcode command line tools installed: ```sh xcode-select --install ``` For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane) ``` -------------------------------- ### Install with Cocoapods Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/Examples/KlaviyoSwiftExamples/README.md Use this command to install the Klaviyo Swift SDK when your project utilizes Cocoapods. Ensure your Podfile specifies the SDK as a dependency. ```bash pod install ``` -------------------------------- ### Install Xcode Command Line Tools Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/fastlane/README.md Ensures the necessary Xcode command line tools are installed on the system. ```sh xcode-select --install ``` -------------------------------- ### Install KlaviyoForms via CocoaPods Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Add KlaviyoForms to your app target using CocoaPods. Ensure 'YourAppTarget' is replaced with your actual app target name. ```ruby target 'YourAppTarget' do pod 'KlaviyoForms' end ``` -------------------------------- ### Rich Push Notification Payload (Video) Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Example JSON payload for sending a rich push notification with a video. Ensure 'mutable-content' is set to 1. ```json { "aps": { "alert": { "title": "Video Push Notification", "body": "Check out this video content" }, "mutable-content": 1 }, "rich-media": "https://example.com/videos/mp4/your_video.mp4", "rich-media-type": "mp4" } ``` -------------------------------- ### Install KlaviyoSwift via CocoaPods Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Add KlaviyoSwift to your app target using CocoaPods. Ensure 'YourAppTarget' is replaced with your actual app target name. ```ruby target 'YourAppTarget' do pod 'KlaviyoSwift' end ``` -------------------------------- ### Rich Push Notification Payload (Image) Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Example JSON payload for sending a rich push notification with an image. Ensure 'mutable-content' is set to 1. ```json { "aps": { "alert": { "title": "Sample title for a Klaviyo push notification", "body": "Sample body for a Klaviyo push notification" }, "mutable-content": 1 }, "rich-media": "https://picsum.photos/200/300.jpg", "rich-media-type": "jpg" } ``` -------------------------------- ### SwiftUI App Deep Link Handling Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Example of integrating deep link handling into a SwiftUI application using the `.onOpenURL` modifier. This modifier should be attached to the root view of your main App scene to capture incoming URLs. ```swift @main struct MyApplication: App { var body: some Scene { WindowGroup { ContentView() .onOpenURL { url in // handle the URL // if you created a helper method (see "Adding link-handling logic", above), call it here } } } } ``` -------------------------------- ### Install KlaviyoSwiftExtension via CocoaPods Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Add KlaviyoSwiftExtension to your notification service extension target using CocoaPods. Ensure 'YourAppNotificationServiceExtenionTarget' is replaced with your actual extension target name. ```ruby target 'YourAppNotificationServiceExtenionTarget' do pod 'KlaviyoSwiftExtension' end ``` -------------------------------- ### Request Push Notification Permission Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Example code to request push notification permission from the user. This should be called after setting the push token. The SDK automatically tracks permission changes. ```swift import UserNotifications func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { KlaviyoSDK().initialize(with: "YOUR_KLAVIYO_PUBLIC_API_KEY") UIApplication.shared.registerForRemoteNotifications() let center = UNUserNotificationCenter.current() center.delegate = self as? UNUserNotificationCenterDelegate // the type casting can be removed once the delegate has been implemented let options: UNAuthorizationOptions = [.alert, .sound, .badge] // use the below options if you are interested in using provisional push notifications. Note that using this will not // show the push notifications prompt to the user. // let options: UNAuthorizationOptions = [.alert, .sound, .badge, .provisional] center.requestAuthorization(options: options) { granted, error in if let error = error { // Handle the error here. print("error = ", error) } // Irrespective of the authorization status call `registerForRemoteNotifications` here so that // the `didRegisterForRemoteNotificationsWithDeviceToken` delegate is called. Doing this // will make sure that Klaviyo always has the latest push authorization status. DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() } } return true } ``` -------------------------------- ### Push Notification Payload with Action Buttons Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Example JSON payload structure for Klaviyo push notifications that includes custom action buttons. This payload defines buttons with IDs, labels, actions (like deep linking or opening the app), and associated URLs. ```json { "aps": { "alert": { "title": "New Arrivals Just for You", "body": "Check out our latest collection" }, "mutable-content": 1, "sound": "default" }, "body": { "_k": { }, "action_buttons": [ { "id": "someId", "label": "Go to Settings", "action": "deep_link", "url": "klaviyotest://settings" }, { "id": "someOtherId", "label": "Open App", "action": "open_app" } ] } } ``` -------------------------------- ### Unregister from In-App Forms Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Call `unregisterFromInAppForms()` to stop the SDK from displaying In-App Forms. This is useful, for example, when a user logs out. The next registration will be considered a new session. ```swift import KlaviyoForms KlaviyoSDK().unregisterFromInAppForms() ``` -------------------------------- ### Initialize Klaviyo SDK Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Initialize the SDK with your Klaviyo public API key in your AppDelegate. This should be done before any other SDK methods are called. ```swift // AppDelegate import KlaviyoSwift class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { KlaviyoSDK().initialize(with: "YOUR_KLAVIYO_PUBLIC_API_KEY") return true } } ``` -------------------------------- ### Build for iOS Simulator Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/AGENTS.md Use this command to build the entire Klaviyo Swift SDK package for an iOS Simulator. ```bash xcodebuild build -scheme klaviyo-swift-sdk-Package -destination "platform=iOS Simulator,name=iPhone 17 Pro" ``` -------------------------------- ### Format Code Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/AGENTS.md Uses SwiftFormat to format the entire project directory. ```bash swiftformat . ``` -------------------------------- ### Run Library Tests (Release) Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/AGENTS.md Executes the library tests in a release configuration by specifying the CONFIG=release argument. ```bash make CONFIG=release test-library ``` -------------------------------- ### Register Push Token and Initialize SDK Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Call this in your app delegate's `application:didFinishLaunchingWithOptions:` to initialize the SDK and register for remote notifications. The `application:didRegisterForRemoteNotificationsWithDeviceToken` method receives the token from APNs and sets it with Klaviyo. ```swift import KlaviyoSwift func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { KlaviyoSDK().initialize(with: "YOUR_KLAVIYO_PUBLIC_API_KEY") UIApplication.shared.registerForRemoteNotifications() return true } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { KlaviyoSDK().set(pushToken: deviceToken) } ``` -------------------------------- ### Initialize and Register for In-App Forms Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Call `registerForInAppForms()` after initializing the SDK with your public API key. This enables the SDK to display forms. Recommended to call after loading is complete. ```swift import KlaviyoSwift import KlaviyoForms ... // if registering in the same location where you're initializing the SDK KlaviyoSDK() .initialize(with: "YOUR_KLAVIYO_PUBLIC_API_KEY") .registerForInAppForms() // if registering elsewhere after `KlaviyoSDK` is initialized KlaviyoSDK().registerForInAppForms() ``` -------------------------------- ### Run Library Tests (Debug) Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/AGENTS.md Runs the library tests in a debug configuration using the make command. ```bash make test-library ``` -------------------------------- ### Run Tests via xcodebuild Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/AGENTS.md Executes all tests for the Klaviyo Swift SDK package directly using xcodebuild. ```bash xcodebuild test -scheme klaviyo-swift-sdk-Package -destination "platform=iOS Simulator,name=iPhone 17 Pro" ``` -------------------------------- ### Handle Universal Links in SceneDelegate (App Running/Background) Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Implement the `scene(_:continue:)` method in your SceneDelegate for handling universal tracking links when the app is running or in the background. Extract the URL from the NSUserActivity and pass it to the Klaviyo SDK. ```swift func scene( _ scene: UIScene, continue userActivity: NSUserActivity ) { // Get the URL from the incoming user activity. guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, let incomingURL = userActivity.webpageURL else { return } if KlaviyoSDK().handleUniversalTrackingLink(incomingURL) { return } else { // handle a link that's not a Klaviyo universal tracking link // if you created a helper method (see "Adding link-handling logic", above), call it here } } ``` -------------------------------- ### Handle Universal Links in SceneDelegate (App Terminated) Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Implement the `scene(_:willConnectTo:options:)` method in your SceneDelegate for handling universal tracking links when the app is terminated. Extract the URL from connection options and pass it to the Klaviyo SDK. ```swift func scene( _ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions ) { // Get the URL from the incoming user activity. guard let userActivity = connectionOptions.userActivities.first, userActivity.activityType == NSUserActivityTypeBrowsingWeb, let incomingURL = userActivity.webpageURL else { return } if KlaviyoSDK().handleUniversalTrackingLink(incomingURL) { return } else { // handle a link that's not a Klaviyo universal tracking link // if you created a helper method (see "Adding link-handling logic", above), call it here } } ``` -------------------------------- ### Set Push Token: Old vs. New SDK Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/MIGRATION_GUIDE.md Illustrates the change in how push tokens are set, from the older `set(deviceToken:)` method to the new `set(pushToken:)` method. ```swift Klaviyo.sharedInstance.set(deviceToken: "your-token-here") ``` ```swift KlaviyoSDK().set(pushToken: "your-token-here") ``` -------------------------------- ### Build Specific Module Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/AGENTS.md Builds a specific module within the Klaviyo Swift SDK, such as KlaviyoSwift. ```bash xcodebuild build -scheme KlaviyoSwift -destination "platform=iOS Simulator,name=iPhone 17 Pro" ``` -------------------------------- ### Handle Universal Links in AppDelegate Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Implement the `application(_:continue:restorationHandler:)` method in your AppDelegate to process incoming universal tracking links. Ensure the URL is extracted and passed to the Klaviyo SDK. ```swift func application( _ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void ) -> Bool { // Get the URL from the incoming user activity. guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, let incomingURL = userActivity.webpageURL else { return false } if KlaviyoSDK().handleUniversalTrackingLink(incomingURL) { return true } else { // handle a link that's not a Klaviyo universal tracking link // if you created a helper method (see "Adding link-handling logic", above), call it here } } ``` -------------------------------- ### Swift Helper Method for Deep Link Handling Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md A recommended Swift helper method to encapsulate deep link handling logic. This method can be used to parse URL components and manage app navigation based on the link's parameters. ```swift func handleDeepLink(url: URL) { // parse the URL into its components by creating a URLComponents object; i.e., // let components = URLComponents(url: url, resolvingAgainstBaseURL: true) // extract the path and/or the query items from the URL components // use your app's navigation logic to handle routing to the appropriate // screen given the extracted path and/or query items } ``` -------------------------------- ### Replace Singleton Instance with Direct Initialization Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/MIGRATION_GUIDE.md In v2.0.0, the singleton pattern for Klaviyo is deprecated. Replace references to `Klaviyo.sharedInstance` with direct initialization of `KlaviyoSDK()`. ```swift // Old code: Klaviyo.sharedInstance // New code: KlaviyoSDK() ``` -------------------------------- ### Track Event: Old vs. New SDK Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/MIGRATION_GUIDE.md Compares the previous method of tracking events using dictionaries with the new SDK's strongly-typed `Event` object for more robust tracking. ```swift let klaviyo = Klaviyo.sharedInstance let customerDictionary : NSMutableDictionary = NSMutableDictionary() customerDictionary[klaviyo.KLPersonEmailDictKey] = "john.smith@example.com" 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 ) ``` ```swift let klaviyo = KlaviyoSDK() let event = Event(name: .StartedCheckout, properties: [ "Total Price": 10.99, "Items Purchased": ["Hot Dog", "Fries", "Shake"] ], identifiers: .init(email: "junior@blob.com"), profile: [ "$first_name": "Blob", "$last_name": "Jr" ], value: 10.99) klaviyo.create(event: event) ``` -------------------------------- ### Reset and Set Klaviyo Profile Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Demonstrates how to reset the current profile to stop tracking a user and then set a new profile. Useful for scenarios like user logout. ```swift // start a profile for Blob Jr. let profile = Profile(email: "junior@blob.com", firstName: "Blob", lastName: "Jr.") KlaviyoSDK().set(profile: profile) // stop tracking Blob Jr. KlaviyoSDK().resetProfile() // start a profile for Robin Hood let profile = Profile(email: "robin@hood.com", firstName: "Robin", lastName: "Hood") KlaviyoSDK().set(profile: profile) ``` -------------------------------- ### Register for Geofencing in AppDelegate Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Call `registerGeofencing()` as early as possible in your app's lifecycle, ideally after initializing the SDK. This method begins monitoring geofences and tracking enter/exit events. ```swift // AppDelegate import KlaviyoSwift import KlaviyoLocation class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { KlaviyoSDK() .initialize(with: "YOUR_KLAVIYO_PUBLIC_API_KEY") .registerGeofencing() return true } } ``` -------------------------------- ### Handle Push Notification Response Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/MIGRATION_GUIDE.md Shows how to integrate Klaviyo's push notification handling into your `AppDelegate`'s `UNUserNotificationCenterDelegate` implementation. Use this to track push opens and ensure correct notification handling. ```swift 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 } } } ``` -------------------------------- ### Info.plist Configuration for Geofencing Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Configure your app's Info.plist with necessary location usage descriptions and background modes for geofencing. This includes descriptions for 'When In Use' and 'Always' location access, and enabling the 'location' background mode. ```xml NSLocationWhenInUseUsageDescription This app needs location access to show your current location and help you find nearby locations. NSLocationAlwaysAndWhenInUseUsageDescription This app needs location access to monitor geofences and provide location-based notifications when the app is in the background. ``` ```xml UIBackgroundModes location ``` -------------------------------- ### Register Deep Link Handler with Klaviyo SDK Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Register a closure to handle incoming deep links from Klaviyo. This is recommended for centralized navigation logic. Call this chained with initialization or separately after the SDK is initialized. ```swift import KlaviyoSwift import KlaviyoForms ... // Chained with initialization KlaviyoSDK() .initialize(with: "YOUR_KLAVIYO_PUBLIC_API_KEY") .registerDeepLinkHandler { url in // Your code to parse the URL and use the result to navigate to a specific screen // if you created a helper method (see "Adding link-handling logic", above), call it here } // **Or** called separately after initialization KlaviyoSDK().registerDeepLinkHandler { url in // Your code to parse the URL and use the result to navigate to a specific screen // if you created a helper method (see "Adding link-handling logic", above), call it here } ``` -------------------------------- ### Dispatch Lifecycle Events and Native Bridge Communication Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/Tests/KlaviyoFormsTests/Assets/IAFUnitTest.html Configures the lifecycle event dispatcher and initializes the native bridge connection upon DOM content loading. ```javascript window.dispatchLifecycleEvent = function(type) { console.log('Dispatching lifecycle event:', type); document.head.dispatchEvent(new CustomEvent('lifecycleEvent', { detail: { type: type } })); }; document.addEventListener("DOMContentLoaded", function () { const message = JSON.stringify({ type: "handShook", data: {} }); window.webkit.messageHandlers.KlaviyoNativeBridge.postMessage(message); }); ``` -------------------------------- ### Set Klaviyo Profile Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Set a user's profile with their email, first name, and last name. This method can also be used to set other profile attributes individually. ```swift // organization, title, image, location and additional properties (dictionary) can also be set using the below constructor let profile = Profile(email: "junior@blob.com", firstName: "Blob", lastName: "Jr.") KlaviyoSDK().set(profile: profile) // or setting individual properties KlaviyoSDK().set(profileAttribute: .firstName, value: "Blob") KlaviyoSDK().set(profileAttribute: .lastName, value: "Jr.") ``` -------------------------------- ### Handle Deep Link in Push Notification Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/MIGRATION_GUIDE.md Demonstrates how to handle deep links within push notifications using the Klaviyo SDK. This allows for custom navigation logic when a user interacts with a push notification containing a deep link. ```swift 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 } } } ``` -------------------------------- ### Registering URL Scheme in Info.plist Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md XML snippet to be added to your app's Info.plist file to whitelist a custom URL scheme. This allows your app to handle deep links originating from push notifications or other sources. ```xml LSApplicationQueriesSchemes {your_url_scheme} ``` -------------------------------- ### Handle Push Notification Interaction Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Implement this method in your AppDelegate to process user interactions with push notifications, distinguishing between Klaviyo notifications and others. ```swift // be sure to set the UNUserNotificationCenterDelegate to self in the didFinishLaunchingWithOptions method (refer the requesting push notification permission section above for more details on this) extension AppDelegate: UNUserNotificationCenterDelegate { // below method will be called when the user interacts with the push notification func userNotificationCenter( _ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { // If this notification is Klaviyo's notification we'll handle it // else pass it on to the next push notification service to which it may belong let handled = KlaviyoSDK().handle(notificationResponse: response, withCompletionHandler: completionHandler) if !handled { completionHandler() } } // below method is called when the app receives push notifications when the app is the foreground func userNotificationCenter( _ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { if #available(iOS 14.0, *) { completionHandler([.list, .banner]) } else { completionHandler([.alert]) } } } ``` -------------------------------- ### Lint and Auto-Fix Code Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/AGENTS.md Applies SwiftLint auto-fixes and enforces strict linting rules, similar to pre-commit hooks. ```bash swiftlint --fix --strict ``` -------------------------------- ### iOS Actions Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/fastlane/README.md Available Fastlane actions for iOS development. ```APIDOC ## iOS Actions ### ios patch ```sh [bundle exec] fastlane ios patch ``` Release a new version with a patch bump_type ### ios minor ```sh [bundle exec] fastlane ios minor ``` Release a new version with a minor bump_type ### ios major ```sh [bundle exec] fastlane ios major ``` Release a new version with a major bump_type ``` -------------------------------- ### Update Legacy Event Names to New Metric Suffix Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/MIGRATION_GUIDE.md In v2.4.0, legacy event names like .ViewedProduct are deprecated. Use the new cases with the -Metric suffix, such as .ViewedProductMetric, for correct logging. ```swift // 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) ``` -------------------------------- ### Track Klaviyo Event Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Track user events using predefined or custom event names. Events can include properties and a numeric value. ```swift // using a predefined event name let event = Event(name: .StartedCheckoutMetric, properties: [ "name": "cool t-shirt", "color": "blue", "size": "medium", ], value: 166 ) KlaviyoSDK().create(event: event) // using a custom event name let customEvent = Event(name: .CustomEvent("Checkout Completed"), properties: [ "name": "cool t-shirt", "color": "blue", "size": "medium", ], value: 166) KlaviyoSDK().create(event: customEvent) ``` -------------------------------- ### Update Profile Identification API Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/MIGRATION_GUIDE.md The v2.0.0 SDK updates the profile identification API. Use the `Profile` object with email and location, then set it using `KlaviyoSDK().set(profile:)` instead of the old dictionary method. ```swift // Old code: let klaviyo = Klaviyo.sharedInstance let personInfoDictionary : NSMutableDictionary = NSMutableDictionary() personInfoDictionary[klaviyo.KLPersonEmailDictKey] = "john.smith@example.com" personInfoDictionary[klaviyo.KLPersonZipDictKey] = "02215" klaviyo.trackPersonWithInfo(personDictionary: personInfoDictionary) // New code: let profile = Profile(email: "john.smith@example.com", location: .init(zip: "02215")) KlaviyoSDK().set(profile: profile) ``` -------------------------------- ### Release iOS Version Bumps Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/fastlane/README.md Commands to trigger patch, minor, or major version releases for iOS. ```sh [bundle exec] fastlane ios patch ``` ```sh [bundle exec] fastlane ios minor ``` ```sh [bundle exec] fastlane ios major ``` -------------------------------- ### Unregister from Geofencing Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md If you need to stop monitoring geofences, you can call `unregisterGeofencing()`. This will cease tracking geofence enter and exit events. ```swift import KlaviyoSwift import KlaviyoLocation KlaviyoSDK().unregisterGeofencing() ``` -------------------------------- ### Register Form Lifecycle Handler Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Register a handler to track form lifecycle events like showing, dismissing, and CTA clicks. This is useful for sending engagement data to third-party analytics platforms. The handler is called on the main thread. ```swift import KlaviyoForms KlaviyoSDK().registerFormLifecycleHandler { event in switch event { case .formShown(let formId, let formName): // Track when a form is displayed Analytics.track("Klaviyo Form Shown", properties: [ "formId": formId, "formName": formName ]) case .formDismissed(let formId, let formName): // Track when a form is dismissed Analytics.track("Klaviyo Form Dismissed", properties: [ "formId": formId, "formName": formName ]) case .formCtaClicked(let formId, let formName, let buttonLabel, let deepLinkUrl): // Track when a user taps a call-to-action button Analytics.track("Klaviyo Form CTA Clicked", properties: [ "formId": formId, "formName": formName, "buttonLabel": buttonLabel, "deepLinkUrl": deepLinkUrl.absoluteString ]) } } ``` -------------------------------- ### Handle Silent Push Notifications Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Implement this method to process silent push notifications. It accesses custom key-value pairs from the notification's user info. ```swift func application (_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { // Access custom key-value pairs from the top level if let customData = userInfo["key_value_pairs"] as? [String: String] { // Process your custom key-value pairs here for (key, value) in customData { print("Key: \(key), Value: \(value)") } } else { print("No key_value_pairs found in notification") } } ``` -------------------------------- ### Dispatch In-App Form Profile Event Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/Sources/KlaviyoForms/InAppForms/Assets/InAppFormsTemplate.html Use this function to dispatch profile-related events for In-App Forms. It dispatches a CustomEvent named 'profileEvent' on the document's head, including metric, unique ID, time, value, and properties. ```javascript window.dispatchProfileEvent = function(metric, uuid, time, value, properties) { document.head.dispatchEvent(new CustomEvent('profileEvent', { detail: { metric: metric, unique_id: uuid, time: time, value: value, properties: properties } })); }; ``` -------------------------------- ### Configure In-App Forms Session Timeout Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Customize the session timeout duration for In-App Forms by passing an `InAppFormsConfig` object to `registerForInAppForms()`. The default is 3600 seconds (1 hour). ```swift import KlaviyoForms // e.g. to configure a session timeout of 30 minutes let config = InAppFormsConfig(sessionTimeoutDuration: 1800) KlaviyoSDK().registerForInAppForms(configuration: config) ``` -------------------------------- ### Use Custom Event for Legacy Names Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/MIGRATION_GUIDE.md If you need to continue using deprecated legacy event names after v2.4.0, use the .Custom() enum case with the legacy name as a string argument. ```swift let event = Event(name: .Custom("$viewed_product")) ``` -------------------------------- ### Dispatch In-App Form Lifecycle Event Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/Sources/KlaviyoForms/InAppForms/Assets/InAppFormsTemplate.html Use this function to dispatch lifecycle events for In-App Forms. It logs the event type to the console and dispatches a CustomEvent named 'lifecycleEvent' on the document's head. ```javascript window.dispatchLifecycleEvent = function(type) { console.log('Dispatching lifecycle event:', type); document.head.dispatchEvent(new CustomEvent('lifecycleEvent', { detail: { type: type } })); }; ``` -------------------------------- ### Update Switch Statement for Exhaustive Cases Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/MIGRATION_GUIDE.md When migrating to v3.3.0, update switch statements on Event.EventName to include new camelCase cases alongside existing PascalCase ones to avoid compiler errors. ```swift switch event { case .OpenedPush: <...> case .OpenedAppMetric, .openedAppMetric: <...> case .ViewedProductMetric, .viewedProductMetric: <...> case .AddedToCartMetric, .addedToCartMetric: <...> case .StartedCheckoutMetric, .startedCheckoutMetric: <...> case .CustomEvent(let string), .customEvent(let string): <...> } ``` -------------------------------- ### Check if a Notification is from Klaviyo Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Use the `isKlaviyoNotification` extension property to determine if a `UNNotificationResponse` originated from Klaviyo. This is useful when managing multiple push notification providers. ```swift import KlaviyoSwift if notificationResponse.isKlaviyoNotification { // Handle Klaviyo notification } ``` -------------------------------- ### Close Window Button Event Listener Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/Sources/KlaviyoForms/KlaviyoWebView/Development Assets/HTML/jstest.html Attaches a click event listener to a button with the ID 'close-button' to close the current window. ```javascript document.getElementById("close-button").addEventListener("click", function() { window.close(); }); ``` -------------------------------- ### Unregister Form Lifecycle Handler Source: https://github.com/klaviyo/klaviyo-swift-sdk/blob/master/README.md Unregister the previously registered form lifecycle handler. This stops the SDK from sending form interaction events to the custom handler. ```swift KlaviyoSDK().unregisterFormLifecycleHandler() ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.