pushplay

interactive · design · studio


< Back to Main

Capturing tracking statistics from an iPhone application

May 20, 2009
|

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,
  `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.)

<?
 
 mysql_connect ("localhost", "DATABASE_USER_NAME",
   "DATABASE_USER_PASSWORD");
 mysql_select_db ("DATABASE_NAME");
 
 $dateCreated = date ("Y-m-d H:i:s");
 $strIPCreated = $_SERVER[REMOTE_ADDR];
 
 
 function cleanString ($strInput) {
 
   $strInput = trim(strip_tags ($strInput));
 
   return (mysql_real_escape_string ($strInput));
 }
 
 
 $_POST[a] = cleanString ($_POST[a]);
 $_POST[b] = cleanString ($_POST[b]);
 $_POST[c] = cleanString ($_POST[c]);
 $_POST[d] = cleanString ($_POST[d]);
 $_POST[e] = cleanString ($_POST[e]);
 $_POST[f] = cleanString ($_POST[f]);
 
 // check to see if UDID is in database
 // if not, add it
 
 $qry = mysql_query ("SELECT intDeviceID, intTotalUpdates
   FROM TableDevices WHERE strDeviceUniqueIdentifier = '$_POST[f]'");
 if ($qry != "" && mysql_num_rows ($qry) > 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]',
            dateUpdated = '$dateCreated',
            strIPUpdated = '$strIPCreated',
            intTotalUpdates = '$intTotalUpdates'
     WHERE
       intDeviceID = '$intDeviceID'");
 
 
 } else {
          $qry2 = mysql_query ("INSERT INTO TableDevices (
            strDeviceName,
            strDeviceModel,
            strDeviceLocalizedModel,
            strDeviceSystemName,
            strDeviceSystemVersion,
            strDeviceUniqueIdentifier,
            dateCreated,
            strIPCreated,
            intTotalUpdates
          ) VALUES (
            '$_POST[a]',
            '$_POST[b]',
            '$_POST[c]',
            '$_POST[d]',
            '$_POST[e]',
            '$_POST[f]',
            '$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];
 
       NSString *myRequestString = [NSString
         stringWithFormat:@"a=%@&b=%@&c=%@&d=%@&e=%@&f=%@", 
         device.name, device.model, device.localizedModel,
         device.systemName, device.systemVersion, device.uniqueIdentifier];
       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...

1 Comments

02 Jul
2009
Alexandra Asselin Hernandez
Very smart you are.....

Submit a Comment:

Your Name:
Email Address:
Comments:
Enter what you see: Verification Image