Create a gist now

Instantly share code, notes, and snippets.

This is a little CommonJS library I put together for adding Mixpanel tracking to an iOS and Android Appcelerator Titanium app I built. YMMV. I'm sharing it since I hadn't seen anything similar, and Mixpanel rocks. There are no native dependencies. All Mixpanel API calls are made by using the HTTP specification (https://mixpanel.com/docs/api-docu…
// The currentUser lib stores a model representing the logged in user, and other login state information
var currentUser = require('currentUser');
// Logger is a Ti.API.info() wrapper with a bit more flexibility
var logger = require('logger');
var messageQueue = []; // put this into local storage at some point to retain recent offline events before crashes
var messageInTransit = null;
var token = Ti.App.Properties.getString('mixpanel.token');
var systemProperties = {
mobile_osname: Ti.Platform.osname,
mobile_ostype: Ti.Platform.ostype,
mobile_osversion: Ti.Platform.version,
mobile_device_mfg: Ti.Platform.manufacturer,
mobile_device_model: Ti.Platform.model,
mobile_locale: Ti.Platform.locale
};
var uuid = Ti.Platform.createUUID();
exports.track = function(event, properties) {
logger.info('mixpanel track ' + event);
properties = properties || {};
properties = _.extend(properties, systemProperties);
properties.time = (new Date()).getTime();
properties.token = token;
properties.distinct_id = currentUser.isLoggedIn ? currentUser.user.get('email') : uuid;
event = "(App) " + event;
messageQueue.push({
payload: {
event: event,
properties: properties
},
type: 'event'
});
sendNextMessage();
};
exports.alias = function() {
if(currentUser.isLoggedIn) {
logger.info('mixpanel alias');
messageQueue.push({
payload: {
event: '$create_alias',
properties: {
"alias": currentUser.user.get('email'),
"distinct_id": uuid,
"time": (new Date()).getTime(),
"token": token
}
},
type: 'event'
});
sendNextMessage();
}
};
exports.people = {
set: function(properties) {
properties = properties || {};
logger.info('mixpanel people.set ' + properties);
if(!currentUser.isLoggedIn) {
console.log('mixpanel people.set skipped - user not logged in');
return false;
}
properties = _.extend(properties, systemProperties);
properties = _.extend(properties, {
'$first_name': currentUser.user.get('first_name'),
'$last_name': currentUser.user.get('last_name'),
'$username': currentUser.user.get('username'),
'$email': currentUser.user.get('email'),
});
var payload = {
'$set': properties,
'$token': token,
'$distinct_id': currentUser.user.get('email')
};
messageQueue.push({
payload: payload,
type: 'people.set'
});
sendNextMessage();
}
};
function sendMessage(message) {
var url = '';
if(message.type == 'event') {
url = "http://api.mixpanel.com/track/?data=" + Titanium.Utils.base64encode(JSON.stringify(message.payload)) + "&ip=1";
} else if(message.type == 'people.set') {
url = "http://api.mixpanel.com/engage/?data=" + Titanium.Utils.base64encode(JSON.stringify(message.payload));
}
xhr = Titanium.Network.createHTTPClient({
onload : function(e) {
messageInTransit = false;
messageQueue.shift();
sendNextMessage();
},
onerror: function(e){
messageInTransit = false;
logger.info('Failed mixpanel event with status ' + this.status + ' and error : ' + JSON.stringify(e));
setTimeout(function() {
sendNextMessage();
}, 2000); // wait a couple of seconds before we try this again
},
timeout: config.imageUploadTimeout
});
xhr.open('POST', url);
xhr.send();
}
function sendNextMessage() {
if(!Ti.Network.online) {
setTimeout(sendNextMessage, 10000);
return false;
}
if(messageInTransit)
return false;
if(messageQueue.length > 0) {
messageInTransit = messageQueue[0]; // FIFO
sendMessage(messageInTransit);
}
}
@mattberg

This is great. I think switching to the "Batch" type of request, every 20 seconds or so, and it would be perfect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment