Coder Social home page Coder Social logo

klaviyo / klaviyo-swift-sdk Goto Github PK

View Code? Open in Web Editor NEW
8.0 72.0 11.0 32.38 MB

SDK that allows users to incorporate Klaviyo's event and person tracking functionality within iOS applications. Written in Swift.

License: MIT License

Swift 98.56% Ruby 1.23% Makefile 0.20%

klaviyo-swift-sdk's Introduction

KlaviyoSwift

CI Status Swift Swift Package Manager Version License Platform

Overview

KlaviyoSwift is an SDK, written in Swift that can be integrated into your iOS App. The SDK enables you to engage with your customers using push notifications. In addition you will be able to take advantage of Klaviyo's identification and event tracking functionality. Once integrated, your marketing team will be able to better understand your app users' needs and send them timely messages via APNs.

Installation options

  1. Install with SPM
  2. Install with Cocoapods

Install with SPM

KlaviyoSwift is available via Swift Package Manager (SPM). Follow the steps below to install.

  1. Open your project and navigate to your project’s settings.
  2. Select the Swift Packages tab and click on the add button below the packages list.
  3. Enter the URL of the Swift SDK repository https://github.com/klaviyo/klaviyo-swift-sdk in the text field and click Next.
  4. On the next screen, select the latest SDK version and click Next.
  5. Select the KlaviyoSwift package.
  6. Click Finish.

Install with CocoaPods

KlaviyoSwift is available through CocoaPods.

  1. To install, add the following line to your Podfile:
pod "KlaviyoSwift"
  1. Run pod install to complete the integration.

The library can be kept up-to-date via pod update.

Event tracking

After the SDK is installed you can begin tracking events in your app.

  1. Make sure any .swift files using the Klaviyo SDK contain the following import call:
import KlaviyoSwift
  1. To add Klaviyo's tracking functionality, include the following line in AppDelegate.swift, within application:didFinishLaunchingWithOptions:
KlaviyoSDK().initialize(with: "YOUR_KLAVIYO_PUBLIC_API_KEY")
  1. Begin tracking events anywhere within your application by calling the create(event:) method in the relevant location.
let event = Event(name: .AddedToCartMetric, properties: [
    "Total Price": 10.99,
    "Items": ["Hot Dog", "Fries", "Shake"]
], identifiers: .init(email: "[email protected]"),
profile: [
    "$first_name": "Blob",
    "$last_name": "Jr"
], value: 10.99)

KlaviyoSDK().create(event: event)

Arguments

The create method takes an event object as an argument. The event can be constructed with the following arguments:

  • name: The name of the event you want to track, as a EventName enum. The are a number of commonly used event names provided by default. If you need to log an event with a different name use CustomEvent with a string of your choosing. This argument is required to track an event.

  • profile: An dictionary of properties that belong to the person who did the action you're tracking. Including an $email, $phone_number or $id key associates the event with particular profile in Klaviyo. In addition the SDK will retain these properties for use in future sdk calls, therefore if they are not included previously set identifiers will be used to log the event. This argument is optional.

  • properties: An dictionary of properties that are specific to the event. This argument is optional.

  • time: This is the timestamp, as an Date, when the event occurred. This argument is optional but recommended if you are tracking past events. If you're tracking real-time activity, you can ignore this argument.

  • value: A numeric value (Double) to associate with this event. For example, the dollar amount of a purchase.

Identifying traits of people

If your app collects additional identifying traits about your users you can provide this to Klaviyo via the set(profileAttribute:value:) or set(profile:) methods and via the individual setters methods for email, phone number, and external id. In both cases we've provided a wide array of commonly used profile properties you can use. If you need something more custom though you can always pass us those properties via the properties dictionary when you create your profile object.

let profile = Profile(email: "[email protected]", firstName: "Blob", lastName: "Jr")
KlaviyoSDK().set(profile: profile)

// or setting individual properties
KlaviyoSDK().set(profileAttribute: .firstName, value: "Blob")
KlaviyoSDK().set(profileAttribute: .lastName, value: "Jr")

Note that the only argument set(profile:) takes is a dictionary representing a customer's attributes. This is different from trackEvent, which can take multiple arguments.

Anonymous Tracking Notice

By default, Klaviyo will begin tracking unidentified users in your app once the SDK is initialized. This means you will be able to track events from users in your app without any user information provided. When an email or other primary identifier is provided, Klaviyo will merge the data from the anonymous user to a new identified user.

Prior to version 1.7.0, the Klaviyo SDK used the Apple identifier for vendor (IDFV) to facilitate anonymous tracking. Starting with version 1.7.0, the SDK will use a cached UUID that is generated when the SDK is initialized. For existing anonymous profiles using IDFV, the SDK will continue to use IDFV, instead of generating a new UUID.

Profile properties and Identifiers

Whenever an email (or other identifier) is provided to use via our APIs we will retain that information for future calls so that new data is tracked against the right profile. However, you are always free to override the current identifiers by passing new ones into a customer properties dictionary.

KlaviyoSDK().set(email: "[email protected]")

Push Notifications

Implementing push notifications requires a few additional snippets of code to enable.:

  1. Registering users for push notifications.
  2. Sending resulting push tokens to Klaviyo.
  3. Handling when users attempt to open your push notifications.

Sending push notifications

  1. Add the following code to your application wherever you would like to prompt users to register for push notifications. This is often included within application:didFinishLaunchingWithOptions:, but it can be placed elsewhere as well. When this code is called, ensure that the Klaviyo SDK is configured and that set(email:) is called. This enables Klaviyo to match app tokens with profiles in Klaviyo customers.
	import UserNotifications
	...
	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)
	    }

	    // Enable or disable features based on the authorization status.
	}

	UIApplication.shared.registerForRemoteNotifications()
  1. Add the following code to the application delegate file in application:didRegisterForRemoteNotificationsWithDeviceToken. You may need to add this code to your application delegate if you have not done so already.
    func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        KlaviyoSDK().set(pushToken: deviceToken)
    }

Any users that enable/accept push notifications from your app now will be eligible to receive your custom notifications.

To read more about sending push notifications, check out our additional push notification guides.

Tracking push notifications

The following code example allows you to track when a user opens a push notification.

  1. Add the following code that extends your app delegate:
extension AppDelegate: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
	let handled = KlaviyoSDK().handle(notificationResponse: response, withCompletionHandler: completionHandler)
	if !handled {
	   // not a klaviyo notification should be handled by other app code
	}
    }
}

Once your first push notifications are sent and opened, you should start to see Opened Push metrics within your Klaviyo dashboard.

Foreground push handling

The following code example allows push notifications to be displayed when your app is running:

    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                  willPresent notification: UNNotification,
                                  withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        var options: UNNotificationPresentationOptions =  [.alert]
        if #available(iOS 14.0, *) {
          options = [.list, .banner]
        }
        completionHandler(options)
    }

If a user taps on the notification with the application open, this event is tracked as an Opened Push event.

Deep Linking

⚠️ Your app needs to use version 1.7.2 at a minimum in order for the below steps to work.

There are two use cases for deep linking that can be relevant here:

  1. When you push a notification to your app with a deep link.
  2. Any other cases where you may want to deep link into your app via SMS, email, web browser etc.

In order for deep linking to work, there are a few configurations that are needed and these are no different from what are required for handling deep linking in general and Apple documentation on this can be followed in conjunction with the steps highlighted here:

Option 1: Modify Open Tracking

If you plan to use universal links in your app for deep linking you will need to modify the push open tracking as described below:

extension AppDelegate: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        let handled = KlaviyoSDK().handle(notificationResponse: response, withCompletionHandler: completionHandler) { url in
            print("deep link is ", url)
        }
        if !handled {
           // not a klaviyo notification should be handled by other app code
        }
    }
}

Note that the deep link handler will be called back on the main thread. If you want to handle uri schemes in addition to universal links you implement them as described below.

Option 2: Use URL Schemes

If you do not need universal link support you can instead implement url schemes for your app and the deepLinkHandler as indicated in Option 1 can be omitted. The Klaviyo SDK will follow all url automatically in this case.

Step 1: Register the URL scheme

In order for Apple to route a deep link to your application you need to register a URL scheme in your application's Info.plist file. This can be done using the editor that xcode provides from the Info tab of your project settings or by editing the Info.plist directly.

The required fields are as following:

  1. Identifier - The identifier you supply with your scheme distinguishes your app from others that declare support for the same scheme. To ensure uniqueness, specify a reverse DNS string that incorporates your company’s domain and app name. Although using a reverse DNS string is a best practice, it doesn’t prevent other apps from registering the same scheme and handling the associated links.
  2. URL schemes - In the URL Schemes box, specify the prefix you use for your URLs.
  3. Role - Since your app will be editing the role select the role as editor.

In order to edit the Info.plist directly, just fill in your app specific details and paste this in your plist.

<key>CFBundleURLTypes</key>
<array>
	<dict>
		<key>CFBundleTypeRole</key>
		<string>Editor</string>
		<key>CFBundleURLName</key>
		<string>{your_unique_identifier}</string>
		<key>CFBundleURLSchemes</key>
		<array>
			<string>{your_URL_scheme}</string>
		</array>
	</dict>
</array>

Step 2: Whitelist supported URL schemes

Since iOS 9 Apple has mandated that the URL schemes that your app can open need to also be listed in the Info.plist. This is in addition to Step 1 above. Even if your app isn't opening any other apps, you still need to list your app's URL scheme in order for deep linking to work.

This needs to be done in the Info.plist directly:

<key>LSApplicationQueriesSchemes</key>
<array>
	<string>{your custom URL scheme}</string>
</array>

Step 3: Implement handling deep links in your app

Steps 1 & 2 set your app up for receiving deep links but now is when you need to figure out how to handle them within your app.

If you are using UIKit, you need to implement application:openURL:options: in your application's app delegate.

Finally, we have an example app (Examples/KlaviyoSwiftExamples) in the SDK repo that you can reference to get an example of how to implement deep links in your app.

Example:

func application(
    _ app: UIApplication,
    open url: URL,
    options: [UIApplication.OpenURLOptionsKey : Any] = [:]
) -> Bool {
    guard let components = NSURLComponents(url: url, resolvingAgainstBaseURL: true)
    else {
       print("Invalid deep linking URL")
       return false
    }

    print("components: \(components.debugDescription)")

    return true
}

If you are using SwiftUI, then you can implement onOpenURL(perform:) as a view modifier in the view you intent to handle deep links. This may or may not be the root of your scene.

Example:

@main
struct MyApplication: App {
  var body: some Scene {
    WindowGroup {
      ContentView()
        .onOpenURL { url in
          // handle the URL that must be opened
        }
    }
  }
}

Once the above steps are complete, you can send push notifications from the Klaviyo Push editor within the Klaviyo website. Here you can build and send a push notification through Klaviyo to make sure that the URL shows up in the handler you implemented in Step 3.

Additionally, you can also locally trigger a deep link to make sure your code is working using the below command in the terminal.

xcrun simctl openurl booted {your_URL_here}

Rich push notifications

⚠️ Rich push notifications are supported in SDK version 2.2.0 and higher

Rich push notification is the ability to add images to your push notification messages that Apple has supported since iOS 10. In order to do this Apple requires your app to implement a Notification service extension. Following the below steps should help set up your app to receive rich push notifications.

Step 1: Add notification service app extension to your project

A notification service app extension ships as a separate bundle inside your iOS app. To add this extension to your app:

  1. Select File > New > Target in Xcode.
  2. Select the Notification Service Extension target from the iOS > Application extension section.
  3. Click Next.
  4. Specify a name and other configuration details for your app extension.
  5. Click Finish.

⚠️ By default the deployment target of your notification service extension might be the latest iOS version and not the minimum you want to support. This may cause push notifications to not show the attached media in devices whose iOS versions are lower than the deployment target of the notification service extension. ⚠️

Step 2: Implement the notification service app extension

The notification service app extension is responsible for downloading the media resource and attaching it to the push notification.

Once step 1 is complete, you should see a file called NotificationService.swift under the notification service extension target. From here on depending on which dependency manager you use the steps would look slightly different:

Swift Package Manager(SPM)

  • Tap on the newly created notification service extension target
  • Under General > Frameworks and libraries add KlaviyoSwiftExtension using the + button at the bottom left.
  • Then in the NotificationService.swift file add the code for the two required delegates from this file. This sample covers calling into Klaviyo so that we can download and attach the media to the push notification.

Cocoapods

  • In your Podfile add in KlaviyoSwiftExtension as a dependency to the newly added notification service extension target.

    Example:

    target 'NotificationServiceExtension' do
        pod 'KlaviyoSwiftExtension', '2.1.0-beta1'
    end
    

    Be sure to replace the name of your notification service extension target above.

  • Once you've added in the dependency make sure to pod install.

  • Then in the NotificationService.swift file add the code for the two required delegates from this file. This sample covers calling into Klaviyo so that we can download and attach the media to the push notification.

Step 3: Test your rich push notifications

Local testing

There are three things you would need to do this -

  1. Any push notifications tester such as this.
  2. A push notification payload that resembles what Klaviyo would send to you. The below payload should work as long as the image is valid:
{
  "aps": {
    "alert": {
      "title": "Free apple vision pro",
      "body": "Free Apple vision pro when you buy a Klaviyo subscription."
    },
    "mutable-content": 1
  },
  "rich-media": "https://www.apple.com/v/apple-vision-pro/a/images/overview/hero/portrait_base__bwsgtdddcl7m_large.jpg",
  "rich-media-type": "jpg"
}
  1. A real device's push notification token. This can be printed out to the console from the didRegisterForRemoteNotificationsWithDeviceToken method in AppDelegate.

Once we have these three things we can then use the push notifications tester and send a local push notification to make sure that everything was set up correctly.

Sandbox Support

Apple has two environments with push notification support - production and Sandbox. The Production environment supports sending push notifications to real users when an app is published in the App Store or TestFlight. In contrast, Sandbox applications that support push notifications are those signed with iOS Development Certificates, instead of iOS Distribution Certificates. Sandbox acts as a staging environment, allowing you to test your applications in a environment similar to but distinct from production without having to worry about sending messages to real users.

Our SDK supports the use of Sandbox for push as well. Klaviyo's SDK will determine and store the environment that your push token belongs to and communicate that to our backend, allowing your tokens to route sends to the correct environments. There is no additional setup needed. As long as you have deployed your application to Sandbox with our SDK employed to transmit push tokens to our backend, the ability to send and receive push on these Sandbox applications should work out-of-the-box.

Testing with Klaviyo

At this point unfortunately we don't support testing debug builds with Klaviyo. So if you are trying to send a test push notification to a debug build you'll see an error on Klaviyo.

A suggested temporary workaround would be creating a test flight build with the above changes required for rich push notifications, performing some actions on the test flight build to identify the device and making sure you are able to see that device in Klaviyo. Once you have that device's push token in any profile you can create a list or segment with that profile and send a push campaign with an image to test the full end-to-end integration.

SDK Data Transfer

Starting with version 1.7.0, the SDK will cache incoming data and flush it back to the Klaviyo API on an interval. The interval is based on the network link currently in use by the app. The table below shows the flush interval used for each type of connection:

Network Interval
WWAN/Wifi 10 seconds
Cellular 30 seconds

Connection determination is based on notifications from our reachability service. When there is no network available, the SDK will cache data until the network becomes available again. All data sent by the SDK should be available shortly after it is flushed by the SDK.

Retries

The SDK will retry API requests that fail under certain conditions. For example, if a network timeout occurs, the request will be retried on the next flush interval. In addition, if the SDK receives a rate limiting error 429 from the Klaviyo API, it will use exponential backoff with jitter to retry the next request.

License

KlaviyoSwift is available under the MIT license. See the LICENSE file for more info.

UserDefaults access

As of fall 2023, Apple requires apps that access specific Apple APIs to provide a reason for this access. Previous versions of the Klaviyo SDK used UserDefaults to store data about the current user. Today, when the SDK starts up, it must access this data to migrate to a new format. Below, we've provided a sample reason you can include with your app submission (if requested):

UserDefaults is accessed by the Klaviyo SDK within our app to migrate some user data (previously stored there). None of this data is shared with other apps.

If your app or other SDKs also access UserDefaults, you may need to amend the reason to include that usage as well. Use the string NSPrivacyAccessedAPICategoryUserDefaults as the value for the NSPrivacyAccessedAPIType key in your NSPrivacyAccessedAPITypes dictionary. For more information, see this guide.

klaviyo-swift-sdk's People

Contributors

ajaysubra avatar chrisconlon-klaviyo avatar dependabot[bot] avatar evan-masseau avatar floriankrueger avatar iballan avatar jordan-griffin avatar khinkle14 avatar ndurell avatar sairamkotha avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

klaviyo-swift-sdk's Issues

Missing "Added to Cart" event

Description

I'm new to Klaviyo, but neither the iOS nor Android SDKs have the "Added to Cart" event name/type available. You guys have plenty of documentation indicating it's a normal standard event (including JS examples for triggering it), so I'm confused.

Should we trigger it as a custom event? If so, what should the event name be? Other mobile event names look like $viewed_product whereas JS documentation shows event names like Added to Cart, so I'm also confused about the formatting differences.

Checklist

  • I have determined whether this bug is also reproducible in a vanilla SwiftUI project.
  • If possible, I've reproduced the issue using the main branch of this package.
  • This issue hasn't been addressed in an existing GitHub issue or discussion.

Expected behavior

There is an explicit addedToCart event name.

Actual behavior

There is none, while most if not all other events exist.

Steps to reproduce

No response

The Klaviyo Swift SDK version information

2.2.1

Destination operating system

iOS 17

Xcode version information

Xcode 15

Swift Compiler version information

No response

Push Token shows Null in profile after User Registration.

Description

I am calling User Registration event using following SDK method. And then call set push token

klaviyoSdk?.set(profile: Profile(email: email, phoneNumber: number, externalId: externalId))
klaviyoSdk?.set(pushToken: localToken)

if user is not doing any other action we are seeing Push Token as Null as soon as we check the registration event.
If user does some activity by triggering other Klaviyo events the PushToken is reflecting.
Attaching image for reference. Let me know if I need to do some thing else at code side to resolve it.

Screenshot 2023-12-06 at 12 50 12 PM

Checklist

  • I have determined whether this bug is also reproducible in a vanilla SwiftUI project.
  • If possible, I've reproduced the issue using the main branch of this package.
  • This issue hasn't been addressed in an existing GitHub issue or discussion.

Expected behavior

As soon as the User Registration gets called and set token method is called push token should get reflected

Actual behavior

No response

Steps to reproduce

I am calling User Registration event using following SDK method.

klaviyoSdk?.set(profile: Profile(email: email, phoneNumber: number, externalId: externalId))

And then call set push token

klaviyoSdk?.set(pushToken: localToken)

The Klaviyo Swift SDK version information

2.2.1

Destination operating system

iOS 16.2

Xcode version information

13

Swift Compiler version information

No response

Client Push token API is failing when background field is UNAVAILABLE

Description

Push Tokens are not registering on the dashboard when the background refresh is a UNAVAILABLE field inside the push tokens API.
API:
https://a.klaviyo.com/client/push-tokens/?company_id=XXXXXX
Request body:

{
 {

> "background": "UNAVAILABLE",

      "vendor": "APNs",
      "platform": "ios",
      "enablement_status": "AUTHORIZED",
      "profile": {
        "data": {
          "attributes": {
            "anonymous_id": "41E5D174-6970-4064-8CDA-31132864ABD5",
            "properties": {}
          },
          "type": "profile"
        }
      }
    },
    "type": "push-token"
  }
}

Response:

{
  "errors": [
    {
      "id": "5dc13942-2156-4b17-a2a2-b3b3bd75d858",
      "status": 400,
      "code": "invalid",
      "title": "Invalid input.",
      "detail": "'UNAVAILABLE' is not a valid choice for 'background'.",
      "source": {
        "pointer": "/data/attributes/background"
      },
      "meta": {}
    }
  ]
}

Based on the Swift code:
This enum returns UNAVAILABLE and API is returning 400 status code.
enum PushBackground: String {
case available = "AVAILABLE"
case unavailable = "UNAVAILABLE"

    static func create(from status: UIBackgroundRefreshStatus) -> PushBackground {
        switch status {
        case .available:
            return PushBackground.available
        default:
            return PushBackground.unavailable
        }
    }
}

Checklist

  • I have determined whether this bug is also reproducible in a vanilla SwiftUI project.
  • If possible, I've reproduced the issue using the main branch of this package.
  • This issue hasn't been addressed in an existing GitHub issue or discussion.

Expected behavior

Push tokens API shouldn't fail for background request status

Actual behavior

No response

Steps to reproduce

No response

The Klaviyo Swift SDK version information

2.2.0 version

Destination operating system

iOS 16.4

Xcode version information

Xcode: 14.3.1

Swift Compiler version information

No response

KlaviyoSDK().handle is always returning false

Description

Im trying to implement deep linking using the KlaviyoSDK. I have implemented this method

public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        let handled = KlaviyoSDK().handle(notificationResponse: response, withCompletionHandler: completionHandler) { url in
            print(url.absoluteString)
        }
        if !handled {
            completionHandler()
        }
    }

The url never gets printed and handled is always returning false. I have looked into this method and I think the cause is because the _k property is not part of the body on the userInfo. The notifications are being sent from Klaviyo. Is there any setting I need to set up to have the notification payload contain the _k key ?

I am running this in sandbox.

Checklist

  • I have determined whether this bug is also reproducible in a vanilla SwiftUI project.
  • If possible, I've reproduced the issue using the main branch of this package.
  • This issue hasn't been addressed in an existing GitHub issue or discussion.

Expected behavior

The KlaviyoSDK().handle will return true and the deepLinkHandler would return the url.

Actual behavior

The KlaviyoSDK().handle returns false and the deepLinkHandler never gets called.

Steps to reproduce

Set up the handle methos in the userNotificationCenter didReceive delegate method. Send and notification from Klayvio.

The Klaviyo Swift SDK version information

2.2.1

Destination operating system

16.6

Xcode version information

14.3

Swift Compiler version information

1.75.2 Apple Swift version 5.8 (swiftlang-5.8.0.124.2 clang-1403.0.22.11.100)

Track event causes the app to crash

Our iOS mobile app is integrated with Klaviyo Swift SDK. From time to time the app crashes when Klaviyo attempts to track an event. Here is a fragment of a sample crash log:

Thread 1 name:
Thread 1 Crashed:
0 KlaviyoSwift 0x0000000103c43b0c closure #1 in Klaviyo.trackEvent(event:customerProperties:propertiesDict:eventDate:) + 1460 (Klaviyo.swift:0)
1 KlaviyoSwift 0x0000000103c435a4 closure #1 in Klaviyo.trackEvent(event:customerProperties:propertiesDict:eventDate:) + 76

Any idea on this one?

Unable to build SDK

Description

I am having an issue showing inside the framework. Having build issues
Screenshot 2024-01-31 at 1 34 27 PM

Checklist

  • I have determined whether this bug is also reproducible in a vanilla SwiftUI project.
  • If possible, I've reproduced the issue using the main branch of this package.
  • This issue hasn't been addressed in an existing GitHub issue or discussion.

Expected behavior

No response

Actual behavior

No response

Steps to reproduce

No response

The Klaviyo Swift SDK version information

No response

Destination operating system

No response

Xcode version information

No response

Swift Compiler version information

No response

`.ViewedProduct` event does not show up as 'Viewed Product' in dashboard

Description

When sending the .ViewedProduct event, it shows up in the dashboard as a new duplicated '$viewed_product' event instead of the canonical 'Viewed Product' event. I assume this is the case for other events as well, though I'll check more soon. I'll also try out version 2.3.0 since it was just released.

This is obviously pretty bad, since it bifurcates analytics data and muddies up one's whole dashboard setup.

Checklist

  • I have determined whether this bug is also reproducible in a vanilla SwiftUI project.
  • If possible, I've reproduced the issue using the main branch of this package.
  • This issue hasn't been addressed in an existing GitHub issue or discussion.

Expected behavior

Events sent from the iOS SDK appear with normalized names like 'Viewed Product' in the dashboard so that they integrate with the events from other surfaces.

Actual behavior

Events sent from the iOS SDK appear as dollar sign-prefixed snake case names like $viewed_product in the dashboard.

Steps to reproduce

  1. Send a .ViewedProduct event from the iOS SDK.
  2. Go to your Klaviyo profile event history to see the event it sent

The Klaviyo Swift SDK version information

2.2.1

Destination operating system

iOS 17

Xcode version information

15

Swift Compiler version information

No response

Unable to set push token in React Native Project

Description

I have created a react native package for Klaviyo Swift SDK for our RN project which is using Objective c.
I am using package to set pushToken to Klaviyo SDK.
I have device token in string which is provided by PushNotificationIOS in JS code but Klaviyo SDK accepts Data .

I tried Data(token.utf8) but this is generating bad token.

I am not sure what to do now.

Checklist

  • I have determined whether this bug is also reproducible in a vanilla SwiftUI project.
  • If possible, I've reproduced the issue using the main branch of this package.
  • This issue hasn't been addressed in an existing GitHub issue or discussion.

Expected behavior

No response

Actual behavior

No response

Steps to reproduce

No response

The Klaviyo Swift SDK version information

No response

Destination operating system

No response

Xcode version information

No response

Swift Compiler version information

No response

func handle(notificationResponse: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void, deepLinkHandler: ((URL) -> Void)? = nil) -> Bool

Description

hey guys, did you guys ever encounter that this function is breaking the single responsibility principal. This function performs four job works

  1. Creates tracking event in Klaviyo
  2. Validate if it is Klaviyo payload
  3. Handles the deep link
  4. Redirect to Deeplink custom handler.

Checklist

  • I have determined whether this bug is also reproducible in a vanilla SwiftUI project.
  • If possible, I've reproduced the issue using the main branch of this package.
  • This issue hasn't been addressed in an existing GitHub issue or discussion.

Expected behavior

As this being SDK, it should allow consumers to consume functions with single responsibility. Depending on consumer requirement they can sequence the function calls.

Actual behavior

One function does all, which is not the best approach

Steps to reproduce

Call handle()

The Klaviyo Swift SDK version information

lastest version

Destination operating system

Latest iOS SDK

Xcode version information

latest XCode version

Swift Compiler version information

N.A

Some problem with sending push notifications

Description

Hello. One of the my colleagues report a problem and haven’t had any answer https://community.klaviyo.com/members/alena-n-14748. Looks like klaviyo sends pushes using sandbox endpoint because of we have same result using side service

Checklist

  • I have determined whether this bug is also reproducible in a vanilla SwiftUI project.
  • If possible, I've reproduced the issue using the main branch of this package.
  • This issue hasn't been addressed in an existing GitHub issue or discussion.

Expected behavior

No response

Actual behavior

No response

Steps to reproduce

No response

The Klaviyo Swift SDK version information

2.2.1

Destination operating system

iOS 16

Xcode version information

No response

Swift Compiler version information

No response

Not able to see OPEN RATE on Klaviyo's dashboard

Description

Reported the same issue on Android sdk too klaviyo/klaviyo-android-sdk#78

But on Android we had to customize the behavior and log OPENED_PUSH manually.
On iOS it is not working even though we are using the SDK's version of handling notification.

        let isKlaviyoNotification = KlaviyoSDK().handle(notificationResponse: response, withCompletionHandler: completionHandler, deepLinkHandler: deeplinkHandler)
        if !isKlaviyoNotification {
             // our code goes here
        }

KlaviyoSDK().handle should be handling the logic of logging OPENED_PUSH event, yet i tried to create the event and send it to make sure it is sent to Klaviyo.
Yet i don't see open rate on the dashboard

Checklist

  • I have determined whether this bug is also reproducible in a vanilla SwiftUI project.
  • If possible, I've reproduced the issue using the main branch of this package.
  • This issue hasn't been addressed in an existing GitHub issue or discussion.

Expected behavior

When I send push notification from klaviyo's dashboard and click on it, I expect to see 1 opened notification on the dashboard.

Actual behavior

Open rate is 0% all the time no matter how I log the OPENED_PUSH event

Steps to reproduce

Send push notification to iOS, clicking it won't show open rate on the dashboard

The Klaviyo Swift SDK version information

2.0.1

Destination operating system

iOS 16

Xcode version information

14.3.1

Swift Compiler version information

Swift 5

set(Profile) not identifiying the user in 2.2.0

Description

Hi,
I was using KlaviyoSDK in the latest version (2.2.0) and I was not able to identify the user using the set method provided by SDK. Every time that I call this method it starts creating a new not identified user.
My solution was rolling back the version to 2.0.1 which is working great. After I call the set(Profile) method, and start sending events my user is being identified in the Klaviyo Portal with the information provided.

I did not have time to extensive reproduce this issue since rolling back the version fix the issue for me.

Checklist

  • I have determined whether this bug is also reproducible in a vanilla SwiftUI project.
  • If possible, I've reproduced the issue using the main branch of this package.
  • This issue hasn't been addressed in an existing GitHub issue or discussion.

Expected behavior

set(Profile) should identify the user that sends new events with information provided (firstName, lastName, email)

Actual behavior

calling set(Profile) then sending an event, will create a new unidentified user with the new event

Steps to reproduce

  1. init the SDK with a valid key
  2. call set(Profile) with firstName lastName and email
  3. send any event

if you repeat the steps without a new app installation it will create a new user to hold for the second event

The Klaviyo Swift SDK version information

2.2.0

Destination operating system

Simulator: iPhone 14 Pro - iOS 16.2

Xcode version information

14.2 (14C18)

Swift Compiler version information

swift-driver version: 1.62.15 Apple Swift version 5.7.2 (swiftlang-5.7.2.135.5 clang-1400.0.29.51)
Target: arm64-apple-macosx12.0

Stuck in bad state when passing improper phone number format

Description

If we call set(profile:) with a profile containing a phone number that the API doesn't like (e.g. empty string, though presumably other values as well), the SDK seems to get stuck in a bad state that prevents profile syncing from working, even if we later set the phone number to nil in code. I notice warning logs that show a 400 http error from the Klaviyo API indicating that the phone number is invalid. This persists even after I then attempt to set the phone number to nil.

Besides handling phone number as an empty string, I also worry that this same behavior would occur if the phone number we pass belongs to a country that Klaviyo does not yet have SMS support for. Some conversations I found online from Klaviyo staff indicated that this may be the case.

For what it's worth, I don't believe the Android SDK has the same issue. I pass an empty phone number string there and I think all is well.

My app sets the profile in a reactive manner whenever the "customer stream" emits a new customer value. This occurs immediately on app start, on sign in / register, on profile information update, and on sign out (in which we call resetProfile()).


I assume nil values are interpreted as "ignore", where the internal state management retains previously set non-nil values. So it seems impossible to effectively remove a previously-set field.

It may be worth considering switching from a raw String to an enum that allows more granularity. I've seen other tools implement something similar. Example:

enum ProfileValue {
  case unset
  case set(String?)
}

Checklist

  • I have determined whether this bug is also reproducible in a vanilla SwiftUI project.
  • If possible, I've reproduced the issue using the main branch of this package.
  • This issue hasn't been addressed in an existing GitHub issue or discussion.

Expected behavior

Either:

  • an empty phone number string is parsed out by the SDK and not sent up to the API
  • setting a profile field to nil wipes out the previous field value (though I understand this has other implications, so probs not a solution)

Actual behavior

The Klaviyo SDK holds onto old profile values (the phone number empty string) and does not unset them when we later try to set it to nil, resulting in all future API calls to fail.

Steps to reproduce

  1. Set profile phone number to empty string
  2. Notice API call fail with an invalid phone number error
  3. Set profile phone number to nil
  4. Notice API call continue to fail for the same initial reason

The Klaviyo Swift SDK version information

2.2.1

Destination operating system

iOS 17

Xcode version information

15

Swift Compiler version information

No response

Readme Should Include Instructions for working with UNUserNotificationCenterDelegate

The readme doesn't currently show that in order to get proper open rates, if you are using UNUserNotificationCenterDelegate you need to include the following:

extension AppDelegate: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        Klaviyo.sharedInstance.handlePush(userInfo: response.notification.request.content.userInfo as NSDictionary)
        completionHandler()
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.