iOS SDK Implementation Guide

Getting Started with iOS

Specific configuration IDs and attribute code names are required to process app data into your Salesforce DMP account. Contact your Salesforce DMP representative for this information.

  • site Config id
  • exact attribute code names
  • event ids (if needed)
  • transaction attributes codes (if enabled)

iOS Setup

See instructions to download the Salesforce DMP framework

    1. Unzip the framework zip file provided by Salesforce DMP

    2. Copy iOSKruxLibUniversal.framework to your apps root folder
    3. Open Xcode where you are developing the mobile app.
    4. Drag iOSKruxLibUniversal.framework into Xcode. This opens a popup as shown below:



    5. The Salesforce DMP Framework becomes part of your app as shown below



    6. The following dependent frameworks are required to use the Salesforce DMP framework:
      • SystemConfiguration.framework
      • AdSupport.framework

Salesforce DMP supports collecting location data in lat/long coordinates as a page attribute, but needs to configured in advanced in Salesforce DMP.

  1. Contact your Salesforce DMP representative to enable the specific confID used in app to location_services_enabled.
  2. Add CoreLocation.framework to app
  3. Add the key NSLocationWhenInUseUsageDescription to the info.plist file of the application in order to request user's permission for iOS 8.0 and above.

Initializing KruxTracker in iOS

To start integration with the Salesforce DMP iOS SDK, import KruxTracker from the iOSKruxLibUniversal framework as shown below:

#import <iOSKruxLibUniversal/KruxTracker.h>

For Objective-C apps, KruxTracker must be imported by any file using the Salesforce DMP framework.

For Swift app, KruxTracker needs to be imported in a file named <App-name>-Bridging-Header.h. Then, it would be available to be used in any of the swift files without any import statements. Refer to https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html for more details.

Salesforce DMP will provide every app with a unique ConfigID which is generated in Salesforce DMP. This can be generated in Salesforce DMP or a Salesforce DMP representative will help you get one for your app.

You should use that to initialize the KruxTracker. If you initialize without a ConfigID, the KruxTacker will not be initialized properly. If you use the wrong ConfigID, you will not be able to send the data to Salesforce DMP servers.

KruxTracker is a singleton and must be initialized with the ConfigID before being used to send data. Initialize it in the AppDelegate file as shown below so that it is available as soon as the app launches.

In Objective-C

In Swift

The initialization sets the default values and starts the scheduler that fetches the Salesforce DMP Config and segments every 30 minutes. There is a time interval restriction of 30 minutes on fetching config and segments. All these calls are performed in background threads and does not impact the main thread.

The debug and dryRun flags are useful for testing purposes. Please use them only during the development phase. They must be turned off before the final submission of the app.

Sending data to Salesforce DMP from iOS apps

KruxTracker exposes three methods to send data to Salesforce DMP servers. All calls are made asynchronously and will not impact the latency and stability of the core mobile app.

A queue is used to store requests when network or Salesforce DMP Config is unavailable. Queued data is sent when the user gets back network and the Salesforce DMP Config. The queue has a limit of 200 requests and stores the most recent ones when that limit is reached. Every config maps to a “site” in Salesforce DMP.

trackPageView in iOS

The trackPageView method helps app developers send user actions performed on apps to Salesforce DMP. These user actions need to specify a URL and a set of attributes Salesforce DMP should track.

The URL sent is shown as a “section” in Salesforce DMP and the attributes are displayed as page or user attributes.

Example News-based App in iOS using Salesforce DMP

The trackPageView method helps app developers send user actions performed on apps to Salesforce DMP. These user actions need to specify a URL and a set of attributes Salesforce DMP needs to   track.

 The first argument is shown as a “section” in Salesforce DMP and the attributes can be either a page or user attributes.

Implement trackPageView at least once for all users to report the app/site in Unique Trend report in Salesforce DMP UI

After determining the attributes to collect, send those exact names to your Solutions Manager for activation. Doing so adds the names to your attribute tree and segment creation in Salesforce DMP.

For the news-based app example you would call trackPageView at the following places:

  1. User opens the iOS app For Objective-C:
    
    // Create a dictionary of page attributes
    NSDictionary *pageAttr = [[NSDictionary alloc] initWithObjectsAndKeys: :@"open_app", @"action", nil];
    // Create a dictionary of user attributes
    NSDictionary *userAttr = [[NSDictionary alloc] init];
    // Initialize Krux Tracker
    [[AppDelegate getKruxTracker] trackPageView:@"Home_Page" pageAttributes:pageAttr userAttributes:userAttr];
    
    For Swift:
    
    // Create Page attribute.
    let pageAttr = ["action": "open", "screen": "home"]
    // Create User attributes in applicable
    // Initialize Krux Tracker
    (AppDelegate.getKruxTracker()).trackPageView("Home_Page", pageAttributes:pageAttr, userAttributes:nil)
    
    
  2. User reads an "Entertainment" Article For Objective C:
    
    // Send Entertainment article
    // article_read is the page attribute and 'Entertainment' is its value
    NSDictionary *pageAttr = [[NSDictionary alloc] initWithObjectsAndKeys: :@"Entertainment", @"article_read", nil];
    
    NSMutableDictionary *userAttr = [[NSMutableDictionary alloc] init];
    [[AppDelegate getKruxTracker] trackPageView:@"Article_Page" 
    pageAttributes:pageAttr userAttributes:userAttr];
    
    For Swift:
    
    // Send Entertainment article
    // article_read is the page attribute and 'Entertainment' is its value
    
    let pageAttr = ["article_read": "Entertainment"]
    (AppDelegate.getKruxTracker()).trackPageView("Article_Page", pageAttributes:pageAttr, userAttributes:nil)
    
  3. User logs in and reads a “Sports” Article For Objective C:
    
    // Send Sports article
    // article_read is the page attribute and 'Sports' is its value
    // login id is a user attribute(12345 in this example) and loginId is how we are going to represent it in Krux
    
    NSDictionary *pageAttr = [[NSDictionary alloc] initWithObjectsAndKeys: @"Sports", @"article_read", nil];
    NSDictionary *userAttr = [[NSDictionary alloc] initWithObjectsAndKeys: :@"12345", @"loginId", nil]; 
    [[AppDelegate getKruxTracker] trackPageView:@"Article_Page" pageAttributes:pageAttr userAttributes:userAttr];
    
    For Swift:
    
    // Send Sports article
    // article_read is the page attribute and 'Sports' is its value
    // login id is a user attribute(12345 in this example) and loginId is how we are going to represent it in Krux
    
    let pageAttr = ["article_read": "Sports"]
    let userAttr = ["loginId": "12345"]
    (AppDelegate.getKruxTracker()).trackPageView("Article_Page", pageAttributes: pageAttr, userAttributes: userAttr)

PLEASE NOTE: If you wish to pass more than one attribute value to a single attribute in the pixel call, please make sure the values are comma-separated when passing them.

FireEvent in iOS

Salesforce DMP users can create events in Salesforce DMP UI. They can then use the fireEvent method to send information about an event to Salesforce DMP.

The first parameter of this method should be the unique id of the event that publisher wants to track. If the event contains attributes, you can send their values via this method call. The fireEvent method must be called if you created an event in the "People > Actions - Manage Events" section of Salesforce DMP UI.

For example, if you created an event with unique id ‘HsdfRt12,’ and created an attribute that you want to send data with that event ‘article_category’. You might want to fire this event every time someone goes to a new article category.

For that case, you can call fireEvent similarly:

In Objective C:

NSDictionary *attrs = [[NSDictionary alloc] initithObjectsAndKeys: @"Entertainment", @"article_category", nil]; 
[[AppDelegate getKruxTracker] fireEvent:@"HsdfRt12" eventAttributes:attrs withError:&err];

In Swift:

let attrs =["article_category": "Entertainment"]
do {
    try (AppDelegate.getKruxTracker()).fireEvent("HsdfRt12", eventAttributes:attrs)
}
catch {
    print(“Error: %@”,error)
}

TrackTransaction iOS

This feature must be enabled to your account.

See description and requirements for Transaction segments.

Salesforce DMP users can send transaction data which includes an actual e-commerce purchase. The attributes that need to be sent with this data are “price”, “quantity” and “orderDate”. Please note that these names are configurable in Salesforce DMP and you should talk to you Salesforce DMP representative to get the names of these attributes.

In the example below, we are using “totalPrice”, “quantity” and “dateOrder” as  the attributes which correspond to “price”, “quantity” and “orderDate”.

Note that this is a just an example and you implementation will differ based off your settings in Salesforce DMP.

In Objective C:

NSDictionary *attr = [[NSDictionary alloc] initithObjectsAndKeys: :@"1000", @"totalPrice", @"5", @"quantity", @"2016-07-15", @"dateOrder" nil]; 
[[AppDelegate getKruxTracker] trackTransactionWithAttributes:attr];
 

In Swift:

let attr = ["totalPrice ": "1000", "quantity": "5", "dateOrder": "2016-07-15"]; 
(AppDelegate.getKruxTracker()).trackTransactionWithAttributes(attr)

Fetching data from Salesforce DMP for iOS Apps

KruxTracker gathers information about Salesforce DMP user segments that a particular user might be a part of. This information is fetched asynchronously in the background when the tracker is initialized. App developers can use this information to customize the content or show the right ad to the user.

In ObjectiveC

[[AppDelegate getKruxTracker] getSegments]

In Swift

(AppDelegate.getKruxTracker()).getSegments()

Initialize KruxTracker during app open for segments to be available as early as possible during app usage.

 

Helper methods

On initialization, KruxTracker starts a scheduler that fetches config and segments every 30 minutes.  The below methods are exposed but should not be used explicitly unless you want to control when the config and segments are fetched. We strongly recommend that you do not call these methods unless you want to be able to control the timing when config and segments are fetched.

There are two helper methods exposed to handle this scheduler:

In Objective-C,

[[AppDelegate getKruxTracker] startScheduler];[[AppDelegate getKruxTracker] stopScheduler];

In Swift,

(AppDelegate.getKruxTracker()).startScheduler()(AppDelegate.getKruxTracker()).stopScheduler()

 

To get the current version number of the Salesforce DMP SDK:

In Objective-C,

[[AppDelegate getKruxTracker] getKruxSDKVersionNo];

In Swift

(AppDelegate.getKruxTracker()).getKruxSDKVersionNo()

Consent Capture & Lookup

This documentation supports SDK specific enhancements made as part of feature releases to support Consumer Rights Management. Please read supporting documentation on Consumer Rights Management features on Zendesk, here.

Many data protection and privacy regulations require you and your company to obtain consent from users before collecting data about them, and to honor users' requests for how you use their data. The SDK includes the following two methods as it relates to consent:

- (void) consentSetRequest:(NSDictionary *)consentSetAttributes;
- (void) consentGetRequest:(NSDictionary *)consentGetAttributes;

The consentSetRequest method accepts the following parameters:

Parameter Full form
idt Identification Type
dt Device Type
idv Identification Value
pr Policy Regime
dc Data Collection
al Analytics
tg Targeting
cd Cross Device
sh Sharing Data
re ReIdentification


The consentGetRequest method accepts the following parameters:

Parameter Full form
idt Identification Type
dt Device Type
idv Identification Value
pr Policy Regime

 

For additional information about the meaning of and supported values for these parameters, please consult the glossary of terms, here.

idt, dt and idv are user identification parameters that the DMP uses to manage Consumer Rights activities. Providing identification parameters is optional with the SDK; In absence of identification parameters, the SDK defaults to using idt=device and dt=idfa.

If any user identification parameters (idt, dt, or idv) are provided, the caller must provide all identification parameters. If any one of them is missing, the "Wrong Identification Parameters" error is returned through callback.

These methods are implemented in an asynchronous fashion. If you want to handle response and/or errors for these requests, please implement the KruxConsentCallback protocol, and provide its object as a parameter while initializing the SDK.

The SDK will forward response/error for a particular consent request by calling one of the methods of this consent callback object. The SDK is backward compatible, so you do not need to change application code if you don’t want to handle consent response/error messages.

Consent Get/Set Response Messages

Please refer to Consent and Consumer Webservice documentation here for more detail.

Consent Get/Set Error Messages

There are various error conditions under which consent set/get request might not be processed. A few examples of these situations are network not available, and an SDK internal error. For all of these errors, there will be one single message forwarded through callback implementation. That message is "Could not process consent request". If the consent service responds with an http error then that error will be forwarded to the application.

SDK in-memory consent management

  • SDK runs a scheduler to fetch consent values every 30 minutes. So, if the consent settings are set using e.g., file upload, then consent values will be updated correctly.
  • SDK is concerned only with the data collection field. Based on this value, it will decide whether to collect data or not.
  • SDK manages in-memory consent record. This consent record gets updated either by a scheduler or whenever user sets the consent values by calling consent set method.
  • SDK also logs a warning message every 30 minutes if device does not have directly given consent values (i.e., file upload, via SDK interface, or by calling HTTP API directly).


Code snippet for KruxConsentCallback protocol

@protocol KruxConsentCallback <NSObject>

- (void) handleConsentGetResponse:(NSString *) consentGetResponse;
- (void) handleConsentGetError:(NSString *) consentGetError;
- (void) handleConsentSetResponse:(NSString *) consentSetResponse;
- (void) handleConsentSetError:(NSString *) consentSetError;

@end

Objective C code snippet to set and get consent values

- (void) callConsentRequests
{
NSDictionary *consentSetAttributes = [self getConsentAttributes];
NSDictionary *consentGetAttributes = [self getIdParameters];
[[AppDelegate getKruxTracker] consentGetRequest:consentGetAttributes];
[[AppDelegate getKruxTracker] consentSetRequest:consentSetAttributes];
}

- (NSDictionary *) getConsentAttributes
{
NSMutableDictionary *consentAttributes = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:0], @“dc”,
[NSNumber numberWithInt:0], @“cd”,
[NSNumber numberWithInt:0], @“tg”,
[NSNumber numberWithInt:0], @“al”,
[NSNumber numberWithInt:0], @“sh”,
[NSNumber numberWithInt:0], @“re”, nil];
[consentAttributes addEntriesFromDictionary:[self getIdParameters]];
return consentAttributes;
}

- (NSDictionary *) getIdParameters
{
NSDictionary *consentAttributes = [[NSDictionary alloc] init];
[consentAttributes setValue:@“<idfa-value>” forKey:@“idv”];
[consentAttributes setValue:@“gdpr” forKey:@“pr”];
[consentAttributes setValue:@“idfa” forKey:@“dt”];
[consentAttributes setValue:@“device” forKey:@“idt”];

return consentAttributes;
}

Objective C code snippet containing KruxConsentCallback implementation

KruxConsentCallbackImpl.h

#import <iOSKruxLibUniversal/KruxConsentCallback.h>

@interface KruxConsentCallbackImpl : NSObject<KruxConsentCallback>

@end

KruxConsentCallbackImpl.m

#import <Foundation/Foundation.h>
#import "KruxConsentCallbakImpl.h"

@interface KruxConsentCallbackImpl()

@end

@implementation KruxConsentCallbackImpl

- (void) handleConsentGetResponse:(NSString *) consentGetResponse {
NSLog(@"Consent Callback : Consent Get Response: %@", consentGetResponse);
}

- (void) handleConsentGetError:(NSString *) consentGetError {
NSLog(@"Consent Callback : Consent Get Error: %@", consentGetError);
}

- (void) handleConsentSetResponse:(NSString *) consentSetResponse {
NSLog(@"Consent Callback : Consent Set Response: %@", consentSetResponse);
}

- (void) handleConsentSetError:(NSString *) consentSetError {
NSLog(@"Consent Callback : Consent Set Error: %@", consentSetError);
}

@end

Objective C code snippet containing SDK initialization with KruxConsentCallback parameter

@implementation AppDelegate

static KruxTracker *kt;
+ (KruxTracker *)getKruxTracker {
return kt;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
KruxConsentCallbackImpl *consentCallback = [[KruxConsentCallbackImpl alloc] init];
kt = [KruxTracker sharedEventTrackerWithConfigId:@"KZuFtT_j" debugFlag:true dryRunFlag:false consentCallback:consentCallback];
return YES;
}

Swift code snippet to set and get consent values

func callConsentRequests() {
(AppDelegate.getKruxTracker()).consentSetRequest(self.getConsentAttributes())
(AppDelegate.getKruxTracker()).consentGetRequest(self.getIdParameters())
}

func getConsentAttributes() -> [String:Any] {
var consentAttributes : [String:Any] = [:]
consentAttributes["dc"] = 0
consentAttributes["cd"] = 0
consentAttributes["tg"] = 0
consentAttributes["al"] = 0
consentAttributes["sh"] = 0
consentAttributes["re"] = 0

let idParams = self.getIdParameters()
idParams.forEach { (k,v) in consentAttributes[k] = v }
return consentAttributes
}

func getIdParameters() -> [String:Any] {
var consentAttributes : [String:Any] = [:]
consentAttributes["idv"] = "<idfa-value>"
consentAttributes["pr"] = "gdpr"
consentAttributes["dt"] = "idfa"
consentAttributes["idt"] = "device"
return consentAttributes
}

Swift code snippet containing KruxConsentCallback implementation

KruxConsentCallbackImpl.swift

@objc class KruxConsentCallbackImpl: NSObject, KruxConsentCallback {
func handleConsentGetResponse(_ consentGetResponse: String) {
NSLog("Consent Callback: Consent Get Response: %@", consentGetResponse as NSString)
}

func handleConsentGetError(_ consentGetError: String!) {
NSLog("Consent Callback: Consent Get Error: %@", consentGetError as NSString)
}

func handleConsentSetResponse(_ consentSetResponse: String!) {
NSLog("Consent Callback: Consent Set Response: %@", consentSetResponse as NSString)
}

func handleConsentSetError(_ consentSetError: String!) {
NSLog("Consent Callback: Consent Set Error: %@", consentSetError as NSString)
}
}

Swift code snippet containing SDK initialization with KruxConsentCallback parameter

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?
static var kt: KruxTracker!
static var consentCallback:KruxConsentCallback!
static func getKruxTracker() -> KruxTracker {
return kt
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
AppDelegate.consentCallback = KruxConsentCallbackImpl()
AppDelegate.kt = KruxTracker.sharedEventTracker(withConfigId: "KZuFtT_j", debugFlag: true,
dryRunFlag: false, consentCallback:AppDelegate.consentCallback)
return true
}
}

Remove and Portability

If you would like to support delete/remove and portability requests, please make API calls per the technical spec defined here.

Debugging/Testing in iOS

KruxTracker exposes two parameters to help you ensure that you are able to send data to backend servers properly. They are:

debugFlag:true

This outputs debug messages while it is trying to fetch data/send data to Salesforce DMP backend servers. You should turn this off before the final submission of your app.

dryRunFlag: true

This does a dryRun without sending any data to the Salesforce DMP servers. This is useful while you are developing an app. You should turn this off before the final submission of your app.

 

Upgrading to Salesforce DMP iOS SDK version 4.0.1 

Initialization of KruxTracker

In the version 4.0.1, KruxTracker is a singleton that must be initialized with the unique config Id provided by Salesforce DMP. If you initialize without a configID, the KruxTacker will not be initialized and if you use the wrong configID, you will not be able to send the data to Salesforce DMP servers. It also takes debug and dryRun flags that are useful for testing purposes and must be set to false before the final submission of the app. It is recommended to initialize the KruxTracker as a static variable in AppDelegate.m so that its available as soon as the app launches.

Before,

// Initialize KruxTracker (earlier version)
kruxTracker = [[KruxTracker alloc] initWithConfigId:@""];

After,

// Initialize KruxTracker
kruxTracker = [KruxTracker sharedEventTrackerWithConfigId:@"<config id provided by Krux>" debugFlag:false dryRunFlag:false];

In this version, a time interval restriction of 30 minutes has been added on fetching config and segments.

Sending Data to Salesforce DMP

KruxTracker exposes three methods now to send data to Salesforce DMP servers as described earlier. 

The method definition for trackPageView has changed and a new method has been added to send data related to transactions to the Salesforce DMP servers. There are no changes in the fireEvent method.

 Following is the change in trackPageView usage:

Before,

// Send Sports article
// article_read is the page attribute and 'Sports' is its value
// login id is a user attribute(12345 in this example) and loginId is how we are going to represent it in Krux

NSMutableDictionary *pageAttr = [[NSMutableDictionary alloc] init];
NSMutableDictionary *userAttr = [[NSMutableDictionary alloc] init];
[pageAttr setObject:@"Sports" forKey:@"article_read"];
[userAttr setObject:@"12345" forKey:@"loginId"];
[_kruxTracker trackPageView:@"Article_Page" pageAttributes:pageAttr userAttributes:userAttr withError:&err];

 

After,

// Send Sports article
// article_read is the page attribute and 'Sports' is its value
// login id is a user attribute(12345 in this example) and loginId is how we are going to represent it in Krux NSDictionary *pageAttr = [[NSDictionary alloc] initWithObjectsAndKeys: @"Sports", @"article_read", nil];
NSDictionary *userAttr = [[NSDictionary alloc] initWithObjectsAndKeys: :@"12345", @"loginId", nil]; [kruxTracker trackPageView:@"Article_Page" pageAttributes:pageAttr userAttributes:userAttr];

 

Transaction data can be sent to Salesforce DMP in the following way:

NSDictionary *attr = [[NSDictionary alloc] initithObjectsAndKeys: :@"1000", @"totalPrice", @"5", @"qty", @"07/15/2016", @"date" nil]; 
[kruxTracker trackTransactionWithAttributes:attr];

 

More Helper methods

 New helper method has been exposed to provide more control on the scheduler as described earlier.

However, we strongly recommend that you do not use this and let the SDK manage the fetching of config and segments.

Testing 

Before publishing your app with Salesforce DMP, see "Testing Your SDK Integration" and "Verifying the SDK Implementation with Charles Proxy" on how to test and verify your Salesforce DMP SDK implementation.

Have more questions? Submit a request

0 Comments

Article is closed for comments.