iOS v3.3.X

Introduction

SDK overview

Welcome to the Flagship iOS SDK documentation!

The following documentation helps you to run Flagship on your native iOS app using our client library with preconfigured methods to implement the Decision API.

Feel free to contact us if you have any questions regarding this documentation.

SDK features

This SDK version will help you:

Prequisites

  • Your app must be a native app written in Swift or Objective C.

  • Swift Client application must use Swift 5 or higher

Good to know

Supported platforms

Platform
Version

iOS

11.0

tvOS

11.0

macOS

10.13

watchOS

5.0

Getting Started

Our Flagship SDK is available for distribution through CocoaPods, Swift Package Manager or Carthage installation.

Cocoapods

  1. Open Terminal and browse to the directory that contains your project then, enter the following command: pod init

  2. Open your Podfile and add the following line to the Podfile

  1. Run pod install from your Xcode project's base directory

  2. Make sure you always open the Xcode workspace and not the project file when building your project

Swift Package Manager (SPM)

You can search for Flagship package on GitHub.

Add your GitHub or GitHub Enterprise account in Xcode’s preferences, and a package repository appear as you type.

For more information about Swift Package Manager, refer to Apple documentation.

Carthage

  1. Install Carthage

  2. Create a Cartfile in the same directory where your .xcodeproj or .xcworkspace is.

  3. Add this line to the Cartfile

  1. Run carthage update --use-xcframeworks

  2. A Cartfile.resolved file and a Carthage directory will appear in the same directory where your .xcodeproj or .xcworkspace is.

  3. Drag the built Flagship.xcframework bundles from Carthage/Build into the "Frameworks, Libraries, and Embedded Content" section of your application’s Xcode project.

For More information refer to Carthage

Initialization

To run experiments with Flagship, you will need to start the SDK.

Flagship uses a sharedInstance then create a visitor to activate experiments and track events.

  • func start(envId:String, apiKey:String, config:FSConfig)

Parameter
Type
Required
Description

envId

String

Yes

Identifies your Flagship account and environment (pre-prod or prod).

apiKey

String

Yes

Identifies your Flagship api key (pre-prod or prod)

config

FSConfig

No

Object that represent configuration client

📘 API Key & Environment ID required

You can find your apiKey and your environmentId on your Flagship account, in Parameters > Environment & Security.

Advanced Configuration

FlagshipConfig class help you to configure the SDK via the following two available config implementations: DecisionApi and Bucketing. See Decision Mode section.

Timeout

This delay only concerns the request on fetching campaigns under the api mode. If the API didn't answer during this interval of time, the SDK will not wait longer for it and will use the modifications values already present on device's cache. If there is no cache yet, the default values will be returned from the getFlag function.

  • ** func withTimeout(_ timeout:TimeInterval)->FSConfigBuilder**

Parameter
Type
Description

timeout

TimeInterval

Milliseconds, default value is 2000 ms

📘

The unit of measure for the timeout is Millisecond.

Log Level

  • func withLogLevel(_ logLevel:FSLevel)->FSConfigBuilder

Specifies a log level to filter logs emitted by the SDK.

Parameter
Type
Description

level

FSLevel

The levels in ascending order are : NONE(0), EXCEPTIONS(1), ERROR(2), WARNING(3), DEBUG(4), INFO(5), ALL(6).

Decision Mode

DecisionApi

When the SDK is running in DecisionApi mode, the campaign assignments and targeting validation take place server-side. In this mode, each call to the fetchFlags method to refresh the flags will create an HTTP request.

Bucketing

When the SDK is running in BUCKETING mode, the SDK downloads all the campaigns configurations at once in a single bucketing file so that variation assignment can be computed client-side by the SDK. This bucketing file is stored in cache and will only be downloaded again when campaign configurations are modified in the Flagship interface. Learn more

📘

The default value is DECISION API

Polling Interval Time

Only available for Bucketing Mode:

  • func withBucketingPollingIntervals(_ pollingTime:TimeInterval)->FSConfigBuilder

Define time interval between two bucketing updates. Default is 60 seconds.

Parameter
Type
Description

pollingTime

TimeInterval

interval time, default is 60 seconds.

Tracking Config Manager

func withTrackingManagerConfig(_ trackingMgrConfig: FSTrackingManagerConfig)->FSConfigBuilder

The SDK through the TrackingManager class report analytics event using batching process, each time a visitor emits a hit, the tracking manager will stack it in the event pool.

When the time interval batchIntervals is over or pool Maximum Size poolMaxSize is reached, the batch process is triggered and the pool emptied. In the meantime, the caching process depends on the cache strategy adopted.

The advantages:

  • Use less network traffic

  • Avoid data loss

  • Catch all hits that would fail

The TrackingManager stand on three options to setup :

  1. Time Interval Time interval to process and send event through batch

📘

The batchIntervals parameter is an integer, default value is 5 seconds

  1. Pool Max Size Specifies the maximum number of hits in the pool

📘

The poolMaxSize parameter is an integer, default value is 10

  1. Cache Strategy Define a strategy to adopt, we have two strategies represented by an enum BatchCachingStrategy.

1 - CONTINUOUS_CACHING

📘

Recommended for client-side applications

Each time a visitor emits an event, this strategy duplicates events in cache using cacheHit (see InterfaceCache), on completion batching process the saved hits are removed from the cache.

Note: The SDK has a default cache implementation using a database

2 - PERIODIC_CACHING

📘

Recommended for server-side applications

This strategy periodically make a copy in the cache of the existing event in the pool, those events will be removed once the batching process completed and succeed

Cache Management

Use a default cache Management provided by the SDK or create your own custom cache manager .

  • func withCacheManager(_ customCacheManager:FSCacheManager)->FSConfigBuilder

Parameter
Type
Description

customCacheManager

FSCacheManager

Managing the cache

FSCacheManager

This class affords two protocols to handle the cache management.

  • ** init(_ visitorCacheImp: FSVisitorCacheDelegate? = nil, _ hitCacheImp: FSHitCacheDelegate? = nil, visitorLookupTimeOut: TimeInterval = 0.2, hitCacheLookupTimeout: TimeInterval = 0.2)**

Parameter
Type
Default Value
Description

visitorCacheImp

nil

class implementing visitor protocol , use FSDefaultCacheVisitor if nil

hitCacheImp

nil

class implementing hit protocol, use FSDefaultCacheHit if nil

visitorLookupTimeOut

TimeInterval

200 ms

The time duration milliseconds given to lookup visitor, over this delay the operation is stopped

hitCacheLookupTimeout

TimeInterval

200 ms

The time duration milliseconds given to lookup hits, over this delay the operation is stopped

Developer Usage Tracking

  • func withDisableDeveloperUsageTracking(_ disableDeveloperUsageTracking: Bool)->FSConfigBuilder

Parameter
Description
Type

disableDeveloperUsageTracking

Collects information about the usage of SDK. By default the value is set to false otherwise set to true to disable this feature.

Bool

SDK Status

List of the possible SDK status :

Status
Description

NOT_INITIALIZED

Flagship SDK has not been started or initialized successfully.

POLLING

Flagship SDK has been started successfully but is still polling campaigns. (Only when Bucketing mode is used)

PANIC

Flagship SDK is ready but is running in Panic mode: All visitor's features are disabled except 'fetchFlags' which refreshes this status.

READY

Flagship SDK is ready to use.

It is possible to get the current status via the method getStatus() from the Flagship class.

  • func getStatus()->FStatus

    Return the current SDK status

onVisitorExposed

In some cases, you'll need to send informations about the exposition (When a flag has been seen by your visitor), like sending visitor and flag data to third parties.

To centralize it, we provide a callback in the configuration option of the SDK.

  • ** func withOnVisitorExposed(_ onVisitorExposed: OnVisitorExposed)->FSConfigBuilder **

This callback is triggered each time:

  • The visitorExposed() method is successfully called through the flag instance.

  • The value() method is called through the flag instance with "true" as parameter (default).

The OnVisitorExposed callback is a function with two parameters

Parameter
Type
Description

visitorExposed

FSVisitorExposed

This class represent the visitor exposed.

fromFlag

FSExposedFlag

This class represent the flag exposed. \n(The flag that has triggered the exposition)

  • FSVisitorExposed

The class FSVisitorExposed give us the visitor's information

Parameter
Type
Description

id

String

VisitorId

anonymousId

String

anonymous id, used with Experience Continuity

context

Dictionary

The current visitor’s context

  • FSExposedFlag

The class FSExposedFlag give us the flag's information

Parameter
Type
Description

key

String

key for flag

value

Any

value for flag

defaultValue

Any

default value

metadata

[FSFlagMetadata](#Getting flags campaigns metadata)

Campaign information metadata, this class already existed

For both class FSVisitorExposed & FSVisitorExposed use toJson() method to get the Json string representation and toDictionary() method to get a dictionary representation

📘 The onVisitorExposed callback is triggered ONLY when the visitorExpose() method is called and success.

Here is an example on how to use this callback:

Create a new visitor

The visitor instance is an object that lets you manage the context, activate experiments and track events.

The user context is a property dataset that defines the current user of your app.

This dataset is sent and used by the Flagship Decision API as targeting criteria for campaign assignment.

For example, if you wanted to enable or disable a specific feature based on VIP status, you would pass that attribute as a key-value pair in the user context so that the Decision API can enable or disable the corresponding feature flag for the user.

  • func newVisitor(_ visitorId:String, instanceType:Instance = .SHARED_INSTANCE)-> FSVisitorBuilder

Parameter
Type
Description

visitorId

String

Unique visitor identifier.

instanceType

Instance

How Flagship SDK should handle the newly created visitor instance. (Default is SINGLE_INSTANCE) \n \nSINGLE_INSTANCE : \nThe newly created visitor instance will be returned and saved into the Flagship singleton. Call Flagship.getVisitor() to retrieve the instance. \n \nNEW_INSTANCE: \nThe newly created visitor instance wont be saved and will simply be returned.

Visitor Builder methods :

  • func withContext(context:[String:Any])->FSVisitorBuilder

Represent the visitor's initial context key/values used for targeting. Context keys must be String, and values types must be one of the following: Number, Boolean, String.

Parameter
Type
Description

context

[String:Any]

initial context

  • func hasConsented(hasConsented:Bool)->FSVisitorBuilder

Specify if the visitor has consented to personal data usage. When false some features will be deactivated; the cache will be deactivated and cleared. The default value is true.

Parameter
Type
Description

hasConsented

Bool

true when user has given consent, false otherwise.

📘

The default value is true

  • func isAuthenticated(_ autenticated:Bool)->FSVisitorBuilder

The visitorId will be considered as authenticated if true otherwise is anonymous.

Parameter
Type
Description

autenticated

Bool

true for authenticated user, false for anonymous.

📘

The default value is false

Updating the visitor context

The user context is a property dataset that defines the current user of your app.

This dataset is sent and used by the Flagship Decision API as targeting criteria for campaign assignment.

The following method from the Visitor instance allows you to set new context values matching the given keys.

  • func updateContext(_ key:String, _ newValue:Any)

Upsert the visitor context values, matching the given keys, used for targeting. Only Integer, String, Boolean, Double typed values are accepted.

Parameter
Type
Description

key

String

Context key

newValue

Any

Context value

  • func updateContext(_ context:[String:Any])

Update visitor context using dictionary which contain several keys/values

Parameter
Type
Description

context

[String:Any]

Only Integer, String, Boolean, Double typed values are accepted.

❗️

User context values must have a type of Integer, String, Boolean, Double.

  • func updateContext(_ flagshipContext:FlagshipContext, _ value:Any)

flagshipContext

FlagshipContext

Predefined context key

value

Any

value of the associated Predefined key

  • func clearContext() Clear all the visitor context values used for targeting.

  • func getContext()->[String:Any] Get visitor current context key / values.

Managing visitor campaigns and their flags

Fetching Flags

The fetchFlags() method of the visitor instance automatically updates the campaign assignments according to the current user context and retrieves applicable flags.

  • func fetchFlags(onFetchCompleted: @escaping ()-> Void)

This function will call the decision api and update all the campaigns flags from the server according to the visitor context.

Parameter
Type
Description

onFetchCompleted

Code

Block to execute once the sync is completed

Getting flags

Once the campaign has been assigned and fetched, all the flags are stored in the SDK.

You can retrieve these flags using the following functions from the Visitor instance:

  • func getFlag<T>(key:String, defaultValue : T?)->FSFlag

Retrieve a FSFlag object by its key. If no flag match the given key an empty flag will be returned. Call exists() to check if the flag has been found.

Parameter
Type
Description

key

String

key associated to the flag

defaultValue

T

flag default value

🚧

Default value must be one of the following type : String, Boolean, Integer,Double Array, Dictionary.

Getting flags current values

To retrieve flag current value, simply call value() method of the Flag object.

  • func value(visitorExposed: Bool = true)->Any?

Returns the value from the assigned campaign variation or the Flag default value if the Flag does not exist, or if types are different.

Parameter
Type
Default value
Description

visitorExposed

Bool

true

Tells Flagship the user have been exposed and have seen this flag. This will increment the visits for the current variation on your campaign reporting. \nIf needed it is possible to set this param to false and call visitorExposed() afterward when the user has really been exposed to it.

Getting flags campaigns metadata

You may need to send campaign's informations to a third-party for reporting and/or analytics purposes. The metadata method returns a dictionary with values you can use.

  • func metadata()->FSFlagMetadata Return the campaign metadata or an empty object if the Flag doesn't exist or if the default value type does not correspond to the Flag type in Flagship.

The metadata you can access to are the following one:

FSFlagMetadata
Type
Default value
Description

campaignId

String

""

id of the campaign

campaignName

String

""

Campaign name

variationGroupId

String

""

Id of the variation group

variationGroupName

String

""

Variation group name

variationId

String

""

id of the variation assigned

variationName

String

""

Variation name

isReference

Bool

false

if true that means the assigned variation is the reference, otherwise it's not.

campaignType

String

""

Type of the campaign. Ex: AB

slug

String

""

campaign slug or empty string if not configured in the platform

📘

To get the dictionary of metadata use the toJson method through the FSFlagMetadata instance.

Report a Flag exposition

By default when the method value() is called, the SDK considers that the user has seen your Flag unless you pass false to value(). In this last case, you will have to call the visitorExposed() method.

There are two options for exposing a user to a flag:

  • Pass an visitorExposed=true parameter to the value() method.

  • Use the following visitorExposed() method from the Flag instance.

  • func visitorExposed()

🚧

Deprecated

The userExposed() method is deprecated since the version 3.2.0 please use visitorExposed() instead.

Check if a Flag exists

  • func exists()->Bool This method will return true if a Flag has been returned by Flagship.

The Visitor class provides a method to let you manage visitor consent for data privacy usage. When false, campaign activation and hits will be disabled and cache cleared.

  • func setConsent(hasConsented:Bool)

Parameter
Type
Default value
Description

hasConsented

Bool

true

Set visitor consent for private data usage. When false some features will be deactivated, cache will be deactivated and cleared.

🚧

When consent is not given:

  • Hits and Activations will be deactivated

  • All the cached visitor data will be cleared until consent is given again

  • Only consent tracking requests will be sent in order to clear server-side cached data.

Managing visitor cache

By default, the Flagship iOS SDK provides a default cache manager implementation.

This feature helps to cache visitors' data, to cache non-sent hits due to internet failures or server errors, to cache campaign assignations for offline mode and to prevent reallocation in Bucketing mode.

Indeed as the assignation is made on a local device in bucketing mode, changing campaign allocation in the platform would make visitors see different variations if there's no cache.

The default cache manager uses a local database.

Custom Cache Manager

It's possible to provide a custom cache implementation using the following protocols

protocol FSVisitorCacheDelegate

This protocol specifies the methods to implement in order to cache visitors' information.

  • func cacheVisitor(visitorId: String, _ visitorData: Data)

This method is called when the SDK needs to cache visitor information in your database.

Parameter
Type
Description

visitorId

String

Visitor unique identifier from which data need to be cached.

visitorData

Data

Visitor data to cache

  • func lookupVisitor(visitorId: String) -> Data?

This method is invoked when the SDK needs to get visitor information from database. This method must to respect a time delay which is configurable.

Parameter
Type
Description

visitorId

String

Visitor unique identifier from which data need to be loaded.

Return visitor data respecting the expected format.

  • func flushVisitor(visitorId: String)

This method is called when the SDK needs to flush visitor information in your database. For example, when the user hasn't given his consent this method will be called.

Parameter
Type
Description

visitorId

String

Visitor unique identifier from which data need to be cleared.

protocol FSHitCacheDelegate

This interface specifies the methods to implement in order to cache visitors' hits when they failed to be sent.

  • func cacheHits(hits: [String: [String: Any]])

This method will be called to cache hits depending on the cache strategy used.

Parameter
Type
Description

hits

Dictionary

key is a unique Id for each hit \n \n- value is an Dictionary that represent hit

  • func lookupHits() -> [String: [String: Any]]

This method will be called to load all hits present in database. This method have to respect a time duration, over this delay the operation is cancelled.

Parameter
Type
Description

return

Dictionary

key is a unique Id for each hit \n \n- value is an Dictionary that represent hit

  • ** func flushHits(hitIds: [String])**

This method is called when the SDK needs to flush tracking hits in your database except the consent ones. For example when the user hasn't given his consent this method will be invoked.

Parameter
Type
Description

hitIds

Array

list of hit's id to remove from database

  • func flushAllHits()

This method will be called to erase all hits in your database without exception.

Close

When your application is about to terminate, you can call the close method of Flagship class, by doing this, the batch process one last time before stop.

But don't worry if the close function is not invoked the data is stored in cache and will be processed on the next start

  • func close()

Experience Continuity

Dealing with anonymous and logged-in users, experience continuity allows you to maintain consistency between sessions and devices.

🚧

Make sure that the experience continuity option is enabled on the flagship platform before using those methods.

Authenticate

There are 2 ways to authenticate a visitor:

  1. Set key isAuthenticated to true when creating a new visitor

  2. Use authenticate method of Visitor instance

Authenticate anonymous visitor

func authenticate(visitorId:String)

Parameter
Type
Description

visitorId

String

id of the new authenticated visitor.

🚧

Because we have changed the visitor data, we have to call the fetchFlags method after calling this one to update the decision from Flagship.

The targeting / Flags could be different for the visitor.

Unauthenticate

This function change authenticated Visitor to anonymous visitor

func unauthenticate()

🚧

Because we have changed the visitor datas, we have to call the fetchFlags method after calling this one to update the decision from Flagship.

The targeting / Flags could be different for the visitor.

Code example

Let's assume basic scenario to understand how things work:

  1. Your visitor arrives on your app for the first time.

We need to initialize the visitor but as we don't know anything about this visitor, we'll create a random_Id. You can also specify some visitor context if necessary.

The actual random_Id will be what we call the _anonymous id_.

  1. Your visitor is signing in.

To tell the SDK about this status modification, you'll have to call the authenticate function which takes the required visitor id as argument.

The visitor is updated as authenticated, keeping the previous variations from campaigns that are still matched and thus gives you same flags as before being logged in.

📘

Keep in mind that if the visitor also has its context changed, you might still have changes on flags as your visitor might target new campaigns.

  1. Your visitor decides to sign out.

If you want to keep the same visitor experience, then you should do:

Final implementation example

Hit Tracking

This section helps you track your users in your application and learn how to build hits in order to feed campaign goals. For more information about our measurement protocol, read our Universal Collect documentation.

There are four different types of Hits available:

  • Screen

  • Transaction

  • Item

  • Event

They must all be sent with the following function through the visitor instance

func sendHit<T: FSTrackingProtocol>(_ event:T)

Common Parameters

These parameters can be sent with any type of hit.

Parameter
Type
Required
Description

userIp

String

No

Current user IP address

screenResolution

String

No

Screen Resolution

userLanguage

String

No

User Language

currentSessionTimeStamp

Int64

No

Current Session Timestamp

sessionNumber

Int

No

Session Number

Screen

This hit should be sent each time a visitor arrives on a new interface.

The FSScreen class represents this hit and it requires location as a string parameter.

init(_ location:String)

Parameter
Type
Required
Description

location

String

Yes

location name

Page

This hit should be sent each time a visitor visits a new local or web page in an embedded web view.

The FSPage class represent Page hit and requires location as a string parameter.

Parameter
Type
Required
Description

location

String

Yes

Valid url

Transaction

Hit to send when a user completes a Transaction.

FSTransaction represents it and requires a unique transactionId and affiliation name.

📘

The affiliation is the name of Transaction that should appear in the report

init(transactionId:String, affiliation:String)

Parameter
Type
Required
Description

transactionId

String

Yes

Transaction unique identifier.

affiliation

String

Yes

Transaction name. Name of the goal in the reporting.

revenue

Float

No

Total revenue associated with the transaction. This value should include any shipping or tax costs.

shipping

Float

No

Specifies the total shipping cost of the transaction.

tax

Float

No

Specifies the total taxes of the transaction.

currency

String

No

Specifies the currency used for all transaction currency values. Value should be a valid ISO 4217 currency code.

paymentMethod

String

No

Specifies the payment method for the transaction.

shippingMethod

String

No

Specifies the shipping method of the transaction.

itemCount

Int

No

Specifies the number of items for the transaction.

couponCode

String

No

Specifies the coupon code used by the customer for the transaction.

Item

Hit to send an item with a transaction. It must be sent after the corresponding transaction.

FSItem represents this hit and requires transactionId and product name.

init(transactionId:String, name:String, code:String)

Parameter
Type
Required
Description

transactionId

String

Yes

Transaction unique identifier

name

String

Yes

Product name

price

Float

No

Specifies the item price

code

String

Yes

Specifies the item code or SKU

category

String

No

Specifies the item category

quantity

Int

No

Specifies the item quantity

Event

Hit which represents an event. It can be anything you want: for example a click on an Add to Cart button or a newsletter subscription.

FSEvent represents this hit and requires a category event and action name string.

FSCategoryEvent can be Action_Tracking or User_Engagement.

init(eventCategory:FSCategoryEvent, eventAction:String)

Parameter
Type
Required
Description

category

FSCategoryEvent

Yes

Category of the event (Action_Tracking or User_Engagement).

action

String

yes

Name of the event.

label

String

No

Description of the event.

eventValue

UInt

No

Value of the event, must be an unsigned integer value

📘

The event action is the name of Event that should appear in the report

Appendix

Predefined user context keys

The Flagship SDK contains predefined user context keys.

The keys marked as Yes in the Auto-set by SDK column will be automatically set, while the ones marked as No need to be set by the client.

They are nevertheless overridable at anytime. Then these predefined context keys-value pairs will be sent to the server and be editable in the Persona section of the Flagship platform.

SDK Variable name
Description
Context Variable name
Type
Auto-set by SDK
Example

FIRST_TIME_INIT

First init of the app

sdk_firstTimeInit

Boolean

Yes

true (false if the init isn’t the first one)

LOCALE

Language of the device

sdk_deviceLanguage

String

Yes

fr_FR

DEVICE_TYPE

Type of the device (Tablet/Mobile/Watch)

sdk_deviceType

String

Yes

mobile

DEVICE_MODEL

Model of the device

sdk_deviceModel

String

Yes

iPhone12,8

LOCATION_CITY

City geolocation

sdk_city

String

No

toulouse

LOCATION_REGION

Region geolocation

sdk_region

String

No

occitanie

LOCATION_COUNTRY

Country geolocation

sdk_country

String

No

France

LOCATION_LAT

Current Latitude

sdk_lat

Double

No

43.623647

LOCATION_LONG

Current Longitude

sdk_long

Double

No

1.445397

OS_NAME

Name of the OS

sdk_osName

String

Yes

iOS / macOS

OS_VERSION_CODE

Version of OS

sdk_osVersionCode

String

Yes

9.0

OS_VERSION_NAME

Name of OS

sdk_osVersionName

String

Yes

iOS / tvOS

MVNO / carrierName

(Mobile virtual network operator)"

sdk_carrierName

String

No

orange

DEV_MODE

Is the app in debug mode?

sdk_devMode

Boolean

No

true

INTERNET_CONNECTION

What is the internet connection

sdk_internetConnection

String

No

3g

APP_VERSION_NAME

Version name of the app

sdk_versionName

String

No

1.1.2-beta

APP_VERSION_CODE

Version code of the app

sdk_versionCode

Number (int)

No

40

FLAGSHIP_VERSION

Version of the Flagship SDK

sdk_fsVersion

String

Yes

1.1.2

INTERFACE_NAME

Name of the interface

sdk_interfaceName

String

No

ProductPage

Here you can see how a predefined key is used to filter a report in the Flagship interface:

📘

To overwrite the keys, use the updateContext method

Last updated

Was this helpful?