The Ravelin Mobile SDKs are critical to our ability to provide informed decisions to our clients.
Like the JavaScript library, the SDK enables:
We have two frameworks within the SDK:
We also have a legacy “fat” framework, available for both core and encrypt modules, on versions 1.0.2 and below. However, were possible, we recommend that you use the XCFramework distribution, since the legacy frameworks will no longer have new updates.
You can choose what functionality of the SDK you would like to use. However, at a mimimum we advise that you use the SDK to generate a reliable device ID and to send the additional device details for your app traffic. Device IDs are critical throughout our fraud prevention tool, especially for use in our graph database.
Before you can integrate with the Ravelin mobile SDK for iOS, you will need to:
If you have any questions on getting started, please ask us in your Ravelin support channel on Slack.
The SDK supports a minimum iOS 9 with some exceptions around encryption written up below.
For Encryption:
If you would like to use encryption it’s only available for iOS 10 and above, where you can use the RavelinEncrypt.xcframework
module which relies on native encryption.
The SDK is available via Cocoapods or Swift Swift Package Manager(SPM).
Add RavelinCore to your PodFile:
pod 'RavelinCore', '1.1.1', :source => 'https://github.com/unravelin/Specs.git'
Then, from the command line: pod install
If you are using encryption also add RavelinEncrypt to your PodFile.
pod 'RavelinEncrypt', '1.1.1, :source => 'https://github.com/unravelin/Specs.git'
Add RavelinCore via Xcode, Add Package Dependency: a package manifest is available at: git@github.com:unravelin/ravelin-core-ios-xcframework-distribution.git
If you are using encryption also add the encrypt module that is available at: git@github.com:unravelin/ravelin-encrypt-ios-xcframework-distribution.git
Swift Package Manager support is only available from version 1.1.0
In your PodFile change the version to the latest SDK version number.
Use the Cocoapod command line and run pod update RavelinCore
(for deviceId, fingerprinting and tracking activity) and/or pod update RavelinEncrypt
(if using encryption) to update the SDK with the new version.
To verify the latest Ravelin SDK version check our Release Notes section.
You can update to the latest version of any packages you depend on by selecting File ▸ Swift Packages ▸ Update to Latest Package Versions.
Before v1.1.0 the SDK was only available as a “fat” framework, since v1.1.0 and above we have updated to use the XCFrameworks.
To update to the XCFrameworks in your project’s Podfile, change from using:
'pod 'RavelinCore', '1.0.2' or: pod 'RavelinCore'
to:
pod 'RavelinCore', '1.1.1', :source => 'https://github.com/unravelin/Specs.git'
If you are using encryption follow the above steps for RavelinEncrypt.
To verify the latest Ravelin SDK version check our Release Notes section.
To use the framework within your project, import RavelinCore and/or RavelinEncrypt where required:
Objective-C
#import <RavelinCore/Ravelin.h>
#import <RavelinEncrypt/RavelinEncrypt.h>
Swift
import RavelinCore
import RavelinEncrypt
The singleton Ravelin class should be accessed via the sharedInstance
method. You will first need to initialise the SDK with the createInstance
method call with your Ravelin Publishable API Key. See the Authentication for where to find this key.
Please ensure you use your Publishable API Key. Your Secret API Key should never be embedded in your app – it should only be used to send requests from your backend to api.ravelin.com.
The singleton RVNEncryption class should be accessed via the sharedInstance
method. You must then provide your RSA key for card encryption.
Objective-C
// Instantiation for tracking only
self.ravelin = [Ravelin createInstance:@"publishable_key_live_----"];
// Instantiation for encryption
self.ravelinEncrypt = [RVNEncryption sharedInstance];
self.ravelinEncrypt.rsaKey = @"----|----";
Swift
// Instantiation for tracking only
let ravelin = Ravelin.createInstance("publishable_key_live_----")
// Instantiation for encryption
let ravelinEncrypt = RVNEncryption.sharedInstance()
ravelinEncrypt.rsaKey = "----|----"
Once initialised, you can use the sharedInstance
directly to access methods and properties.
Objective-C
// Directly
[[Ravelin sharedInstance] methodName];
[[RVNEncryption sharedInstance]] methodName];
// Variable
Ravelin *ravelin = [Ravelin sharedInstance];
RVNEncryption *ravelinEncrypt = [RVNEncryption sharedInstance];
Swift
// Directly
Ravelin.sharedInstance().methodName()
RVNEncryption.sharedInstance().methodName()
// Variable
let ravelin = Ravelin.sharedInstance()
let ravelinEncrypt = RVNEncryption.sharedInstance()
Depending on your integration, you may want to encrypt card details via the SDK. The SDK can be used to allow the secure sharing of card information with Ravelin whilst removing the need to handle PCI-compliant data.
When collecting the card details, using encrypt(pan, month, year, nameOnCard)
, pan
, month
, year
are required, while nameOnCard
is optional and may be an empty string but never null. We then encrypt the values to send using the code method below.
Validation is performed, confirming that expiry dates are valid and that the PAN is at least 13 characters. Should any validation checks fail, nil
is returned from the method. Pass an error by ref to determine the cause of failure if any occurs.
Objective-C
// Card details
NSString *pan = @"41111111111111";
NSString *month = @"10";
NSString *year = @"2022";
NSString *cardHolder = @"Mr John Doe";
// Error handling
NSError *error;
// Encrypt
NSDictionary *encryptionPayload = [[RVNEncryption sharedInstance] encrypt:pan month:month year:year nameOnCard:cardHolder error:&error];
if(!error) {
NSLog(@"Ravelin encryption payload: %@",encryptionPayload);
// Send to your servers
} else {
NSLog(@"Ravelin encryption error %@", error.localizedDescription);
}
Swift
var error:NSError? = nil
let encryptionPayload = RVNEncryption.sharedInstance().encrypt("41111111111111", month: "10", year: "10", nameOnCard: "Mr John Doe", error: &error)
if let error = error {
print("Ravelin encryption error \(error.localizedDescription)")
} else {
print("Ravelin Encryption payload: \(encryptionPayload as AnyObject)")
// Send to your servers
}
Using the Ravelin Mobile SDK, you can capture various built in events along with your own custom ones that can later be viewed in the Ravelin dashboard. This can be very useful for analysts to gain additional context during an investigation. For example, if you can see that a user is going through unexpected parts of your customer journey at a set speed on a new device that could indicate suspicious activity. It can also be powerfull information to use for our Machine Learning Models to identify new parterns and behaviours.
These are the available predefined events:
To be used at any appropriate checkpoint to profile a user’s device.
Ensure that the customerId
is set before trackFingerprint()
is called.
Ravelin.trackFingerprint:(NSDictionary *)eventProperties
To indicate when the user hits a new page. We would like this to be used for every new page or screen the user goes to.
Ravelin.trackPage:(NSString *)pageTitle
To be used when a user performs a search. There is an optional searchValue
property that can be added to let us know about the search term.
Ravelin.trackSearch:(NSString* _Nullable)pageTitle searchValue:(NSString* _Nullable)searchValue;
To be used when a user selects or changes a product option like colour, size or delivery option.
There is an optional option
property that can be added to let us know about the what option was selected, we suggest using one of the following values colour
, size
, date
, time
, seat
, ticketType
, delivery option
, but other values are accepted.
There is also an optional optionValue
porperty that can be sent to let us know what value was selected.
Ravelin.trackSelectOption:(NSString* _Nullable)pageTitle option:(NSString* _Nullable)option optionValue:(NSString* _Nullable)optionValue;
To be used when an item is added or removed from the cart. There are two optional properteis itemName
and quantity
that can be added to let us know the product name and the quantity.
Ravelin.trackAddToCart:(NSString* _Nullable)pageTitle itemName:(NSString* _Nullable)itemName quantity:(NSNumber* _Nullable)quantity;
Ravelin.trackRemoveFromCart:(NSString* _Nullable)pageTitle itemName:(NSString* _Nullable)itemName quantity:(NSNumber* _Nullable)quantity;
To be used when an item is added or removed from the wishlist. There is an optional itemName
property that can be added to let us know the product name.
Ravelin.trackAddToWishlist:(NSString* _Nullable)pageTitle itemName:(NSString* _Nullable)itemName;
Ravelin.trackRemoveFromWishlist:(NSString* _Nullable)pageTitle itemName:(NSString* _Nullable)itemName;
To be used when the user interacts with product content like plays a video, expands a photo, expands product details.
There is an optional contentType_ property
to let us know what content the user intercated with, we suggest using one of the following values video
, photo
, productDescription
, deliveryOptions
, but other values are accepted.
Ravelin.trackViewContent:(NSString* _Nullable)pageTitle contentType:(NSString* _Nullable)contentType;
To indicate that the user has just authenticated themselves. Use eventProperties to add additional key/pair information to the payload
Ravelin.trackLogin:(NSString *)pageTitle eventProperties:(NSDictionary *)eventProperties
To indicate when the user has signed out of their session.
Ravelin.trackLogout:(NSString *)pageTitle eventProperties:(NSDictionary *)eventProperties
The track method can be used to log notable client-side events:
Objective-C
NSString *pagetitle = @"productPpage";
NSString *eventName = @"SHARE_PRODUCT";
NSDictionary *meta = @{@"productId" : @"213", @"sharePlaftorm" : @"facebook"};
[[Ravelin sharedInstance]track:pageTitle eventName:eventName eventProperties:meta];
Swift
let pageTitle = "productPage"
let eventName = "SHARE_PRODUCT"
let meta = ["productId" : "213", "sharePlaftorm" : "facebook"]
Ravelin.sharedInstance().track(pageTitle, eventName: eventName, eventProperties: meta)
NOTE: Track events have overload methods with completion handlers and will accept nil values for eventProperties
We can detect paste events using the UITextFieldDelegate method shouldChangeCharactersInRange
in conjunction with the Ravelin track
method to send a custom event.
Objective-C
- (BOOL)textField:(UITextField *)iTextField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
// avoid checking the pasteboard when a user is typing and only adding a single character at a time
if(string.length <= 1) { return YES; }
// Check if the textfield contains pasted text
if([string containsString:[UIPasteboard generalPasteboard].string]) {
// Send paste event to Ravelin
NSString *pageTitle = @"home";
NSString *pasteLength = [NSString stringWithFormat:@"%ld", (long)[UIPasteboard generalPasteboard].string.length];
NSDictionary *meta = @{@"pasteLength": pasteLength};
[self.ravelin track:pageTitle eventName:@"paste" eventProperties:meta];
}
return YES;
}
Swift
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// avoid checking the pasteboard when a user is typing and only adding a single character at a time
guard string.count > 1 else {
return true
}
guard string.contains(UIPasteboard.general.string ?? "") else {
return true
}
let pageTitle = "home"
let eventName = "paste"
let pasteLength : String = "\(UIPasteboard.general.string?.count ?? 0)"
let meta = ["pasteLength" : pasteLength]
self.ravelin.track(pageTitle, eventName: eventName, eventProperties: meta)
return true
}
NOTE: Track events have overload methods with completiton handlers
For location tracking to be successful from within the Ravelin Mobile SDK, your application should ask for user permissions for location sharing. Please refer to the Apple documentation here for more information on the subject.
You can check our demo repos with simple projects, showing the integration and usage of RavelinCore and RavelinEncrypt:
Here is a simple end-to-end example of using the Ravelin Framework within a View.
NOTE: All Ravelin network methods are asynchronous. Completion blocks are provided so you can handle each request accordingly. The example code will not necessarily call each method sequentially and is for demonstration purposes only.
#import "ViewController.h"
#import <UIKit/UIKit.h>
#import <RavelinCore/Ravelin.h>
#import <RavelinEncrypt/RavelinEncrypt.h>
@interface ViewController ()
@property (strong, nonatomic) Ravelin *ravelin;
@property (strong, nonatomic) RVNEncryption *ravelinEncrypt;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Make Ravelin instance with API keys
self.ravelin = [Ravelin createInstance:@"publishable_key_live_----"];
// Make RavelinEncrypt instance with rsa key
self.ravelinEncrypt = [RVNEncryption sharedInstance];
self.ravelinEncrypt.rsaKey = @"----|----";
// Setup customer info and track their login
self.ravelin.customerId = @"customer1234";
self.ravelin.orderId = @"web-001";
[self.ravelin trackLogin:@"loginPage"];
// Track customer moving to a new page
[self.ravelin trackPage:@"checkout"];
// Send a device fingerprint
[self.ravelin trackFingerprint];
// Send a device fingerprint with a completion block (if required)
[self.ravelin trackFingerprint:^(NSData *data, NSURLResponse *response, NSError *error) {
if(!error) {
NSDictionary *responseData;
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode == 200) {
responseData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers|NSJSONReadingAllowFragments error:nil];
// Do something with responseData
} else {
// Status was not 200. Handle failure
}
} else {
NSLog(@"%@",error.localizedDescription);
}
}];
// Encrypt customer card details, ready for sending for payment
NSError *error;
NSDictionary *encryptionPayload = [self.ravelinEncrypt encrypt:@"41111111111111" month:@"10" year:@"20" nameOnCard:@"Mr John Doe" error:&error];
if(!error) {
NSLog(@"Ravelin Encryption payload: %@", encryptionPayload);
} else {
NSLog(@"Ravelin encryption error %@", error.localizedDescription);
}
// Track a customer logout
[self.ravelin trackLogout:@"logoutPage"];
}
@end
import UIKit
import RavelinCore
import RavelinEncrypt
class ViewController: UIViewController {
// Declare Ravelin Shared Instance with API keys
private var ravelin = Ravelin.createInstance("publishable_key_live_----")
private var ravelinEncrypt = RVNEncryption.sharedInstance()
override func viewDidLoad() {
super.viewDidLoad()
// set up ravelin encryption RSA key
ravelinEncrypt.rsaKey = "----|----"
// Setup customer info and track their login
ravelin.customerId = "customer1234"
ravelin.orderId = "web-001"
ravelin.trackLogin("loginPage")
// Track customer moving to a new page
ravelin.trackPage("checkout")
// Send a device fingerprint
ravelin.trackFingerprint()
// Send a device fingerprint with a completion block (if required)
ravelin.trackFingerprint { (data, response, error) -> Void in
if let error = error {
// Handle error
print("Ravelin error \(error.localizedDescription)")
} else if let httpResponse = response as? HTTPURLResponse {
if httpResponse.statusCode == 200 {
// Handle success
}
}
}
// Encrypt customer card details, ready for sending for payment
var error:NSError? = nil
let encryptionPayload = ravelinEncrypt.encrypt("41111111111111", month: "10", year: "20", nameOnCard: "Mr John Doe", error: &error)
if let error = error {
print("Ravelin encryption error \(error.localizedDescription)")
} else {
print("Ravelin Encryption payload: \(encryptionPayload as AnyObject)")
// Send to server
}
// Track a customer logout
ravelin.trackLogout("logoutPage")
}
}
For apps that provide part of the user interface with WebViews, embedded within a native app, it is recommended making a deviceId cookie available to those WebViews that utilise ravelinjs. The current version of ravelinjs will adhere to any ravelinDeviceId cookie that it finds.
Here is a simple example of sharing the deviceId via a cookie.
import UIKit
import WebKit
import RavelinCore
extension WKWebView {
func set(cookie: HTTPCookie, completion: SetCookieResponse? = nil) {
configuration.websiteDataStore.httpCookieStore.setCookie(cookie, completionHandler: completion)
}
}
class WebViewController: UIViewController {
// get a reference to the deviceId from the shared instance which has been configured elsewhere
private let deviceId = Ravelin.sharedInstance().deviceId
private var webView: WKWebView!
private func makeWebView() -> WKWebView {
let configuration = WKWebViewConfiguration()
configuration.websiteDataStore = WKWebsiteDataStore.default()
let webView = WKWebView(frame: .zero, configuration: configuration)
webView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(self.webView)
// ... complete WebView configuration and layout
return webView
}
private func makeDeviceIdCookie(deviceId: String) -> HTTPCookie? {
// example cookie
var properties: [HTTPCookiePropertyKey: Any] = [
.domain: "your.webite.com",
.path: "/",
.name: "ravelinDeviceId",
.expires: NSDate(timeIntervalSinceNow: yearInterval),
.value: deviceId]
if #available(iOS 13.0, *) {
properties[.sameSitePolicy] = HTTPCookieStringPolicy.sameSiteLax
}
return HTTPCookie(properties: properties)
}
private func shareDeviceIdWithWebView(deviceId: String, webView: WKWebView) {
let cookie = makeDeviceIdCookie(deviceId)
webView.set(cookie: cookie) {
print("setting cookie: \(cookie)")
}
}
override func viewDidLoad() {
super.viewDidLoad()
webView = makeWebView()
shareDeviceIdWithWebView(deviceId: deviceId, webView: webView)
}
}
Note: The Ravelin class requires import of RavelinCore.
createInstance (apiKey)
Create a singleton instance of the Ravelin SDK with your Publishable API Key. Use this method to create an SDK instance for tracking purposes only (i.e. without card encryption functionality)
Parameters
Parameter | Type | Description |
---|---|---|
apiKey | String | Your Publishable API Key. See Authentication for where to find this. |
Return value
The singleton instance of the class
sharedInstance
Get the instantiated Ravelin singleton
Return value
The singleton instance of the class
trackFingerprint
Fingerprints the device and sends results to Ravelin
Return value
Null
trackFingerprint (completionHandler)
Fingerprints the device and sends results to Ravelin
Parameters
Parameter | Type | Description |
---|---|---|
completionHandler | Object | Completion block to handle response |
trackFingerprint(customerId, completionHandler)
Sets a customerId if one has not already been set and sends a fingerprint to Ravelin
Parameters
Parameter | Type | Description |
---|---|---|
customerId | String | The customerId to set for this device fingerprint. |
completionHandler | Object | Completion block to handle response |
trackPage (pageTitle, eventProperties)
Sends a track page event to Ravelin.
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page |
eventProperties | Dictionary | A dictionary of meta data to send with the event |
Also available with a completion handler: trackPage (pageTitle, eventProperties, completionHandler)
trackSearch (pageTitle, searchValue)
Sends a track search event to Ravelin
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page |
searchValue | String | The searched term, optional |
Also available with a completion handler: trackSearch (pageTitle, searchValue, completionHandler)
trackSelectOption (pageTitle, option, optionValue)
Sends a track selected option event to Ravelin
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page |
option | String | The name of the option, optional. Example: {colour, size, date, time, seat, ticketType} |
optionValue | String | The value of the option, optional. Example: {blue, M, 14, first class} |
Also available with a completion handler: trackSelectOption (pageTitle, option, optionValue, completionHandler)
trackAddToCart (pageTitle, itemName, quantity)
Sends a track add to cart event to Ravelin
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page |
itemName | String | The name of the item, optional |
quantity | NSNumber | The quantity of the item, optional |
Also available with a completion handler: trackAddToCart (pageTitle, itemName, quantity, completionHandler)
Sends a track remove from cart event to Ravelin
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page |
itemName | String | The name of the item, optional |
quantity | NSNumber | The quantity of the item, optional |
Also available with a completion handler: trackRemoveFromCart (pageTitle, itemName, quantity, completionHandler)
trackAddToWishlist (pageTitle, itemName)
Sends a track add to wishlist event to Ravelin
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page |
itemName | String | The name of the item, optional |
Also available with a completion handler: trackAddToWishlist (pageTitle, itemName, completionHandler)
trackRemoveFromWishlist (pageTitle, itemName)
Sends a track remove from wishlist event to Ravelin
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page |
itemName | String | The name of the item, optional |
Also available with a completion handler: trackRemoveFromWishlist (pageTitle, itemName, completionHandler)
trackViewContent (pageTitle, contentType)
Sends a track content type event to Ravelin
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page |
contentType | String | The type of the content, optional. Examples: {video, photo, productDescription, deliveryOptions} |
Also available with a completion handler: trackViewContent (pageTitle, contentType, completionHandler)
trackLogin (pageTitle, eventProperties)
Sends a track login event to Ravelin
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page |
eventProperties | Dictionary | A dictionary of meta data to send with the event |
Also available with a completion handler: trackLogin (pageTitle, eventProperties, completionHandler)
trackLogout (pageTitle, eventProperties)
Ends current Ravelin session and sends logout event to Ravelin
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page |
eventProperties | Dictionary | A dictionary of meta data to send with the event |
Also available with a completion handler: trackLogout (pageTitle, eventProperties, completionHandler)
track (pageTitle, eventName, eventProperties)
Sends a track event to Ravelin. Use this method to send custom events and data to analyse in your dashboard.
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page |
eventName | String | The name of the event |
eventProperties | Dictionary | A dictionary of meta data to send with the event |
Also available with a completion handler: track (pageTitle, eventName, eventProperties, completionHandler)
apiKey
Your Publishable API Key. See Authentication for where to find this.
customerId
Your chosen customer ID
tempCustomerId
Temporary customer ID
sessionId (read only)
The Ravelin generated sessionId
deviceId (read only)
The Ravelin generated device ID
orderId
Your chosen order ID
The RVNEncryption class requires import of RavelinEncrypt.
sharedInstance
Get the instantiated RVNEncryption singleton
Return value
The singleton instance of the class
encrypt (pan, month, year, nameOnCard, &error)
Generates encryption payload ready for sending to Ravelin
Parameters
Parameter | Type | Description |
---|---|---|
pan | String | A string representation of the long card number |
month | String | Expiry month of card (1-12) |
year | String | Expiry year (2 or 4 digit) |
nameOnCard | String | The customer name on the card |
error | Object | Passed as reference |
Return value
Dictionary containing methodType, aesKeyCiphertext, cardCiphertext, algorithm, keyIndex and ravelinSDKVersion
rsaKey
Your Public RSA Key. See Authentication for where to find this.
Fatal Exception: NSInvalidArgumentException
Fatal Exception:NSInvalidArgumentException
Was this page helpful?