iOS UX Helper
Rokt UX Helper is an open source project that helps you render beautiful customer experiences in a server to server environment. You can find and contribute to the project on the Github page.
This document outlines the process for integrating RoktUXHelper into your iOS app, which works alongside the Server-to-Server integration(S2S) to deliver relevant experiences to your customers as they checkout. This guide assumes you are familiar with UIKit/SwiftUI and basic iOS development concepts.
System | Version |
---|---|
RoktUXHelper | 0.3.1 |
iOS | 15.0+ |
Package Manager | Swift Package Manager |
Swift | 5+ |
Xcode | 15+ |
Installation Guide
The library is available as a Swift Package Manager(SPM) dependency. To install it, add the following SPM dependency into your package.json
file. This configuration ensures that your app will receive updates to the library up to, but not including, the next major release.
dependencies: [
.package(url: "https://github.com/ROKT/rokt-ux-helper-ios.git", .upToNextMajor(from: "0.1.0"))
]
Import Required Modules
To start using RoktLayoutView, you need to import the necessary modules into your view controller or class.
import SwiftUI
import RoktUXHelper
Initialize RoktLayoutView
The RoktLayoutView
class provides multiple initialization options, allowing for configuration flexibility. You can initialize it by passing required bindings and parameters like experienceResponse
, location
name, optional config
, and event handlers.
var body: some View {
RoktLayoutView(experienceResponse: "{experience_response_json}",
location: "RoktEmbedded1",
config: roktConfig,
onUXEvent: { uxEvent in
// Handle UX events here
},
onPlatformEvent: { platformEvent in
// Send these platform events to Rokt API
})
}
UX Events
Use the onUXEvent handler to receive real-time feedback on user interactions.
At a minimum you must handle when a RoktUXEvent.OpenUrl event is triggered so you can open the link using the below example.
OpenUrl & onClose
event.onClose?(event.id)
is critical to be called after a URL has been opened and will notify the RoktUXHelper to execute some logic like moving to the next offer.
onUXEvent: { uxEvent in // Handle UX events here
// Handle open URL event
// Here is a sample how to open different types of URLs
if let event = uxEvent as? RoktUXEvent.OpenUrl,
let url = URL(string: event.url) {
switch event.type {
case .externally:
UIApplication.shared.open(url) { _ in
event.onClose?(event.id) // This must be called when the user is ready for the next offer
}
default:
let safariVC = SFSafariViewController(url: url)
safariVC.modalPresentationStyle = .overFullScreen
if let rootVC = UIApplication.shared.connectedScenes
.compactMap({ ($0 as? UIWindowScene)?.keyWindow }).last?.rootViewController {
rootVC.present(safariVC, animated: true, completion: {
event.onClose?(event.id) // This must be called when the user is ready for the next offer
})
}
}
}
},
All events
UX Events
Event | Description | Params |
---|---|---|
OfferEngagement | Triggered when the user engages with the offer | layoutId: String |
PositiveEngagement | Triggered when the user positively engages with the offer | layoutId: String |
LayoutInteractive | Triggered when a layout has been rendered and is interactable | layoutId: String |
LayoutReady | Triggered when a layout is ready to display but has not rendered content yet | layoutId: String |
LayoutClosed | Triggered when a layout is closed by the user | layoutId: String |
LayoutCompleted | Triggered when the offer progression reaches the end and no more offers are available to display | layoutId: String |
LayoutFailure | Triggered when a layout could not be displayed due to some failure | layoutId: String (optional) |
OpenUrl | Triggered when a link needs to be opened | url: String, id: String, type: OpenURLType (internally/externally/passthrough), onClose: (String) -> Void, onError: (String: Error?) -> Void |
Send platformEvents to Rokt
Platform events are an essential part of integration and it has to be sent to Rokt via your backend. For ease of use, platformEvent is defined as [String: Any]
onPlatformEvent: { platformEvent in
// Send these platform events to Rokt API
},
Example payload
{
"events":[
{
"instanceGuid":"6A764CDC-CCC5-4976-8121-5179E45757FB",
"eventTime":"2024-10-28T03:56:18.502Z",
"pageInstanceGuid":"",
"eventType":"SignalInitialize",
"sessionId":"DE110000-1000-1000-1000-100000000000",
"attributes":[
],
"metadata":[
{
"name":"clientTimeStamp",
"value":"2024-10-28T03:56:18.502Z"
},
{
"name":"captureMethod",
"value":"ClientProvided"
}
],
"token":"...",
"parentGuid":"b2170040-e74f-49db-819e-317ebd7f92ac"
}
],
"integration":{
"deviceLocale":"en_AU",
"version":"1.0",
"packageName":"com.rokt.roktuxhelperdemo.RoktUX-Demo",
"operatingSystemVersion":"17.5",
"deviceType":"Phone",
"platform":"iOS",
"operatingSystem":"iOS",
"deviceModel":"iPhone 16",
"packageVersion":"1.0",
"layoutSchemaVersion":"2.1.0",
"name":"UX Helper iOS",
"framework":"Swift"
}
}
You can find a full list of events here.
Summary
Integrating RoktLayoutView into your iOS app is straightforward and provides a flexible way to manage views and experiments. By following the steps outlined in this guide, you can add RoktLayoutView into your project and take full advantage of the powerful features offered by RoktUXHelper
.
var body: some View {
RoktLayoutView(
experienceResponse: "{experience_response_json}",
location: "RoktEmbedded1",
config: roktConfig,
onUXEvent: { uxEvent in
// Handle UX events here
if let event = uxEvent as? RoktUXEvent.OpenUrl,
let url = URL(string: event.url) {
switch event.type {
case .externally:
UIApplication.shared.open(url) { _ in
event.onClose?(event.id)
}
default:
let safariVC = SFSafariViewController(url: url)
safariVC.modalPresentationStyle = .overFullScreen
if let rootVC = UIApplication.shared.connectedScenes
.compactMap({ ($0 as? UIWindowScene)?.keyWindow }).last?.rootViewController {
rootVC.present(safariVC, animated: true, completion: {
event.onClose?(event.id)
})
}
}
}
},
onPlatformEvent: { platformEvent in
// Send these platform events to Rokt API
}
)
}
Optional: App Configurations
RoktUXConfig enables partner applications to provide custom configuration settings from their app environment. This allows RoktUXHelper to apply these configurations, offering more flexibility and control over the user experience, rather than relying exclusively on system defaults.
// if application supports only Light Mode.
let roktConfig = RoktUXConfig.builder()
.colorMode(.light)
.imageLoader(imageLoader)
.build()
ColorMode object
Value | Description |
---|---|
light | Application is in Light Mode |
dark | Application is in Dark Mode |
system | Application defaults to System Color Mode |
RoktUXImageLoader
Rokt UX Helper accepts an optional RoktUXImageLoader
to give partners flexibility over image downloads. In the sample RoktUXImageLoaderImpl
, images are fetched asynchronously from a URL using URLSession
and returned via a completion handler. If no ImageLoader is provided, RoktUXHelper defaults to using SwiftUI’s AsyncImage.
import UIKit
import RoktUXHelper
class RoktUXImageLoaderImpl : RoktUXImageLoader {
func loadImage(urlString: String, completion: @escaping (Result<UIImage?, any Error>) -> Void) {
guard let url = URL(string: urlString) else { return }
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else { return }
DispatchQueue.main.async {
completion(.success(UIImage(data: data)))
}
}
task.resume()
}
}
Fonts
Rokt UX Helper will be able to utilise custom fonts by simply registering them to your project and having them configured on your Rokt account in One Platform.
Installation Guide
The library is available as a Swift Package Manager(SPM) dependency. To install it, add the following SPM dependency into your package.json
file. This configuration ensures that your app will receive updates to the library up to, but not including, the next major release.
dependencies: [
.package(url: "https://github.com/ROKT/rokt-ux-helper-ios.git", .upToNextMajor(from: "0.1.0"))
]
Import Required Modules
To start using RoktLayoutUIView, you need to import the necessary modules into your view controller or class.
import UIKit
import RoktUXHelper
Initialize RoktLayoutUIView
The RoktLayoutUIView
class provides multiple initialization options, allowing for configuration flexibility. You can initialize it with an experienceResponse
, location
name and optional configuration parameters such as RoktUXConfig
, and event handlers.
func loadRokt() {
let experienceResponse = "{experience_response_json}"
let roktView = RoktLayoutUIView(
experienceResponse: experienceResponse,
location: "RoktEmbedded1",
config: roktConfig,
onUXEvent: { uxEvent in
// Handle UX events here
},
onPlatformEvent: { platformEvent in
// Send these platform events to Rokt API
},
onEmbeddedSizeChange: { newSize in
// Handle view size changes if required
}
)
}
Add the View to Your Layout
Once initialized, you need to add the RoktLayoutUIView
to your view hierarchy. You can do this programmatically in your view controller by setting constraints or positioning manually.
// Add the RoktLayoutUIView to the view hierarchy
self.view.addSubview(roktView)
// Set constraints to position the RoktLayoutUIView
roktView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
roktView.topAnchor.constraint(equalTo: self.view.topAnchor),
roktView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
roktView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
// Adjust the rest as needed
])
UX Events
Use the onUXEvent handler to receive real-time feedback on user interactions.
At a minimum you must handle when a RoktUXEvent.OpenUrl event is triggered so you can open the link using the below example.
OpenUrl & onClose
event.onClose?(event.id)
is critical to be called after a URL has been opened and will notify the RoktUXHelper to execute some logic like moving to the next offer.
onUXEvent: { uxEvent in // Handle UX events here
// Handle open URL event
// Here is a sample how to open different types of URLs
if let event = uxEvent as? RoktUXEvent.OpenUrl,
let url = URL(string: event.url){
switch event.type {
case .externally:
UIApplication.shared.open(url) { _ in
event.onClose?(event.id) // This must be called when the user is ready for the next offer
}
default:
let safariVC = SFSafariViewController(url: url)
safariVC.modalPresentationStyle = .overFullScreen
self.present(safariVC, animated: true, completion: {
event.onClose?(event.id) // This must be called when the user is ready for the next offer
})
}
}
},
All events
UX Events
Event | Description | Params |
---|---|---|
OfferEngagement | Triggered when the user engages with the offer | layoutId: String |
PositiveEngagement | Triggered when the user positively engages with the offer | layoutId: String |
LayoutInteractive | Triggered when a layout has been rendered and is interactable | layoutId: String |
LayoutReady | Triggered when a layout is ready to display but has not rendered content yet | layoutId: String |
LayoutClosed | Triggered when a layout is closed by the user | layoutId: String |
LayoutCompleted | Triggered when the offer progression reaches the end and no more offers are available to display | layoutId: String |
LayoutFailure | Triggered when a layout could not be displayed due to some failure | layoutId: String (optional) |
OpenUrl | Triggered when a link needs to be opened | url: String, id: String, type: OpenURLType (internally/externally/passthrough), onClose: (String) -> Void, onError: (String: Error?) -> Void |
Send platformEvents to Rokt
Platform events are an essential part of integration and it has to be sent to Rokt via your backend. For ease of use, platformEvent is defined as [String: Any]
onPlatformEvent: { platformEvent in
// Send these platform events to Rokt API
},
Example payload
{
"events":[
{
"instanceGuid":"6A764CDC-CCC5-4976-8121-5179E45757FB",
"eventTime":"2024-10-28T03:56:18.502Z",
"pageInstanceGuid":"",
"eventType":"SignalInitialize",
"sessionId":"DE110000-1000-1000-1000-100000000000",
"attributes":[
],
"metadata":[
{
"name":"clientTimeStamp",
"value":"2024-10-28T03:56:18.502Z"
},
{
"name":"captureMethod",
"value":"ClientProvided"
}
],
"token":"...",
"parentGuid":"b2170040-e74f-49db-819e-317ebd7f92ac"
}
],
"integration":{
"deviceLocale":"en_AU",
"version":"1.0",
"packageName":"com.rokt.roktuxhelperdemo.RoktUX-Demo",
"operatingSystemVersion":"17.5",
"deviceType":"Phone",
"platform":"iOS",
"operatingSystem":"iOS",
"deviceModel":"iPhone 16",
"packageVersion":"1.0",
"layoutSchemaVersion":"2.1.0",
"name":"UX Helper iOS",
"framework":"Swift"
}
}
You can find a full list of events here.
Summary
Integrating RoktLayoutUIView into your iOS app is straightforward and provides a flexible way to manage views and experiments. By following the steps outlined in this guide, you can add RoktLayoutUIView into your project and take full advantage of the powerful features offered by RoktUXHelper
.
import UIKit
import RoktUXHelper
import SafariServices
class ViewController: UIViewController {
// RoktUXImageLoader Implementation to download images
let imageLoader: RoktUXImageLoader = RoktUXImageLoaderImpl()
lazy var roktConfig = RoktUXConfig.builder().imageLoader(imageLoader).build()
override func viewDidLoad() {
super.viewDidLoad()
loadRokt()
}
func loadRokt() {
let experienceResponse = "{experience_response_json}"
let roktView = RoktLayoutUIView(
experienceResponse: experienceResponse,
location: "RoktEmbedded1",
config: roktConfig,
onUXEvent: { uxEvent in // Handle UX events here
// Handle open URL event
// Here is a sample how to open different types of URLs
if let event = uxEvent as? RoktUXEvent.OpenUrl,
let url = URL(string: event.url){
switch event.type {
case .externally:
UIApplication.shared.open(url) { _ in
event.onClose?(event.id)
}
default:
let safariVC = SFSafariViewController(url: url)
safariVC.modalPresentationStyle = .overFullScreen
self.present(safariVC, animated: true, completion: {
event.onClose?(event.id)
})
}
}
},
onPlatformEvent: { platformEvent in
// Send these platform events to Rokt API
},
onEmbeddedSizeChange: { newSize in
// Handle view size changes if required
}
)
self.view.addSubview(roktView)
// Add the RoktLayoutUIView to the view hierarchy
roktView.translatesAutoresizingMaskIntoConstraints = false
// Set constraints to position the RoktLayoutUIView
NSLayoutConstraint.activate([
roktView.topAnchor.constraint(equalTo: self.view.topAnchor),
roktView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
roktView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
// Adjust the rest as needed
])
}
class RoktUXImageLoaderImpl : RoktUXImageLoader {
func loadImage(urlString: String, completion: @escaping (Result<UIImage?, any Error>) -> Void) {
guard let url = URL(string: urlString) else { return }
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else { return }
DispatchQueue.main.async {
completion(.success(UIImage(data: data)))
}
}
task.resume()
}
}
}
Optional: App Configurations
RoktUXConfig enables partner applications to provide custom configuration settings from their app environment. This allows RoktUXHelper to apply these configurations, offering more flexibility and control over the user experience, rather than relying exclusively on system defaults.
// if application supports only Light Mode.
let roktConfig = RoktUXConfig.builder()
.colorMode(.light)
.imageLoader(imageLoader)
.build()
ColorMode object
Value | Description |
---|---|
light | Application is in Light Mode |
dark | Application is in Dark Mode |
system | Application defaults to System Color Mode |
RoktUXImageLoader
Rokt UX Helper accepts an optional RoktUXImageLoader
to give partners flexibility over image downloads. In the sample RoktUXImageLoaderImpl
, images are fetched asynchronously from a URL using URLSession
and returned via a completion handler. If no ImageLoader is provided, RoktUXHelper defaults to using SwiftUI’s AsyncImage.
import UIKit
import RoktUXHelper
class RoktUXImageLoaderImpl : RoktUXImageLoader {
func loadImage(urlString: String, completion: @escaping (Result<UIImage?, any Error>) -> Void) {
guard let url = URL(string: urlString) else { return }
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else { return }
DispatchQueue.main.async {
completion(.success(UIImage(data: data)))
}
}
task.resume()
}
}
Fonts
Rokt UX Helper will be able to utilise custom fonts by simply registering them to your project and having them configured on your Rokt account in One Platform.