- 1. SDK Stats
- 2. Integration Steps:
- 3. Installation
- 4. Usage
- 5. Wunderkind SDK Reference
- 6. Upgrade the Wunderkind-SDK
- 7. Change Log
- 8. License
iOS SDK
1. SDK Stats
Minimum Xcode version: 10.0+
Minimum iOS version: 11.0+
SDK Current Version: 1.4.1
2. Integration Steps
- Follow the steps in the Installation section to include the Wunderkind SDK in your project.
- Initialize the SDK in your project with the steps defined under the Usage section.
- Replace
WEBSITE_ID
with your website ID in the main SDK'sinitialize
function and make sure to setisDebugMode
flag to true both in development and testing environments.
3. Installation
The Wunderkind SDK supports multiple methods for installing into a project. Two have been listed here (CocoaPods and Manual).
3.1 Install with CocoaPods
You can use this guide to install the Wunderkind SDK into your projects.
To install the Wunderkind SDK into your Xcode project using CocoaPods, please follow next steps
- Define the latest Wunderkind SDK in the Podfile
platform :ios, '11.0'
use_frameworks!
target 'AppTarget' do
pod 'Wunderkind', podspec: 'https://storage.googleapis.com/wunderkind-ios-sdk/latest.podspec'
end
If you wish to install specific version x.y.z
, please refer to the corresponding podspec file.
platform :ios, '11.0'
use_frameworks!
target 'AppTarget' do
pod 'Wunderkind', podspec: 'https://storage.googleapis.com/wunderkind-ios-sdk/x.y.z.podspec'
end
- Install the pods, then open your
.xcworkspace
file to see the project in Xcode
$ pod install
$ open your-project.xcworkspace
3.2 Manual Installation
To integrate framework manually,
- Download the
x.y.z
version from Cloud Storage. - Drag and drop
WunderkindKit.xcframework
to Frameworks, Libraries, and Embedded Content in General Settings of your application's target. - If you placed the framework in a custom file system’s location, please specify it in FRAMEWORK_SEARCH_PATHS (in your Build Settings).
4. Usage
In order to allow your app to track events, please follow the steps highlighted in this section
4.1 Import the Wunderkind SDK to your project.
import WunderkindKit
4.2 SDK Initialization
Initialize SDK with your WEBSITE_ID
(If you don't know your WEBSITE_ID
, please contact our support team), and set a corresponding environment configuration isDebugMode
(details below).
The initialization is mandatory. Failure to do so will result in the SDK being unable to track events properly. In most cases, this should be done in application:didFinishLaunchingWithOptions:
💬 By default debug mode is disabled, but setting isDebugMode
to true
will allow you to verify events tracking functionality in a debug environment. Please make sure to set it to false
before deploying to production.
⚠️ isDebugMode
must be set to false
before promoting to production.
class AppDelegate: UIResponder, UIApplicationDelegate {
..
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions
launchOptions: [UIApplication.LaunchOptionsKey: Any]?)
-> Bool {
..
Wunderkind.shared.initialize(websiteId: WEBSITE_ID, isDebugMode:isDebugMode)
}
4.3 Opting Users Out of Tracking
Client-side tracking of user data may be enabled/disabled by controlling a userʼs opt-in/out state. The opt-in/out state of a user is controlled by an opt-out flag that affects on the user's device information.
💬 User information is tracked by default - A user must therefore explicitly opt-out to disable tracking
4.3.1 Context Information Tracking
The Wunderkind SDK collects device/context specific information, which include:
-
Device Information:
- Operating system name
- Operating system version
- Device model
- Screen resolution
- Device type
-
App Information:
- Installation date
- Bundle identifier
- Version number
- Build number
Users may opt-in/out of context tracking and this can be set through the isContextInfoTrackingEnabled
property, which is enabled by default.
💬 Device/Context tracking is enabled by default.
Wunderkind.shared.isContextInfoTrackingEnabled = false
4.4 Track Events
Important Notes:
⚠️ It’s imperative that SDK functions be only called once for a single application event. Duplicate calls may occur when using inheritance patterns and accidental calls to the same SDK functions from parent and child objects simultaneously.
💬 Please refer to the Wunderkind SDK Reference section for more information about classes and types that are used in SDK's API.
💬 Underlying data points gathered by the Wunderkind SDK may be reviewed by using proxy applications such as Charles or Proxyman and through the use of request interceptions. This will help you to validate that events are sent with the expected arguments provided via the API functions. Also note that events are sent to the backend every 1 minute. Please also refer to the Logging section below to customize your project's debug logs section to review Wunderkind SDK's expected results (initialization result, events saving and sending response).
The following is a list of public functions in Wunderkind class that may be used for tracking events.
4.4.1 Screen view event
Overview
This event should be triggered when a user navigates to a new screen, within the app.
Wunderkind.shared.trackScreenView(url: URL, type: ScreenType)
💬 Url property is required to be non-null otherwise this event will not be tracked. If you cannot provide corresponding screen's URL, please use your default home webpage URL.
💬 Type is a required property of type Enum. There is no need to call trackScreenView
if the page does not fall into one of the Enum's types.
⚠️ This event should only be called once per page navigation. We recommend calling trackScreenView
API when the page is presented to the user (viewWillAppear
, viewDidAppear
), and not when page is initialized (init
/ viewDidLoad
, etc.).
Example Implementation:
final class HomeViewController: BaseViewController {
...
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Pass here screen's URL or your default home webpage URL.
Wunderkind.shared.trackScreenView(url: URL(string: "https://www.your-webpage.com/search")!, type: .search)
}
}
4.4.2 Empty cart event
Overview
This event should be triggered when a user empties a cart.
⚠️ This event should only be triggered when a user has items in their cart and empties it. Not every time a user opens their empty cart.
Wunderkind.shared.trackEmptyCart()
Example Implementation:
final class CartViewController: BaseViewController {
...
func cartBecameEmpty() {
// This event should only be triggered when a user has items in their cart and empties it.
// Not every time a user opens their empty cart.
Wunderkind.shared.trackEmptyCart()
}
}
4.4.3 View item event
Overview
This event should be triggered when a user views an item.
Wunderkind.shared.trackViewItem(itemId: String, groupId: String)
💬 itemId
, groupId
properties are required to be non-empty otherwise this event will not be tracked.groupId
represents a group of similar items. For example, a shirt will have the same groupId
for all variations of that shirt (different sizes/colors, etc). I.e. each size/color combo will have a different itemId
but the same groupId
.
💬We recommend calling the trackViewItem
API when the product screen is presented to the user (viewWillAppear
, viewDidAppear
), and not when screen is initialized (init
/ viewDidLoad
).
Example Implementation:
final class ProductDetailsViewController: BaseViewController {
...
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// In the screenshot above the item id is equal to 17727082
let itemId = "17727082"
// In the screenshot above the group id is equal to "pin-dot-quilters-showcase-cotton-fabric"
let groupId = "pin-dot-quilters-showcase-cotton-fabric"
Wunderkind.shared.trackViewItem(itemId: itemId, groupId: groupId)
}
}
4.4.4 Select SKU event
Overview
This event is triggered when a user selects specific product attributes (e.g. color, size, etc…) and contains SKU details that were selected.
Wunderkind.shared.trackSelectSKU(groupId: String, feedId: String)
💬 groupId
and feedId
properties are required to be non-empty otherwise this event will not be tracked. groupId
represents a group of similar items. For example, a shirt will have the same groupId
for all variations of that shirt (different sizes/colors, etc). I.e. each size/color combo will have a different feedId
but the same groupId
.
Example Implementation:
final class ProductDetailsViewController: BaseViewController {
...
func userSelectedProductSize(size: ProductSize) {
// In the screenshot above the group id is equal to 2000469213
let groupId = "2000469213"
// In the screenshot above the feed id is equal to 20004692130203
// In this example feedId = 2000469213 (groupId) + 02 (color) + 03 (size)
let feedId = "20004692130203"
Wunderkind.shared.trackSelectSKU(groupId: groupId, feedId: feedId)
}
}
4.4.5 Add to cart event
Overview
This event is triggered when a user adds an item to their cart.
Wunderkind.shared.trackAddToCart(itemId: String)
💬itemId
property is required to be non-empty otherwise this event will not be tracked.
Example Implementation:
final class ProductDetailsViewController: BaseViewController {
...
func addToCartButtonTapped() {
// In the screenshot above the item id is equal to 17727082
let itemId = "17727082"
Wunderkind.shared.trackAddToCart(itemId: itemId)
}
}
4.4.6 View category event
Overview
This event is triggered when a user views the category screen.
Wunderkind.shared.trackViewCategory(category: ProductCategory)
💬category
property is required to be non-null otherwise this event will not be tracked. If you cannot provide corresponding category’s URL, please pass your default home webpage URL. Please refer to Product Category section to learn more about expected types and values to be sent.
Example Implementation:
final class ProductsListFromCategoryViewController: BaseViewController {
...
func productsLoaded(items: [Product]) {
// In the screenshot above leaf category name is "Fine"
let categoryTitle = "Fine"
// Pass here category's URL or your default home webpage URL.
let categoryUrl = URL(string: "https://www.your-webpage.com/top-level-category/leaf-category")!
// Pass here a list of item ids that are part of selected category
let productsIds = items.map { $0.productId }
let wunderkindCategory = ProductCategory(title: categoryTitle,
url: categoryUrl,
itemIds: productsIds)
Wunderkind.shared.trackViewCategory(category: wunderkindCategory)
}
}
4.4.7 View search event
Overview
This event is triggered when a user views a search results screen.
Wunderkind.shared.trackViewSearch(category: ProductCategory)
💬category
property is required to be non-null otherwise this event will not be tracked. If you cannot provide corresponding search’s URL, please pass your default home webpage URL. Please refer to Product Category section to learn more about expected types and values to be sent.
Example Implementation:
final class ProductsListFromSearchViewController: BaseViewController {
...
func productsLoaded(items: [Product]) {
let searchInput = "coconut"
// Pass here search results URL or your default home webpage URL.
let searchResultsUrl = URL(string: "https://www.your-webpage.com/search?input=coconut")!
// Pass here a list of item ids in the search result
let productsIds = items.map { $0.productId }
let wunderkindCategory = ProductCategory(title: searchInput,
url: searchResultsUrl,
itemIds: productsIds)
Wunderkind.shared.trackViewSearch(category: wunderkindCategory)
}
}
4.4.8 Logged in event
Overview
This event is triggered when a user explicitly successfully signed in to their app. This event is also triggered when a user signed up to their app.
Wunderkind.shared.trackLoggedIn(email: String, phone: Int)
💬email
property is required to be non-empty otherwise this event will not be tracked.
Please pass phone
in the following format (country code)(phone number)
Example: 13305851212
If the phone
is deemed not valid the below warning log will be emitted-
Unfortunately, eventName hasn't been tracked since you
have provided a nullable parameter or a not valid one.
Example Implementation:
final class LoginViewController: BaseViewController {
...
func loginWasSuccessfulViaGoogleSignIn() {
// This event is triggered when a user explicitly successfully signed in to their app.
Wunderkind.shared.trackLoggedIn(email: emailTextField.text, phone: phoneTextField.text)
}
}
4.4.10 LoggedOut Event
Overview
This event is called when a user logs out of the application.
Wunderkind.shared.trackLoggedOut()
Example Implementation:
final class SignOutController: BaseViewController {
...
func signOut() {
Wunderkind.shared.trackLoggedOut()
}
}
4.4.11 Text Opt In Event
Overview
This event is triggered when a user opts in to text messaging.
💬Pass nil for languageCode, unless the desired language is French then pass a String with value “fr”
💬 Please pass phone in the following format (country code)(phone number)
Example: 13305851212
If the PhoneNumber is deemed not valid the below warning log will be emitted-
Unfortunately, eventName hasn't been tracked since you
have provided a nullable parameter or a not valid one.
Wunderkind.shared.trackTextOptIn(phoneNumber: Int, languageCode: String?)
Example Implementation:
final class SignupViewController: BaseViewController {
...
func textOptInSelected(givenPhoneNumber: String, selectedLanguage: String) {
if (selectedLanguage == "french"){
Wunderkind.shared.trackTextOptIn(phoneNumber: givenPhoneNumber, languageCode: "fr")
}
else {
Wunderkind.shared.trackTextOptIn(phoneNumber: givenPhoneNumber, languageCode: null)
}
}
}
4.4.12 Purchase event
Overview
This event is triggered when a user purchases an item and completes their order.
Wunderkind.shared.trackPurchase(order: Order)
💬 order
property is required to be non-null otherwise this event will not be tracked.
⚠️ Please note that due to the importance of the Purchase event, it’s imperative that all of its attributes (Invoice, Customer, Product, Order) be correctly set.
⚠️ Should purchase event attributes not be entered correctly, the following error may be generated in your project’s logs: Unfortunately, event "Purchase" hasn't been tracked since you have provided a nullable parameter or a not valid one.
Please ensure that all arguments sent to the SDK are correctly entered and contact the Wunderkind SDK team, should you need any help.
Example Implementation:
final class CheckoutViewController: BaseViewController {
...
func purchaseWasSuccessful() {
let invoice = Invoice(amount: 40.0,
tax: 2.5,
shipping: 4.5,
totalDiscount: nil,
currency: .USD)
let customer = Customer(email: "test@wunderkind.co",
phone: 12223334445)
let product = Product(productId: "TestProductId",
skuId: "TestSKUId",
price: 10.0,
quantity: 2)
let order = Order(orderId: "TestOrderId",
invoice: invoice,
paymentMethod: "Credit Card",
products: [product],
customer: customer,
coupons: ["TestCoupon"],
goal: "purchase")
Wunderkind.shared.trackPurchase(order: order)
}
}
4.5 Logging
The Wunderkind SDK provides logging capabilities in order to report on events collected and are useful to validate user data.
Setting logLevel property to debug will allow you to trace data going through the Wunderkind SDK.
Wunderkind.shared.logLevel = .debug
Setting logLevel property to none will allow you to disable logging.
Wunderkind.shared.logLevel = .none
5. Wunderkind SDK Reference
5.1 Classes
Product Category
ProductCategory(title: String,
url: URL,
itemIds: [String])
💬title
, itemIds
properties are required to be non-empty otherwise this event will not be tracked.
Invoice
Invoice(amount: Decimal,
tax: Decimal,
shipping: Decimal,
totalDiscount: Decimal?,
currency: Currency)
💬amount
, tax
, shipping
properties are required to be greater than or equal to 0.0 otherwise this event will not be tracked. Also, if totalDiscount
property is not null, it must be greater than or equal to 0.0.
Customer
Customer(email: String,
phone: Int)
💬initWithEmail
, phone
properties are required to be non-empty otherwise this event will not be tracked.Please pass phone
in the following format (country code)(phone number)
Example: 13305851212
If the PhoneNumber is deemed not valid the below warning log will be emitted-
Unfortunately, eventName hasn't been tracked since you
have provided a nullable parameter or a not valid one.
💬email
is required, phone
is optional.
Product
Product(productId: String,
skuId: String,
price: Decimal,
quantity: Int64)
💬productId
, skuId
properties are required to be non-empty, price
, quantity
properties are required to be greater than or equal to 0 otherwise this event will not be tracked.
Order
Order(orderId: String,
invoice: Invoice,
paymentMethod: String?
products: [Product],
customer: Customer,
coupons: [String]?,
goal: String)
💬orderId
, goal
, products
properties are required to be non-empty otherwise this event will not be tracked. Also, if paymentMethod
or coupons
properties are not null, they must be non-empty.
5.2 Enums
Screen Type
enum ScreenType: Int {
case home
case product
case category
case search
case cart
case article
case gallery
case checkout
}
Currency
enum Currency: Int {
case USD
case KRW
case AED
case LTL
case ARS
case MAD
case AUD
case MXN
case BGN
case MYR
case BOB
case NOK
case BRL
case NZD
case CAD
case PEN
case CHF
case PHP
case CLP
case PKR
case CNY
case PLN
case COP
case RON
case CZK
case RSD
case DKK
case RUB
case EGP
case SAR
case EUR
case SEK
case GBP
case SGD
case HKD
case THB
case HRK
case TRY
case HUF
case TWD
case IDR
case UAH
case ILS
case VEF
case INR
case VND
case JPY
case ZAR
}
LogLevel
enum LogLevel: Int {
case none
case debug
case info
}
6. Upgrade the Wunderkind-SDK
💬To upgrade the Wunderkind-SDK please follow the steps in Podfile Modification, as well as incorporating any necessary Code Modifications that have been released since the currently implemented version in your app. Latest Wunderkind-SDK version: 1.4.1
Podfile Modification
If the Podfile is targeting the latest version of the Wunderkind SDK, no Podfile modification is needed.
platform :ios, '11.0'
use_frameworks!
target 'AppTarget' do
pod 'Wunderkind' , podspec: 'https://storage.googleapis.com/wunderkind-ios-sdk/latest.podspec'
end
If the Podfile is targeting a previous specific version of the Wunderkind SDK, please manually change it to 1.4.1.
platform :ios, '11.0'
use_frameworks!
target 'AppTarget' do
pod 'Wunderkind' , podspec: 'https://storage.googleapis.com/wunderkind-ios-sdk/1.4.1.podspec'
end
Then to install the 1.4.1 Wunderkind SDK version run the below command:
pod install --repo-update
Code Modifications
⚡️ 1.4.0
Modifiable Variables removed
Any code referenced below should be omitted.
Wunderkind.shared.visitSessionInterval
Wunderkind.shared.metricsInterval
Phone now Int
phone
should be passed as an Int to ensure proper handling in all methods.
⚠️ Ifphone
is deemed not valid they will not be tracked
and the below warning log will be emitted-
Unfortunately, eventName hasn't been tracked since you
have provided a nullable parameter or a not valid one.
Please update all methods including Login, Conversion, and TextOptIn Events.
Customer isHashed
parameter removed
This parameter can be removed, if sending hashed data use refer to our hashed guide.
Existing LoggedIn and LoginMethod removed
The following LoggedIn functions involving Existing and LoginMethod have been removed, please remove these functions and replace with the correct LoggedIn functions.
@available(* , deprecated, renamed: "trackLoggedIn(email:)")
func trackExistingLoggedIn(email: String)
---------
@available(* , deprecated, renamed: "trackLoggedIn(email:phone:)")
func trackExistingLoggedIn(email: String, phone: String)
---------
@available(* , deprecated, renamed: "trackHashedLoggedIn(email:)")
func trackHashedExistingLoggedIn(email: String)
---------
@available(* , deprecated, renamed: "trackHashedLoggedIn(email:phone:)")
func trackHashedExistingLoggedIn(email: String, phone: String)
---------
@available(* , deprecated, renamed: "trackLoggedIn(email:)")
func trackLoggedIn(email: String, method: LoginMethod)
---------
@available(* , deprecated, renamed: "trackLoggedIn(email:phone:)")
func trackLoggedIn(email: String, method: LoginMethod, phone: String)
---------
@available(* , deprecated, renamed: "trackHashedLoggedIn(email:)")
func trackHashedLoggedIn(email: String, method: LoginMethod)
---------
@available(* , deprecated, renamed: "trackHashedLoggedIn(email:phone:)")
func trackHashedLoggedIn(email: String, method: LoginMethod, phone: String)
Example:
Wunderkind.shared.trackLoggedIn(email: "testemail@gmail.com" , method: LoginMethod.Apple)
->
Wunderkind.shared.trackLoggedIn(email: "testemail@gmail.com")
⚡️ 1.3.4
Location Tracking
Location Tracking has been removed, any code referenced below can be omitted.
Wunderkind.shared.isLocationTrackingEnabled
⚡️ 1.3.3
IDFA Tracking
IDFA Tracking has been removed, any code referenced below can be omitted.
Wunderkind.shared.isIDFATrackingEnabled
⚡️ 1.2.5
The following LoggedIn functions involving Existing and LoginMethod have been marked for deprecation, please remove these functions and replace with the corresponding function.
@available(* , deprecated, renamed: "trackLoggedIn(email:)")
func trackExistingLoggedIn(email: String)
---------
@available(* , deprecated, renamed: "trackLoggedIn(email:phone:)")
func trackExistingLoggedIn(email: String, phone: String)
---------
@available(* , deprecated, renamed: "trackHashedLoggedIn(email:)")
func trackHashedExistingLoggedIn(email: String)
---------
@available(* , deprecated, renamed: "trackHashedLoggedIn(email:phone:)")
func trackHashedExistingLoggedIn(email: String, phone: String)
---------
@available(* , deprecated, renamed: "trackLoggedIn(email:)")
func trackLoggedIn(email: String, method: LoginMethod)
---------
@available(* , deprecated, renamed: "trackLoggedIn(email:phone:)")
func trackLoggedIn(email: String, method: LoginMethod, phone: String)
---------
@available(* , deprecated, renamed: "trackHashedLoggedIn(email:)")
func trackHashedLoggedIn(email: String, method: LoginMethod)
---------
@available(* , deprecated, renamed: "trackHashedLoggedIn(email:phone:)")
func trackHashedLoggedIn(email: String, method: LoginMethod, phone: String)
Example:
Wunderkind.shared.trackLoggedIn(email: "testemail@gmail.com" , method: LoginMethod.Apple)
->
Wunderkind.shared.trackLoggedIn(email: "testemail@gmail.com")
⚡️ 1.2.0
- Please ensure the trigger of a TextOptIn Event when a user opts into text messaging.
- Please input the phone parameter to LoggedIn Event.
Text Opt In Event
Overview
This event is triggered when a user opts in to text messaging.
💬 Pass nil for languageCode, unless the desired language is French then pass a String with value “fr”
Wunderkind.shared.trackTextOptIn(phoneNumber: String, languageCode: String?)
Example Implementation:
final class SignupViewController: BaseViewController {
...
func textOptInSelected(givenPhoneNumber: String, selectedLanguage: String) {
if (selectedLanguage == "french"){
Wunderkind.shared.trackTextOptIn(phoneNumber: givenPhoneNumber, languageCode: "fr")
}
else {
Wunderkind.shared.trackTextOptIn(phoneNumber: givenPhoneNumber, languageCode: null)
}
}
}
LoggedIn Event- Phone Parameter
Overview
Please include the new phone parameter on trackLoggedIn events.
Wunderkind.shared.trackLoggedIn(email: String, method: LoginMethod, phone: String)
💬Please pass phone
in the following format (country code)(phone number)
Example: 13305851212
Example Implementation:
final class LoginViewController: BaseViewController {
...
func loginWasSuccessfulViaGoogleSignIn() {
// This event is triggered when a user explicitly successfully signed in to their app.
Wunderkind.shared.trackLoggedIn(email: emailTextField.text, method: .google, phone: phoneTextField.text)
}
}
7. Change Log
Version | Release Date | Details |
---|---|---|
1.4.1 |
09.05.2024 | • Internal SDK's fixes and improvements. |
1.4.0 |
08.12.2024 |
|
1.3.4 | 05.13.2024 | • remove isLocationTrackingEnabled
|
1.3.3 | 04.19.2024 | • Privacy Manifest, remove isIDFATrackingEnabled
|
1.2.5 | 02.27.2024 | • Remove LoginMethod Parameter, ExistingLoggedIn Methods |
1.2.0 | 01.08.2024 | • New events: TextOptIn, LoggedIn- Phone Parameter. |
1.1.0 | 10.10.2023 | • New events: LoggedOut. |
1.0.8 | 04.19.2023 | • Internal SDK's fixes and improvements. |
1.0.7 | 01.10.2023 | • Internal SDK's fixes and improvements. |
1.0.6 | 10.05.2022 | • Internal SDK's fixes and improvements. |
1.0.5 | 09.12.2022 | • Internal SDK's fixes and improvements. |
1.0.4 | 08.23.2022 | • ScreenType is required for ScreenView Event. • trackExistingLoggedIn event endpoint created. • Checkout ScreenType added. |
1.0.3 | 03.31.2022 | • Internal SDK's fixes and improvements. |
1.0.2 | 01.26.2022 | • Fixes bug related to public property Wunderkind.sdkVersion .• Slightly updates events payload and dispatch functionality. • Fixes minimum deployment target warning message. • Updates framework's name from Wunderkind to WunderkindKit. |
1.0.1 | 08.27.2021 | • Decreases minimum deployment target to 11.0. • Increases test coverage. |
1.0.0 | 07.07.2021 | • Initial Wunderkind SDK release. |
8. License
Distributed under the MIT License. To view the full license, visit http://www.wunderkind.co/legal/sdklicense-agreement