Capturing tracking statistics from an iPhone application

I wanted to collect usage statistics from the users of my iPhone applications. The information Apple collects about free vs paid downloads is interesting, but a little hard to analyze. I wanted to see how much information I could collect, as well as run my own custom queries against a database of statistical information.

In order to do this, I set up a MySQL database online, with a PHP script to enter data into the database. Then I added some code to my main appDelegate.m file to check to see if there was an internet connection, and if so, send the device information. The PHP script then checks the database to see if that device is already in the database and if not, adds it. If it was in the database already, it just increments the number of accesses.

MySQL code

The following are the tables that need to be created within a MySQL database to store the information that you will be collecting.

--
-- Table structure for table `TableDevices`
--
 
CREATE TABLE IF NOT EXISTS `TableDevices` (
  `intDeviceID` int(11) NOT NULL auto_increment,
  `strDeviceName` tinytext NOT NULL,
  `strDeviceModel` tinytext NOT NULL,
  `strDeviceLocalizedModel` tinytext NOT NULL,
  `strDeviceSystemName` tinytext NOT NULL,
  `strDeviceSystemVersion` tinytext NOT NULL,
  `strDeviceUniqueIdentifier` tinytext NOT NULL,
  `strDeviceLocale` tinytext NOT NULL,
  `strDeviceLanguage` tinytext NOT NULL,
  `intTotalUpdates` int(11) NOT NULL,
  `dateCreated` datetime NOT NULL,
  `dateUpdated` datetime NOT NULL,
  `strIPCreated` tinytext NOT NULL,
  `strIPUpdated` tinytext NOT NULL,
  PRIMARY KEY  (`intDeviceID`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

PHP code

(You will need to change DATABASE_USER_NAME, DATABASE_USER_PASSWORD, and DATABASE_NAME below to the appropriate values for your MySQL server instance.)

 0) {
   $arr = mysql_fetch_array ($qry);
   $intTotalUpdates = $arr[intTotalUpdates] + 1;
   $intDeviceID = $arr[intDeviceID];
   $qry2 = mysql_query ("UPDATE TableDevices
     SET
            strDeviceName = '$_POST[a]',
            strDeviceModel = '$_POST[b]',
            strDeviceLocalizedModel = '$_POST[c]',
            strDeviceSystemName = '$_POST[d]',
            strDeviceSystemVersion = '$_POST[e]',
            strDeviceLocale = '$_POST[g]',
            strDeviceLanguage = '$_POST[h]',
            dateUpdated = '$dateCreated',
            strIPUpdated = '$strIPCreated',
            intTotalUpdates = '$intTotalUpdates'
     WHERE
       intDeviceID = '$intDeviceID'");
 
 
 } else {
          $qry2 = mysql_query ("INSERT INTO TableDevices (
            strDeviceName,
            strDeviceModel,
            strDeviceLocalizedModel,
            strDeviceSystemName,
            strDeviceSystemVersion,
            strDeviceUniqueIdentifier,
            strDeviceLocale,
            strDeviceLanguage,
            dateCreated,
            strIPCreated,
            intTotalUpdates
          ) VALUES (
            '$_POST[a]',
            '$_POST[b]',
            '$_POST[c]',
            '$_POST[d]',
            '$_POST[e]',
            '$_POST[f]',
            '$_POST[g]',
            '$_POST[h]',
            '$dateCreated',
            '$strIPCreated',
            '1'
          )");  }
 
 echo "1";
 
?>

iPhone Code

Based on a View Controller application template, the following would need to be added to the main AppDelegate.m file.

You will need to change the host_naem and the strDeviceStatPath below to be whatever your web server addresses are.

NOTE: You’ll also need to add the SystemConfiguration.framework to the list of frameworks in your iPhone application!

#import <SystemConfiguration/SystemConfiguration.h>
 
 
const char *host_name = "www.site.com";
const char *strDeviceStatPath = "http://www.site.com/appname/stats.php";
 
NSMutableURLRequest *urlRequest;
BOOL _isDataSourceAvailable = NO;
 
 
- (BOOL) isDataSourceAvailable {
   static BOOL checkNetwork = YES;
   if (checkNetwork) {
       checkNetwork = NO;
 
       Boolean success;
 
       SCNetworkReachabilityRef reachability = 
         SCNetworkReachabilityCreateWithName(NULL, host_name);
       SCNetworkReachabilityFlags flags;
       success = SCNetworkReachabilityGetFlags(reachability, &flags);
       _isDataSourceAvailable = success
         && (flags & kSCNetworkFlagsReachable)
         && !(flags & kSCNetworkFlagsConnectionRequired);
       CFRelease(reachability);
   }
       return _isDataSourceAvailable;
}
 
-(void) sendUsageStatistics {
 
       UIDevice *device = [UIDevice currentDevice];
	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
	NSArray *languages = [defaults objectForKey:@"AppleLanguages"];
	NSString *currentLanguage = [languages objectAtIndex:0];
 
       NSString *myRequestString = [NSString
         stringWithFormat:@"a=%@&b=%@&c=%@&d=%@&e=%@&f=%@&g=%@&h=%@", 
         device.name, device.model, device.localizedModel,
         device.systemName, device.systemVersion, device.uniqueIdentifier,
	 [[NSLocale currentLocale] localeIdentifier], currentLanguage];
       NSData *myRequestData = [ NSData
         dataWithBytes:[ myRequestString UTF8String ]
         length: [ myRequestString length ] ];
       urlRequest = [ [ NSMutableURLRequest alloc ]
         initWithURL:[ NSURL URLWithString:
           [NSString stringWithFormat:@"%s", strDeviceStatPath] ] ];
 
       [urlRequest setValue:@"application/x-www-form-urlencoded"
         forHTTPHeaderField:@"content-type"];
       [urlRequest setHTTPMethod: @"POST"];
       [urlRequest setHTTPBody: myRequestData];
 
       NSData *returnData = [NSURLConnection
         sendSynchronousRequest:urlRequest
         returningResponse:nil error:nil];
       returnData = nil;
 
}
 
 
 
 
- (void)applicationDidFinishLaunching:(UIApplication *)application {
 
   if ([self isDataSourceAvailable] == YES) {
       [self sendUsageStatistics];
       }
 
   // Override point for customization after app launch
   [window addSubview:viewController.view];
   [window makeKeyAndVisible];
}

And that’s it! It’s a little complicated to set up at first, but once you have it set up, you’ll be able to collect some very interesting data on how many people are using your application, as well as how often they use it. This can also be extended to save total playing time, “hits” on different views within your application, or anything else that can help you make your application more usable (or help debug where people seem to be getting stuck…

jeffrey

About jeffrey

Jeffrey Berthiaume is a multimedia developer and internet architect who has designed and built award-winning websites, kiosks, and content management systems. He bridges the gap between creative and technology with an ability to balance the needs of designers and marketing with the capabilities of existing technology.
This entry was posted in iOS, Tutorials. Bookmark the permalink.

One Response to Capturing tracking statistics from an iPhone application

  1. Ryan says:

    Genius! Keep up the great code, sir!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>