This library is the official Swift SDK of Visilabs for native IOS projects. The library is written with Swift 5 and minimum deployment target is 10.
If you are using a lower version of Swift or minimum deployment target of your project is lower than 10, we recommend using Objective-C Library.
To run the example project, clone the repo, and run pod install
from the Example directory.
VisilabsIOS is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'VisilabsIOS'
Import VisilabsIOS in AppDelegate.swift and call createAPI
method within application:didFinishLaunchingWithOptions:
method.
The code below is a sample initialization of Visilabs library.
import VisilabsIOS
func application(_ application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Visilabs.createAPI(organizationId: "YOUR_ORGANIZATION_ID", profileId: "YOUR_PROFILE_ID"
, dataSource: "YOUR_DATASOURCE", inAppNotificationsEnabled: false, channel: "IOS"
, requestTimeoutInSeconds: 30, geofenceEnabled: false, maxGeofenceCount: 20, isIDFAEnabled: true)
return true
}
createAPI
, a dialog to request permission from end user will open and according to choice of the user, the value of AdvertisingTrackingID will be sent to Visilabs servers. If you want to show your prompt at another time instead of when the app is opened you need to set the value isIDFAEnabled to false and call the public requestIDFA
function whenever you want to show prompt. Click here for detailed informationYou can turn on logging by setting loggingEnabled
property to true
. If enabled the
Visilabs.callAPI().loggingEnabled = true
The default protocol for requests to Visilabs servers is https
. If you want to debug your requests more easily, you can change your protocol by setting insecureProtocol
property to true
.
Visilabs.callAPI().insecureProtocol = true
Vislabs uses events to collect data from IOS applications. The developer needs to implement the methods provided by SDK. customEvent
is a generic method to track user events. customEvent
takes 2 parameters: pageName and properties.
In SDK, apart from customEvent
, there are 2 other methods to collect data: login
and signUp
. As in the customEvent
method, the login
and signUp
methods also take a mandatory and an optional parameter. The first parameter is exVisitorId
which uniquely identifies the user and can not be empty. The second parameter properties
is optional and passsing an empty dictionary also valid.
Some of the most common events:
Visilabs.callAPI().signUp(exVisitorId: "userId")
Moreover, you can pass additional information to the optional parameter properties
when user signs up. The following example shows the call of signUp
method with properties which includes OM.sys.TokenID
and OM.sys.AppID
parameters. OM.sys.TokenID
and OM.sys.AppID
are required to send push notifications and OM.sys.AppID
parameter can be obtained by RMC web panel.
var properties = [String:String]()
properties["OM.sys.TokenID"] = "F7C5231053E6EC543B8930FB440752E2FE41B2CFC2AA8F4E9C4843D347E6A847" // Token ID to use for push messages
properties["OM.sys.AppID"] = "VisilabsIOSExample" //App ID to use for push messages
Visilabs.callAPI().signUp(exVisitorId: "userId", properties: properties)
Like signUp
method login
method can be called with or without optional parameter properties
.
Visilabs.callAPI().login(exVisitorId: "userId")
var properties = [String:String]()
properties["OM.sys.TokenID"] = "F7C5231053E6EC543B8930FB440752E2FE41B2CFC2AA8F4E9C4843D347E6A847" // Token ID to use for push messages
properties["OM.sys.AppID"] = "VisilabsIOSExample" //App ID to use for push messages
Visilabs.callAPI().login(exVisitorId: "userId", properties: properties)
Moreover you can add user segment parameters to properties
.
var properties = [String:String]()
properties["OM.vseg1"] = "seg1val" // Visitor Segment 1
properties["OM.vseg2"] = "seg2val" // Visitor Segment 2
properties["OM.vseg3"] = "seg3val" // Visitor Segment 3
properties["OM.vseg4"] = "seg4val" // Visitor Segment 4
properties["OM.vseg5"] = "seg5val" // Visitor Segment 5
properties["OM.bd"] = "1977-03-15" // Birthday
properties["OM.gn"] = "f" // Gender
properties["OM.loc"] = "Bursa" // Location
Visilabs.callAPI().login(exVisitorId: "userId", properties: properties)
Use the following implementation of customEvent
method to record the page name the visitor is currently viewing. You may add extra parameters to properties dictionary or you may leave it empty.
Visilabs.callAPI().customEvent("Frequently Asked Questions" /*Page Name*/, properties: [String:String]())
Use the following implementation of customEvent
when the user displays a product in the mobile app.
var properties = [String:String]()
properties["OM.pv"] = "12345" // Product Code
properties["OM.pn"] = "USB Charger" // Product Name
properties["OM.ppr"] = 125.49" // Product Price
properties["OM.pv.1"] = "Sample Brand" // Product Brand
properties["OM.inv"] = "5" // Number of items in stock
Visilabs.callAPI().customEvent("Product View", properties: properties)
Use the following implementation of customEvent
when the user adds items to the cart or removes.
var properties = [String:String]()
properties["OM.pbid"] = "bid-12345678" // Basket ID
properties["OM.pb"] = "12345;23456" // Product1 Code;Product2 Code
properties["OM.pu"] = "3;1" // Product1 Quantity;Product2 Quantity
properties["OM.ppr"] = "376.47;23.50" // Product1 Price*Product1 Quantity;Product2 Price*Product2 Quantity
Visilabs.callAPI().customEvent("Cart", properties: properties)
Use the following implementation of customEvent
when the user buys one or more items.
var properties = [String:String]()
properties["OM.tid"] = "oid-12345678" // Order ID/Transaction ID
properties["OM.pp"] = "12345;23456" // Product1 Code;Product2 Code
properties["OM.pu"] = "3;1" // Product1 Quantity;Product2 Quantity
properties["OM.ppr"] = "376.47;23.50" // Product1 Price*Product1 Quantity;Product2 Price*Product2 Quantity
Visilabs.callAPI().customEvent("Purchase", properties: properties)
When the user views a category list page, use the following implementation of customEvent
.
var properties = [String:String]()
properties["OM.clist"] = "c-14" // Category Code/Category ID
Visilabs.callAPI().customEvent("Category View", properties: properties)
If the mobile app has a search functionality available, use the following implementation of customEvent
.
var properties = [String:String]()
properties["OM.OSS"] = "USB" // Search Keyword
properties["OM.OSSR"] = "61" // Number of Search Results
Visilabs.callAPI().customEvent("In App Search", properties: properties)
You can monitor banner click data using the following implementation of customEvent
.
var properties = [String:String]()
properties["OM.OSB"] = "b-666" // Banner Name/Banner Code
Visilabs.callAPI().customEvent("Banner Click", properties: properties)
When the user adds a product to their favorites, use the following implementation of customEvent
.
var properties = [String:String]()
properties["OM.pf"] = "12345" // Product Code
properties["OM.pfu"] = "1"
properties["OM.ppr"] = 125.49" // Product Price
Visilabs.callAPI().customEvent("Add To Favorites", properties: properties)
When the user removes a product from their favorites, use the following implementation of customEvent
.
var properties = [String:String]()
properties["OM.pf"] = "12345" // Product Code
properties["OM.pfu"] = "-1"
properties["OM.ppr"] = 125.49" // Product Price
Visilabs.callAPI().customEvent("Add To Favorites", properties: properties)
After launching the application by clicking on a push message, use the following implementation of customEvent
.
var properties = [String:String]()
properties["utm_source"] = "euromsg" // utm_source value in the payload of push notification
properties["utm_medium"] = "push" // utm_medium value in the payload of push notification
properties["utm_campaign"] = "euromsg campaign" // utm_campaign value in the payload of push notification
Visilabs.callAPI().customEvent("Login", properties: properties)
Also you can send properties without setting page name.
var properties = [String:String]()
properties["utm_source"] = "euromsg" // utm_source value in the payload of push notification
properties["utm_medium"] = "push" // utm_medium value in the payload of push notification
properties["utm_campaign"] = "euromsg campaign" // utm_campaign value in the payload of push notification
Visilabs.callAPI().sendCampaignParameters(properties: properties)
Visilabs needs to receive token to send push messages to users. The token value generated by APNS will be the value of the OM.sys.TokenID
key. The value of the OM.sys.AppID
could be obtained by RMC administration panel. Follow the link https://intelligence.relateddigital.com/a02/index#/Push/AppList and select the relevant push application. The value of App Alias
refers to OM.sys.AppID
. If you have problems, please contact RMC support team.
var properties = [String:String]()
properties["OM.sys.TokenID"] = "F7C5231053E6EC543B8930FB440752E2FE41B2CFC2AA8F4E9C4843D347E6A847" // Token ID to use for push messages
properties["OM.sys.AppID"] = "VisilabsIOSExample" //App ID to use for push messages
Visilabs.callAPI().customEvent("RegisterToken", properties: properties)
You can call the requestIDFA
function whenever you want to show App Tracking Transparency
prompt to request IDFA and send the value to Visilabs servers.
Visilabs.callAPI().requestIDFA()
You can call the sendLocationPermission
method to to send the location permission status of your users to Visilabs servers and use this information on the panel later.
Visilabs.callAPI().sendLocationPermission()
This information is sent with the OM.locpermit
parameter and can take one of the following 3 values:
In-app messages are notifications to your users when they are directly active in your mobile app. To enable In-App Messaging feature you need to set the value of inAppNotificationsEnabled
parameter when calling createAPI
to initialize the SDK.
import VisilabsIOS
func application(_ application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Visilabs.createAPI(organizationId: "YOUR_ORGANIZATION_ID", profileId: "YOUR_PROFILE_ID"
, dataSource: "YOUR_DATASOURCE", inAppNotificationsEnabled: true, channel: "IOS"
, requestTimeoutInSeconds: 30, geofenceEnabled: false, maxGeofenceCount: 20)
return true
}
The existence of a relevant in-app message for an event controlled by after each customEvent
call. You can create and customize your in-app messages on https://intelligence.relateddigital.com/#Target/TargetingAction/TAList page of RMC administration panel.
There are 9 types of in-app messages:
Pop-up - Image, Header, Text & Button | Mini-icon&text | Full Screen-image |
---|---|---|
Full Screen-image&button | Pop-up - Image, Header, Text & Button | Pop-up-Survey |
Pop-up - NPS with Text & Button | Native Alert & Actionsheet | NPS with numbers |
If you want to manage the links you add for in-app messages yourself, you can follow the step below.
First you have to call the delegate method
Visilabs.callAPI().inappButtonDelegate = self
Then you have to add the extension and you can delete the print codes and write your own codes.
extension EventViewController: VisilabsInappButtonDelegate {
func didTapButton(_ notification: VisilabsInAppNotification) {
print("notification did tapped...")
print(notification)
}
}
You can access favorite attributes of the Targeting Actions of type Favorite Attribute Action that you defined from the https://intelligence.relateddigital.com/#Target/TargetingAction/TAList/ section on the RMC panel via the mobile application as follows.
Visilabs.callAPI().getFavoriteAttributeActions { (response) in
if let error = response.error {
print(error)
} else {
if let favoriteBrands = response.favorites[.brand] {
for brand in favoriteBrands {
print(brand)
}
}
if let favoriteCategories = response.favorites[.category] {
for category in favoriteCategories {
print(category)
}
}
}
}
You can also access favorite attributes of a particular Targeting Action by specifying the ID.
Visilabs.callAPI().getFavoriteAttributeActions(actionId: 188) { (response) in
if let error = response.error {
print(error)
} else {
if let favoriteBrands = response.favorites[.brand] {
for brand in favoriteBrands {
print(brand)
}
}
if let favoriteCategories = response.favorites[.category] {
for category in favoriteCategories {
print(category)
}
}
}
}
favorites
property of response
object is a dictionary which has an enum
as key and an array
of String
s as value. The cases of VisilabsFavoriteAttribute
enum
are the followings:
public enum VisilabsFavoriteAttribute: String {
case ageGroup
case attr1
case attr2
case attr3
case attr4
case attr5
case attr6
case attr7
case attr8
case attr9
case attr10
case brand
case category
case color
case gender
case material
case title
}
Story actions allow you to add widgets similar to "Instagram Story" list view on your iOS devices. getStoryView
method returns an instance of VisilabsStoryHomeView
which is a subclass of UIView
.
let storyView = Visilabs.callAPI().getStoryView()
view.addSubview(storyHomeView)
You can also access a story action by specifying the ID of the Targeting Action.
let storyView = Visilabs.callAPI().getStoryView(actionId: 67)
view.addSubview(storyHomeView)
If you add a clickable URL, framework handle to open it on browser (or direct by deeplink). However, if you want to handle by yourself, extend your class that conforms VisilabsStoryURLDelegate, as following;
extension StoryViewController: VisilabsStoryURLDelegate {
func urlClicked(_ url: URL) {
//TO DO
}
}
After you add this, you can set urlDelegate self.
let storyView = Visilabs.callAPI().getStoryView(actionId: 67, urlDelegate: self)
view.addSubview(storyHomeView)
If you set delegate, then clickable URL will not be handled by SDK!
There is also an asynchronous version of getStoryView
method called getStoryViewAsync
which takes an completionHandler that receives an optional VisilabsStoryHomeView
object. If there is no Story Action matching your criteria completionHandler returns nil
.
Visilabs.callAPI().getStoryViewAsync(actionId: 55){ storyHomeView in
if let storyHomeView = storyHomeView {
} else {
print("There is no story action matching your criteria.")
}
}
To enable location services in your application first of all you need to add the following keys to your Info.plist
file.
An example implementation of these permissions as follows:
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>We need access to your location for better user experience.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>We need access to your location for better user experience.</string>
You also need to add the following keys under UIBackgroundModes
in your Info.plist
file to monitor regions, refresh region list and receive push notifications.
<array>
<string>fetch</string>
<string>location</string>
<string>remote-notification</string>
</array>
When initializing Visilabs SDK you need to set geofenceEnabled
parameter of createAPI
method to true
. You may also change the maxGeofenceCount
to a value lower than 20. Apple prevents any single application from monitoring more than 20 regions simultaneously. Visilabs can use all these slots.
import VisilabsIOS
func application(_ application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Visilabs.createAPI(organizationId: "YOUR_ORGANIZATION_ID", profileId: "YOUR_PROFILE_ID"
, dataSource: "YOUR_DATASOURCE", inAppNotificationsEnabled: false, channel: "IOS"
, requestTimeoutInSeconds: 30, geofenceEnabled: true, maxGeofenceCount: 20)
return true
}
After form is created at RMC panel, likewise in-app message, existence of mail subscription form is controlled by after each customEvent
call. It is shown as follows;
After form is created at RMC panel, likewise in-app message, existence of spin to win is controlled by after each customEvent
call. It opens a WebViewController. It is shown as follows;
Spin to Win Full | Spin to Win Half |
---|---|
To display an Inline Nps with Numbers view, you can call the getNpsWithNumbersView method, which takes a properties parameter of type [String: String]
, a delegate
parameter containing the npsItemClicked
method, and a completionHandler
that receives an optional VisilabsNpsWithNumbersContainerView
object.
The delegate
parameter is used to handle button click event, and contains a method called npsItemClicked
that is triggered when the user taps on a button.
The completionHandler
receives an optional VisilabsNpsWithNumbersContainerView
object, which is only returned if there is an action matching the given criteria. If there is no matching action, the completionHandler
will return nil
.
Visilabs.callAPI().getNpsWithNumbersView(properties: props, delegate: self){ npsView in
DispatchQueue.main.async {
if let npsView = npsView {
self.npsView = npsView
self.npsView = npsView
self.view.addSubview(npsView)
npsView.translatesAutoresizingMaskIntoConstraints = false
npsView.topAnchor.constraint(equalTo: self.npsWithNumbersButton.bottomAnchor, constant: -50).isActive = true
npsView.widthAnchor.constraint(equalTo: self.view.saferAreaLayoutGuide.widthAnchor).isActive = true
npsView.heightAnchor.constraint(equalToConstant: 550).isActive = true
} else {
print("There is no nps action matching your criteria.")
}
}
}
extension NpsViewController: VisilabsNpsWithNumbersDelegate {
func npsItemClicked(npsLink: String?) {
print(npsLink)
}
}
Product recommendations are handled by the recommend
method of SDK. You have to pass 3 mandatory arguments which are zoneId
, productCode
and completion
to recommend
method.
completion
parameter is a closure expression which takes an VisilabsRecommendationResponse
instance as input and returns nothing. The structure of VisilabsRecommendationResponse
is shown below:
public class VisilabsRecommendationResponse {
public var products: [VisilabsProduct]
public var error: VisilabsError?
public var widgetTitle: String = ""
internal init(products: [VisilabsProduct], widgetTitle: String = "", error: VisilabsError? = nil) {
self.products = products
self.widgetTitle = widgetTitle
self.error = error
}
}
VisilabsProduct
class has the following properties:
Property | Type |
---|---|
code | String |
title | String |
img | String |
dest_url | String |
brand | String |
price | Double |
dprice | Double |
cur | String |
dcur | String |
freeshipping | Bool |
samedayshipping | Bool |
rating | Int |
comment | Int |
discount | Double |
attr1 | String |
attr2 | String |
attr3 | String |
attr4 | String |
attr5 | String |
If recommended products exist for given arguments in completion
method you need to handle the array of products.
Visilabs.callAPI().recommend(zoneID: "6", productCode: "pc", filters: []){ response in
if let error = response.error {
print(error)
}else{
print("Recommended Products")
for product in response.products{
print("product code: \(product.code) title: \(product.title)")
}
}
}
You may also pass an array of filters to recommend
method. For example the following implementation returns only the products which contains laptop in the title.
var filters = [VisilabsRecommendationFilter]()
let filter = VisilabsRecommendationFilter(attribute: .PRODUCTNAME, filterType: .like, value: "laptop")
filters.append(filter)
Visilabs.callAPI().recommend(zoneID: "6", productCode: "pc", filters: filters){ response in
if let error = response.error{
print(error)
}else{
print("Widget Title: \(response.widgetTitle)")
print("Recommended Products")
for product in response.products{
print("product code: \(product.code) title: \(product.title)")
}
}
}
VisilabsProductFilterAttribute
enum has the following cases and sample values:
case | example |
---|---|
PRODUCTCODE | "" |
PRODUCTNAME | "" |
COLOR | "blue" |
AGEGROUP | "18-40" |
BRAND | "visilabs" |
CATEGORY | "145" |
GENDER | "f" |
MATERIAL | "wood" |
ATTRIBUTE1 | "attr1value" |
ATTRIBUTE2 | "attr2value" |
ATTRIBUTE3 | "attr3value" |
ATTRIBUTE4 | "attr4value" |
ATTRIBUTE5 | "attr5value" |
SHIPPINGONSAMEDAY | "1" |
FREESHIPPING | "1" |
ISDISCOUNTED | "1" |
To report the clicks of widget recommendations you need to call the trackRecommendationClick
method with the qs
property of Product
object.
Visilabs.callAPI().trackRecommendationClick(qs: product.qs)
developer@relateddigital.com