{"id":2685,"date":"2016-04-12T15:16:08","date_gmt":"2016-04-12T21:16:08","guid":{"rendered":"http:\/\/dev.iachieved.it\/iachievedit\/?p=2685"},"modified":"2016-04-12T15:16:08","modified_gmt":"2016-04-12T21:16:08","slug":"service-agnostic-mobile-analytics","status":"publish","type":"post","link":"https:\/\/dev.iachieved.it\/iachievedit\/service-agnostic-mobile-analytics\/","title":{"rendered":"Service-Agnostic Mobile Analytics"},"content":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/img.shields.io\/badge\/Xcode-7.3-blue.svg?style=flat\" alt=\"Xcode 7.3\" \/> <img decoding=\"async\" src=\"https:\/\/img.shields.io\/badge\/Swift-2.2-orange.svg?style=flat\" alt=\"Swift 2.2\" \/><\/p>\n<p>Mobile application analytics is the capture and analysis of what users are doing with your mobile app.  Of course, it is a subcategory of all overall application usage analytics which covers the OS, desktop applications, web usage, and so on.  Up until earlier this year, <a href=\"http:\/\/blog.parse.com\/announcements\/moving-on\/\">Parse<\/a> was a popular cloud platform for capturing and displaying mobile app usage data.<\/p>\n<p>There are a few lessons to be learned from Parse&#8217;s abrupt departure from the scene.  Foremost, and this should come as no surprise to anyone who has done software development for more than year, <i>nothing is forever<\/i>.  Things change.  The second lesson could be, once you&#8217;ve experienced the aggravation (or pain) of changing out one framework for another, why not abstract the underlying operations a little bit and make it easier to change in the future?  We&#8217;re going to take that lesson and apply it to mobile analytics and show how you can &#8220;future proof&#8221; your application a bit.<\/p>\n<h2>Protocols<\/h2>\n<p>Apple&#8217;s <a href=\"https:\/\/developer.apple.com\/library\/ios\/documentation\/Swift\/Conceptual\/Swift_Programming_Language\/Protocols.html\">introduction to protocols<\/a> contains a very succinct definition as to what a protocol is:  <i>a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality.<\/i>  Think about how we can use that definition to define an <i>analytics event logger<\/i> protocol.  There are a few very basic methods that any logger should provide:<\/p>\n<ul>\n<li>registration to the logging backend\n<li>log an event\n<li>log an event with a data dictionary\n<\/ul>\n<p>Certainly, you could go through the various analytics platform providers and find a wide variety of features, but at the core we would like to see at least these three.  Perfect candidates for a protocol definition:<\/p>\n<pre>\nimport Foundation\n\nprotocol AnalyticsEventLogger {\n  \n  func initialize()\n  func logEvent(name:String)\n  func logEvent(name:String, data:AnyObject)\n  \n}\n<\/pre>\n<p>By itself the <code>AnalyticsEventLogger<\/code> protocol will not do anything, it is only <i>the blueprint<\/i>.  We will need an actual analytics framework to do the work.<\/p>\n<h3>Amplitude<\/h3>\n<p><a href=\"https:\/\/amplitude.com\/\">Amplitude<\/a> was the first mobile analytics service we came across when looking to migrate <a href=\"http:\/\/dev.iachieved.it\/iachievedit\/introducing-bondi\/\">Bondi<\/a> away from Parse.  It had a straightforward (and free) signup process combined with a simple API for logging events.  The implementation of an <code>AnalyticsEventLogger<\/code> protocol around Amplitude would be quite simple:<\/p>\n<pre>\nclass AmplitudeEventLogger : AnalyticsEventLogger {\n  \n  func initialize() {\n    Amplitude.instance().initializeApiKey(AmplitudeApplicationKey)\n  }\n  \n  func logEvent(name:String) {\n    Amplitude.instance().logEvent(name)\n  }\n  \n  func logEvent(name:String, data:AnyObject) {\n    Amplitude.instance().logEvent(name, withEventProperties: data as! [NSObject : AnyObject])\n  }\n\n}\n<\/pre>\n<h3>CleverTap<\/h3>\n<p><a href=\"https:\/\/clevertap.com\/\">CleverTap<\/a> is <i>another<\/i> mobile analytics service that provides for fast sign up and registration.  Truth be told, we found the actual integration of the CleverTap SDK into our application to be a bit more cumbersome.  We&#8217;ll get to the reasons why in a moment, but for the sake of completeness, here is what an event logger based upon CleverTap might look like:<\/p>\n<pre>\nimport Foundation\n\nclass CleverTapEventLogger : AnalyticsEventLogger {\n  \n  func initialize() {\n    CleverTap.changeCredentials(withAccountID: accountID, andToken: accountToken)\n  }\n  \n  func logEvent(name:String) {\n    CleverTap.sharedInstance().recordEvent(name)\n  }\n  \n  func logEvent(name:String, data:AnyObject) {\n    CleverTap.sharedInstance().recordEvent(name, withProps: data as! [NSObject:AnyObject])\n  }\n  \n}\n<\/pre>\n<p>The key thing to notice here is that the <i>protocol<\/i> dictates the methods:<\/p>\n<ul>\n<li><code>initialize()<\/code>\n<li><code>logEvent(name:String)<\/code>\n<li><code>logEvent(name:String, data:AnyObject)<\/code>\n<\/ul>\n<p>The underlying implementation for an event logger based upon Amplitude will use Amplitude SDK methods.  The implementation of the protocol based upon CleverTap will use CleverTap SDK methods.<\/p>\n<p><b>Note:<\/b>Many mobile analytics services provide many more methods than this.  For example, some provide heatmap analysis of where on the screen the user is touching.  Our goal here is not to build a protocol that encompasses <i>all<\/i> types of mobile analytics features, but a subset of those that we&#8217;ve found particularly useful.<\/p>\n<h2>Demonstration Application<\/h2>\n<p>We&#8217;ve put together a quick demonstration application that allows for you to use either Amplitude or CleverTap for event logging.  <i>This section<\/i> is a walkthrough of the demonstration application with guidance on where to plug in your API keys.  You will, however, have to actually sign up for the services online to run the app!<\/p>\n<p>The event logger itself is kept as the instance member <code>eventLogger<\/code> of the <code>AppDelegate<\/code>.<\/p>\n<pre>\nclass AppDelegate: UIResponder, UIApplicationDelegate {\n  var window: UIWindow?\n  var eventLogger:AnalyticsEventLogger = AmplitudeEventLogger()\n\n  func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {\n\n    eventLogger.initialize()\n    eventLogger.logEvent(AnalyticsStartEvent)\n    \n    return true\n  }\n\n  \/\/ Additional routines\n}\n<\/pre>\n<p>In the above code we declare an <code>eventLogger<\/code> to be an instance of a class that adheres to the <code>AnalyticsEventLogger<\/code> protocol.  The actual instance will be an <code>AmplitudeEventLogger<\/code> which we&#8217;ve outlined the implementation in the <code>AmplitudeEventLogger.swift<\/code> file.  If you want to change this out to use CleverTap, simply replace the definition with:<\/p>\n<pre>\nvar eventLogger:AnalyticsEventLogger = CleverTapEventLogger()\n<\/pre>\n<p>And in truth, you don&#8217;t even need to declare the variable type (<code>AnalyticsEventLogger<\/code>) here.  The Swift compiler will figure this out.<\/p>\n<h3>Getting the Source<\/h3>\n<p>Get the demonstration application source from BitBucket with <code>git clone git@bitbucket.org:iachievedit\/mobileanalytics.git<\/code> in a terminal.  Open the <code>appname.xcodeproj<\/code> project in Xcode.<\/p>\n<figure id=\"attachment_2718\" aria-describedby=\"caption-attachment-2718\" style=\"width: 257px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/appname_xcodeproj.png\" rel=\"attachment wp-att-2718\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/appname_xcodeproj.png\" alt=\"appname Project\" width=\"257\" height=\"402\" class=\"size-full wp-image-2718\" \/><\/a><figcaption id=\"caption-attachment-2718\" class=\"wp-caption-text\">appname Project<\/figcaption><\/figure>\n<h3>Project Basics<\/h3>\n<p>The key files to review in the demonstration project are:<\/p>\n<ul>\n<li><code>AnalyticsEventLogger.swift<\/code> &#8211; this file contains our <code>AnalyticsEventLogger<\/code> protocol that all &#8220;event loggers&#8221; will adhere to\n<li><code>AmplitudeEventLogger.swift<\/code> &#8211; an implementation of the <code>AnalyticsEventLogger<\/code> protocol using the Amplitude service is here\n<li><code>CleverTapEventLogger.swift<\/code> &#8211; an implementation of the <code>AnalyticsEventLogger<\/code> protocol using the CleverTap service is here\n<li><code>EventConstants.swift<\/code> &#8211; event names for all of the backend services using Swift constant definitions\n<li><code>ViewController.swift<\/code> &#8211; our demonstration application logs analytics events when buttons are pressed on the screen.  The <code>IBAction<\/code> routines for these presses are in the view controller.\n<li><code>ApiKeys.swift<\/code> &#8211; this file contains a routine we use for extract API keys from a <code>.plist<\/code> file.  Details on how this is used is covered in the next section <b>API Keys<\/b>!\n<\/ul>\n<h3>API Keys<\/h3>\n<p>Most, if not all, analytics platform will have you use either a single application key or combination of account identifier and application key.  Amplitude and CleverTap are no different.  The sample application utilizes <a href=\"https:\/\/developer.apple.com\/library\/ios\/documentation\/Cocoa\/Conceptual\/PropertyLists\/Introduction\/Introduction.html\">property lists<\/a> for <a href=\"http:\/\/dev.iachieved.it\/iachievedit\/using-property-lists-for-api-keys-in-swift-applications\/\">managing API keys<\/a>.  If you <i>haven&#8217;t<\/i> signed up for any service, jump down to the sections on signing up for <a href=\"#amplitude\">Amplitude<\/a> or <a href=\"#clevertap\">CleverTap<\/a> and register for the services.<\/p>\n<p>Notice that the <code>ApiKeys.plist<\/code> file above is red.  That means it is missing, so you&#8217;ll need to create one to add keys for the mobile analytics providers you choose.  To be able to switch back and forth between the Amplitude and CleverTap you&#8217;ll need accounts and API keys for both.  You can follow though the instructions below to obtain those, or, even use the starter application as a template to try out other services such as <a href=\"https:\/\/dev.flurry.com\/\">Flurry<\/a> or <a href=\"http:\/\/appanalytics.io\/\">AppAnalytics<\/a>.<\/p>\n<p>Create the <code>ApiKeys.plist<\/code> file using Xcode <b>File &#8211; New &#8211; File<\/b> and then select <b>iOS Resource<\/b>, and choose the <b>Property List<\/b> template.  Click <b>Next<\/b> and name the file <code>ApiKeys.plist<\/code> and ensure that the dialog box includes adding it to the application target.<\/p>\n<p>Add keys for <code>AmplitudeDevelopmentApplicationKey<\/code> etc., one for each key that you will need to reference in the project.  If you follow through with this example and use Amplitude and CleverTap, your <code>ApiKeys.plist<\/code> file should look something like this:<\/p>\n<figure id=\"attachment_2722\" aria-describedby=\"caption-attachment-2722\" style=\"width: 880px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/ApiKeys_plist.png\" rel=\"attachment wp-att-2722\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/ApiKeys_plist.png\" alt=\"ApiKeys.plist\" width=\"880\" height=\"150\" class=\"size-full wp-image-2722\" \/><\/a><figcaption id=\"caption-attachment-2722\" class=\"wp-caption-text\">ApiKeys.plist<\/figcaption><\/figure>\n<p>Once the API keys are in place, update the <code>AppDelegate<\/code> to choose the logger you want to use and then run the application either on a phone or the simulator.<\/p>\n<figure id=\"attachment_2725\" aria-describedby=\"caption-attachment-2725\" style=\"width: 323px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/appname.png\" rel=\"attachment wp-att-2725\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/appname.png\" alt=\"Logging Events\" width=\"323\" height=\"504\" class=\"size-full wp-image-2725\" \/><\/a><figcaption id=\"caption-attachment-2725\" class=\"wp-caption-text\">Logging Events<\/figcaption><\/figure>\n<p>Pressing on the <b>Like<\/b>, <b>Dislike<\/b>, etc. buttons will call the mobile analytics logging methods (see the <code>ViewController.swift<\/code> file).  In the case of the <b>Donate<\/b> button the logged method will include the amount donated.<\/p>\n<h2 id=\"amplitude\">Getting Started with Amplitude<\/h2>\n<p><b>Note:<\/b>  This a quick introduction to signing up for Amplitude and is not meant to be a full-featured tutorial on all of its features.<\/p>\n<p>First, you&#8217;ll need to sign up for Amplitude on their <a href=\"https:\/\/amplitude.com\/signup\">sign up<\/a> page.  Fill in all of the required information (name, email, etc.), and get greeted with a <b>Welcome to Amplitude<\/b> dialog.<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/AmplitudeAnalytics.png\" rel=\"attachment wp-att-2703\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/AmplitudeAnalytics.png\" alt=\"AmplitudeAnalytics\" width=\"600\" height=\"355\" class=\"aligncenter size-full wp-image-2703\" \/><\/a><\/p>\n<p>Click on the <b>Let&#8217;s Go<\/b> button and create your first application.  We&#8217;re going to put in our organization as iAchieved.it LLC and the application will be <b>Appname Development<\/b>.  There will be different &#8220;keys&#8221; for development vs. release applications.<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/SetupOrganizationAndApp.png\" rel=\"attachment wp-att-2705\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/SetupOrganizationAndApp.png\" alt=\"SetupOrganizationAndApp\" width=\"600\" height=\"302\" class=\"aligncenter size-full wp-image-2705\" \/><\/a><\/p>\n<p>Click <b>Continue<\/b> and select the iOS SDK and click <b>I&#8217;m Ready to Install<\/b>.  Amplitude will present a <b>Install the Amplitude SDK<\/b> page which provides a set of instructions for downloading the iOS SDK, updating your projects build settings to include SQLite, and then showing an Objective C example of invoking the service.  We&#8217;re passionate about using Swift for applications, so at this stage click on the <a href=\"https:\/\/github.com\/amplitude\/Amplitude-iOS\/archive\/master.zip\">Download the source code<\/a> link to pull down the iOS source for Amplitude.  Unzip the downloaded folder.<\/p>\n<p>The demonstration application provided already contains the Amplitude SDK, but if you were starting a new project drag and drop the <code>Amplitude<\/code> subfolder into your project.  Make sure and select <b>Copy items if needed<\/b>, <b>Create groups<\/b>, and of course ensure your application target is selected.<\/p>\n<figure id=\"attachment_2730\" aria-describedby=\"caption-attachment-2730\" style=\"width: 947px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/AddingAmplitude.png\" rel=\"attachment wp-att-2730\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/AddingAmplitude.png\" alt=\"AddingAmplitude\" width=\"947\" height=\"368\" class=\"size-full wp-image-2730\" \/><\/a><figcaption id=\"caption-attachment-2730\" class=\"wp-caption-text\">AddingAmplitude<\/figcaption><\/figure>\n<p>Back in the Amplitude portal you can just click <b>Continue<\/b> on the <b>Install Amplitude SDK<\/b> page and then click <b>Done<\/b>, and then when prompted to invite members to your team click <b>Skip<\/b>.<\/p>\n<h3>Add Additional Frameworks<\/h3>\n<p>Add the following frameworks to your Xcode Project:<\/p>\n<ul>\n<li>libsqlite.tbd\n<\/ul>\n<p>Frameworks are easily added by going to your project target application and then selecting <b>Build Phases<\/b>, then going to the <b>Link Binary With Libraries<\/b> and then using the <b>+<\/b> icon to select the framework.<\/p>\n<h3 id=\"bridging\">Add a Bridging Header<\/h3>\n<p>At iAchieved.it we&#8217;ve been using Swift since the day it came out and haven&#8217;t looked back.  If you too are developing your applications with Swift you&#8217;ll need to add a <i>bridging header<\/i> to your project to access the Amplitude API.  Bridging headers are easy to add.  First, use <b>File &#8211; New &#8211; File<\/b> and select <b>iOS Source<\/b>, and then find the <b>Header file<\/b> icon.  Name the file <code>bridgingHeader.h<\/code>.<\/p>\n<p>Next, go to your application target and click on <b>Build Settings<\/b>.  Type <code>bridging<\/code> into the search box to see something like:<\/p>\n<figure id=\"attachment_2742\" aria-describedby=\"caption-attachment-2742\" style=\"width: 873px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/bridgingheader.png\" rel=\"attachment wp-att-2742\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/bridgingheader.png\" alt=\"Bridging Header\" width=\"873\" height=\"263\" class=\"size-full wp-image-2742\" \/><\/a><figcaption id=\"caption-attachment-2742\" class=\"wp-caption-text\">Bridging Header<\/figcaption><\/figure>\n<p>Double-click on the line that says <b>Objective-C Bridging Header<\/b> and type into the dialog box <code>$(SRCROOT)\/bridgingHeader.h<\/code>.  The <code>$(SRCROOT)<\/code> variable will be expanded to your <a href=\"https:\/\/developer.apple.com\/library\/ios\/documentation\/DeveloperTools\/Reference\/XcodeBuildSettingRef\/1-Build_Setting_Reference\/build_setting_ref.html#\/\/apple_ref\/doc\/uid\/TP40003931-CH3-SW38\">project&#8217;s source root <\/a>.<\/p>\n<p>Now, in the <code>bridgingHeader.h<\/code> add the line <code>#import \"Amplitude.h\"<\/code>.<\/p>\n<h3>API Credentials<\/h3>\n<p>The API credentials you will need for your application are easy to find in Amplitude.  In the web portal, click on the account e-mail in the upper-right and select <b>Account Settings<\/b> in the dropdown menu.<\/p>\n<figure id=\"attachment_2733\" aria-describedby=\"caption-attachment-2733\" style=\"width: 896px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/AmplitudeApiKeys.png\" rel=\"attachment wp-att-2733\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/AmplitudeApiKeys.png\" alt=\"Amplitude API Keys \" width=\"896\" height=\"252\" class=\"size-full wp-image-2733\" \/><\/a><figcaption id=\"caption-attachment-2733\" class=\"wp-caption-text\">Amplitude API Keys<br \/><\/figcaption><\/figure>\n<p>In our demonstration application we&#8217;re using the <code>.plist<\/code> method for storing API keys, so take the appropriate key and add to the <code>ApiKeys.plist<\/code> file.  Alternatively you can put the API key directly in the <code>Amplitude.instance.initializeApiKey<\/code> method in the <code>AmplitudeEventLogger.swift<\/code> file.<\/p>\n<h2 id=\"clevertap\">Getting Started With CleverTap<\/h2>\n<p><b>Note:<\/b> This a quick introduction to signing up for CleverTap and is not meant to be a full-featured tutorial on all of its features.<\/p>\n<p>We found working with CleverTap to be a little less intuitive than Amplitude.  Nevertheless, it doesn&#8217;t require a credit card to get started which makes it easy to try-before-you-might-buy.<\/p>\n<p>Sign up with CleverTap by heading over to <a href=\"https:\/\/clevertap.com\/sign-up\/\">Sign Up<\/a> page and filling out the required information.  You&#8217;ll get an activation e-mail sent which contains a link to complete the sign up process.  Find the e-mail and click on the <b>Complete your signup<\/b> button.<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/WelcomeToCleverTap.png\" rel=\"attachment wp-att-2710\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/WelcomeToCleverTap.png\" alt=\"WelcomeToCleverTap\" width=\"885\" height=\"289\" class=\"aligncenter size-full wp-image-2710\" \/><\/a><\/p>\n<p>Click the <b>Add my first app<\/b> button to take you to the next screen:<\/p>\n<figure id=\"attachment_2745\" aria-describedby=\"caption-attachment-2745\" style=\"width: 461px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/AddYourApp2.png\" rel=\"attachment wp-att-2745\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/AddYourApp2.png\" alt=\"Add Your App\" width=\"461\" height=\"508\" class=\"size-full wp-image-2745\" \/><\/a><figcaption id=\"caption-attachment-2745\" class=\"wp-caption-text\">Add Your App<\/figcaption><\/figure>\n<p>Notice that in CleverTap a <b>TEST<\/b> environment automatically gets created for your application.  Frankly I <i>don&#8217;t<\/i> care for this feature because it makes assumptions about what your environments are named.  With Amplitude you would manage your own development vs. staging vs. release applications, whereas CleverTap simply assumes you&#8217;ll have a <b>TEST-<\/b> application.<\/p>\n<p>Click on <b>Add My App<\/b>.  You&#8217;ll be presented with a screen where you can select which ecosystem you&#8217;re developing for (Android, iOS, Windows, etc.) and provide the AppStore URL for your application.  Select iOS and click on <b>Skip URL<\/b>.<\/p>\n<p>Here too the integration instructions for CleverTap are not as straightforward as they could be.  We suggest you click on <b>Skip Integration<\/b> and then follow these instructions:<\/p>\n<h3>Obtain the CleverTap iOS SDK<\/h3>\n<p>A download link to the CleverTap iOS SDK can be found on the <a href=\"https:\/\/support.clevertap.com\/integration\/ios-sdk\/\">iOS SDK integration page<\/a>.  Choose the download for either Xcode 7 or Xcode 6, and a file named something like <code>CleverTapSDK-v2.0.10-20160405.framework.zip<\/code> will be placed in your <code>Downloads<\/code> folder.  Unzip the file and a single framework file <code>CleverTapSDK.framework<\/code> will be there in the <code>Downloads<\/code> folder.  Drag and drop the <code>CleverTapSDK.framework<\/code> file to your Xcode project ensuring that <b>Copy items if necessary<\/b> and <b>Create groups<\/b> is selected, and of course you will want to add it to your application target.<\/p>\n<h3>Add Additional Frameworks<\/h3>\n<p>Add the following frameworks to your Xcode Project:<\/p>\n<ul>\n<li>SystemConfiguration\n<li>CoreTelephony\n<li>Security\n<li>UIKit\n<li>CoreLocation\n<\/ul>\n<h3>Add a Bridging Header (If You&#8217;re Using Swift)<\/h3>\n<p>As with Amplitude, if you are using Swift you will want to add a bridging header.  Refer <a href=\"#bridging\">back<\/a> for quick instructions on adding the header file.  In the <code>bridgingHeader.h<\/code> add the line <code>#import &lt;CleverTapSDK\/CleverTap.h&gt;<\/code>.<\/p>\n<h3>API Credentials<\/h3>\n<p>CleverTap tries to be a bit too clever with its API keys.  There is a method that can be called, <code>autoIntegrate<\/code>, that &#8220;registers everything&#8221; with the CleverTap backend.  There are no arguments to the <code>autoIntegrate<\/code> method and its only after looking closely at this<\/p>\n<figure id=\"attachment_2748\" aria-describedby=\"caption-attachment-2748\" style=\"width: 1284px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/cleverTapCredentials.png\" rel=\"attachment wp-att-2748\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2016\/04\/cleverTapCredentials.png\" alt=\"CleverTap Autointegrate\" width=\"1284\" height=\"324\" class=\"size-full wp-image-2748\" \/><\/a><figcaption id=\"caption-attachment-2748\" class=\"wp-caption-text\">CleverTap Autointegrate<\/figcaption><\/figure>\n<p>that it is clear you need to add two keys <code>CleverTapAccountID<\/code> and <code>CleverTapToken<\/code> to &#8220;your <code>.plist<\/code> file&#8221;.  One assumes that is referring to the <code>Info.plist<\/code> file, but if you are going to manage a test application and regular application, juggling <code>.plist<\/code> files in conditional builds is annoying.  So rather than use the <code>autoIntegrate<\/code> method you can use <code>changeCredentials(withAccountID:andToken)<\/code>.  This skips the auto-integration and need for using <code>.plist<\/code> files to manage the API keys.  Instead you can use something like:<\/p>\n<pre>\nlet accountID    = valueForAPIKey(named:\"CleverTapDevelopmentAccountID\")\nlet accountToken = valueForAPIKey(named:\"CleverTapDevelopmentAccountToken\")\nCleverTap.changeCredentials(withAccountID: accountID, andToken: accountToken)\n<\/pre>\n<p><b>Note:<\/b> The <code>valueForAPIKey<\/code> routine comes from our post on managing API keys with property lists, but using this method you can determine the name of the key.<\/p>\n<h2>Closing Thoughts<\/h2>\n<p>Software developers are interesting creatures.  We frequently want to rewrite things when there is a new language or framework to work with, yet we don&#8217;t necessarily care for changing things when its forced on us.  There is also a desire to develop &#8220;systems&#8221; that are extensible and can adapt to tomorrow&#8217;s requirements.  Our service-agnostic event logging follows the spirit of this approach, but even still one must recognize that tomorrow&#8217;s mobile analytics platforms will provide us with new features and capabilities that require adapting to if they are to be utilized.  In other words, the approach we used here is by no means the final story, and as new services are evaluated we must always be prepared to rework areas of the code that are no longer capable of fitting our needs.  Even still, after you&#8217;ve been through the headache of changing APIs due to one reason or another (your favorite API is <a href=\"https:\/\/allseeing-i.com\/asihttprequest\/\">abandoned<\/a>, <a href=\"https:\/\/github.com\/AFNetworking\/AFNetworking\">isn&#8217;t Swifty enough for you<\/a>, or otherwise end-of-lifed like Parse), you might consider using a protocol-based approach to provide a neutral shim between you and another service.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mobile application analytics is the capture and analysis of what users are doing with your mobile app. Of course, it is a subcategory of all overall application usage analytics which covers the OS, desktop applications, web usage, and so on. Up until earlier this year, Parse was a popular cloud platform for capturing and displaying [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11,5],"tags":[],"class_list":["post-2685","post","type-post","status-publish","format-standard","hentry","category-apple","category-swift"],"_links":{"self":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/2685"}],"collection":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/comments?post=2685"}],"version-history":[{"count":59,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/2685\/revisions"}],"predecessor-version":[{"id":2761,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/2685\/revisions\/2761"}],"wp:attachment":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/media?parent=2685"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/categories?post=2685"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/tags?post=2685"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}