feat(analytics): Mixpanel implementation WIP

This commit is contained in:
Sabe Jones
2015-05-27 12:44:38 -05:00
parent 39cb9bfb99
commit 726a8f1acb
15 changed files with 84 additions and 8 deletions

View File

@@ -449,6 +449,7 @@ api.wrap = (user, main=true) ->
user.items.gear.equipped[item.type] = "#{item.type}_base_0" if user.items.gear.equipped[item.type] is lostItem user.items.gear.equipped[item.type] = "#{item.type}_base_0" if user.items.gear.equipped[item.type] is lostItem
user.items.gear.costume[item.type] = "#{item.type}_base_0" if user.items.gear.costume[item.type] is lostItem user.items.gear.costume[item.type] = "#{item.type}_base_0" if user.items.gear.costume[item.type] is lostItem
user.markModified? 'items.gear' user.markModified? 'items.gear'
mixpanel?.track('Death',{'lostItem':lostItem})
cb? (if item then {code:200,message: i18n.t('messageLostItem', {itemText: item.text(req.language)}, req.language)} else null), user cb? (if item then {code:200,message: i18n.t('messageLostItem', {itemText: item.text(req.language)}, req.language)} else null), user
reset: (req, cb) -> reset: (req, cb) ->
@@ -483,6 +484,7 @@ api.wrap = (user, main=true) ->
task.value = 0 task.value = 0
user.stats.hp = 50 user.stats.hp = 50
cb? null, user cb? null, user
mixpanel?.track("Acquire Item",{'itemName':'Fortify','acquireMethod':'Gems','gemCost':4})
ga?.event('behavior', 'gems', 'reroll').send() ga?.event('behavior', 'gems', 'reroll').send()
rebirth: (req, cb, ga) -> rebirth: (req, cb, ga) ->
@@ -492,6 +494,8 @@ api.wrap = (user, main=true) ->
# only charge people if they are under the max level - ryan # only charge people if they are under the max level - ryan
if user.stats.lvl < api.maxLevel if user.stats.lvl < api.maxLevel
user.balance -= 2 user.balance -= 2
mixpanel?.track("Acquire Item",{'itemName':'Rebirth','acquireMethod':'Gems','gemCost':8})
ga?.event('behavior', 'gems', 'rebirth').send()
# Save off user's level, for calculating achievement eligibility later # Save off user's level, for calculating achievement eligibility later
lvl = api.capByLevel(user.stats.lvl) lvl = api.capByLevel(user.stats.lvl)
# Turn tasks yellow, zero out streaks # Turn tasks yellow, zero out streaks
@@ -541,7 +545,6 @@ api.wrap = (user, main=true) ->
user.stats.buffs = {} user.stats.buffs = {}
# user.markModified? 'stats' # user.markModified? 'stats'
cb? null, user cb? null, user
ga?.event('behavior', 'gems', 'rebirth').send()
allocateNow: (req, cb) -> allocateNow: (req, cb) ->
_.times user.stats.points, user.fns.autoAllocate _.times user.stats.points, user.fns.autoAllocate
@@ -752,7 +755,8 @@ api.wrap = (user, main=true) ->
user.balance += .25 user.balance += .25
user.purchased.plan.gemsBought++ user.purchased.plan.gemsBought++
user.stats.gp -= convRate user.stats.gp -= convRate
return cb? {code:200,message:"+1 Gems"}, _.pick(user,$w 'stats balance') mixpanel?.track("Acquire Item",{'itemName':key,'acquireMethod':'Gold','goldCost':convRate})
return cb? {code:200,message:"+1 Gem"}, _.pick(user,$w 'stats balance')
return cb?({code:404,message:":type must be in [eggs,hatchingPotions,food,quests,gear]"},req) unless type in ['eggs','hatchingPotions','food','quests','gear'] return cb?({code:404,message:":type must be in [eggs,hatchingPotions,food,quests,gear]"},req) unless type in ['eggs','hatchingPotions','food','quests','gear']
if type is 'gear' if type is 'gear'
@@ -769,6 +773,7 @@ api.wrap = (user, main=true) ->
else else
user.items[type][key] = 0 unless user.items[type][key] > 0 user.items[type][key] = 0 unless user.items[type][key] > 0
user.items[type][key]++ user.items[type][key]++
mixpanel?.track("Acquire Item",{'itemName':key,'acquireMethod':'Gems','gemCost':item.value})
cb? null, _.pick(user,$w 'items balance') cb? null, _.pick(user,$w 'items balance')
ga?.event('behavior', 'gems', key).send() ga?.event('behavior', 'gems', key).send()
@@ -784,6 +789,7 @@ api.wrap = (user, main=true) ->
user.achievements.beastMasterCount++ user.achievements.beastMasterCount++
user.items.currentPet = "" user.items.currentPet = ""
cb? null, user cb? null, user
mixpanel?.track("Acquire Item",{'itemName':'Kennel Key','acquireMethod':'Gems','gemCost':4})
releaseMounts: (req, cb) -> releaseMounts: (req, cb) ->
if user.balance < 1 if user.balance < 1
@@ -797,6 +803,7 @@ api.wrap = (user, main=true) ->
user.achievements.mountMasterCount = 0 user.achievements.mountMasterCount = 0
user.achievements.mountMasterCount++ user.achievements.mountMasterCount++
cb? null, user cb? null, user
mixpanel?.track("Acquire Item",{'itemName':'Kennel Key','acquireMethod':'Gems','gemCost':4})
releaseBoth: (req, cb) -> releaseBoth: (req, cb) ->
if user.balance < 1.5 and not user.achievements.triadBingo if user.balance < 1.5 and not user.achievements.triadBingo
@@ -804,6 +811,7 @@ api.wrap = (user, main=true) ->
else else
giveTriadBingo = true giveTriadBingo = true
if not user.achievements.triadBingo if not user.achievements.triadBingo
mixpanel?.track("Acquire Item",{'itemName':'Kennel Key','acquireMethod':'Gems','gemCost':6})
user.balance -= 1.5 user.balance -= 1.5
user.items.currentMount = "" user.items.currentMount = ""
user.items.currentPet = "" user.items.currentPet = ""
@@ -842,6 +850,7 @@ api.wrap = (user, main=true) ->
if not user.achievements.ultimateGear and item.last if not user.achievements.ultimateGear and item.last
user.fns.ultimateGear() user.fns.ultimateGear()
user.stats.gp -= item.value user.stats.gp -= item.value
mixpanel?.track("Acquire Item",{'itemName':key,'acquireMethod':'Gold','goldCost':item.value})
cb? {code:200, message}, _.pick(user,$w 'items achievements stats') cb? {code:200, message}, _.pick(user,$w 'items achievements stats')
buyMysterySet: (req, cb)-> buyMysterySet: (req, cb)->
@@ -850,7 +859,9 @@ api.wrap = (user, main=true) ->
if window?.confirm? if window?.confirm?
return unless window.confirm("Buy this full set of items for 1 Mystic Hourglass?") return unless window.confirm("Buy this full set of items for 1 Mystic Hourglass?")
return cb?({code:404, message:"Mystery set not found, or set already owned"}) unless mysterySet return cb?({code:404, message:"Mystery set not found, or set already owned"}) unless mysterySet
_.each mysterySet.items, (i)->user.items.gear.owned[i.key]=true _.each mysterySet.items, (i)->
user.items.gear.owned[i.key]=true
mixpanel?.track("Acquire Item",{'itemName':i.key,'acquireMethod':'Hourglass'})
user.purchased.plan.consecutive.trinkets-- user.purchased.plan.consecutive.trinkets--
cb? null, _.pick(user,$w 'items purchased.plan.consecutive') cb? null, _.pick(user,$w 'items purchased.plan.consecutive')
@@ -922,6 +933,7 @@ api.wrap = (user, main=true) ->
user.balance -= cost user.balance -= cost
if ~path.indexOf('gear.') then user.markModified? 'gear.owned' else user.markModified? 'purchased' if ~path.indexOf('gear.') then user.markModified? 'gear.owned' else user.markModified? 'purchased'
cb? null, _.pick(user,$w 'purchased preferences items') cb? null, _.pick(user,$w 'purchased preferences items')
mixpanel?.track("Acquire Item",{'itemName':'Customizations','acquireMethod':'Gems','gemCost':(cost / .25)})
ga?.event('behavior', 'gems', path).send() ga?.event('behavior', 'gems', path).send()
# ------ # ------
@@ -961,6 +973,7 @@ api.wrap = (user, main=true) ->
user.balance -= .75 user.balance -= .75
_.merge user.stats, {str: 0, con: 0, per: 0, int: 0, points: api.capByLevel(user.stats.lvl)} _.merge user.stats, {str: 0, con: 0, per: 0, int: 0, points: api.capByLevel(user.stats.lvl)}
user.flags.classSelected = false user.flags.classSelected = false
mixpanel?.track("Acquire Item",{'itemName':klass,'acquireMethod':'Gems','gemCost':3})
ga?.event('behavior', 'gems', 'changeClass').send() ga?.event('behavior', 'gems', 'changeClass').send()
#'stats.points': this is handled on the server #'stats.points': this is handled on the server
cb? null, _.pick(user,$w 'stats flags items preferences') cb? null, _.pick(user,$w 'stats flags items preferences')
@@ -1444,6 +1457,7 @@ api.wrap = (user, main=true) ->
user.items.quests[k]++ user.items.quests[k]++
(user.flags.levelDrops ?= {})[k] = true (user.flags.levelDrops ?= {})[k] = true
user.markModified? 'flags.levelDrops' user.markModified? 'flags.levelDrops'
mixpanel?.track("Acquire Item",{'itemName':k,'acquireMethod':'Drop'})
user._tmp.drop = _.defaults content.quests[k], user._tmp.drop = _.defaults content.quests[k],
type: 'Quest' type: 'Quest'
dialog: i18n.t('messageFoundQuest', {questText: content.quests[k].text(req.language)}, req.language) dialog: i18n.t('messageFoundQuest', {questText: content.quests[k].text(req.language)}, req.language)
@@ -1621,6 +1635,7 @@ api.wrap = (user, main=true) ->
# Analytics # Analytics
user.flags.cronCount?=0 user.flags.cronCount?=0
user.flags.cronCount++ user.flags.cronCount++
options.mixpanel.track('Cron',{'distinct_id':user._id,'resting':user.preferences.sleep})
options.ga?.event('behavior', 'cron', 'cron', user.flags.cronCount).send(); #TODO userId for cohort options.ga?.event('behavior', 'cron', 'cron', user.flags.cronCount).send(); #TODO userId for cohort
# After all is said and done, progress up user's effect on quest, return those values & reset the user's # After all is said and done, progress up user's effect on quest, return those values & reset the user's

View File

@@ -21,6 +21,7 @@
"NEW_RELIC_APPLICATION_ID":"NEW_RELIC_APPLICATION_ID", "NEW_RELIC_APPLICATION_ID":"NEW_RELIC_APPLICATION_ID",
"NEW_RELIC_API_KEY":"NEW_RELIC_API_KEY", "NEW_RELIC_API_KEY":"NEW_RELIC_API_KEY",
"GA_ID": "GA_ID", "GA_ID": "GA_ID",
"MP_ID": "MP_ID",
"FLAG_REPORT_EMAIL": "email@mod.com", "FLAG_REPORT_EMAIL": "email@mod.com",
"EMAIL_SERVER": { "EMAIL_SERVER": {
"url": "http://example.com", "url": "http://example.com",

View File

@@ -46,6 +46,16 @@ angular.module('habitrpg')
if($rootScope.selectedLanguage) url = url + '?lang=' + $rootScope.selectedLanguage.code; if($rootScope.selectedLanguage) url = url + '?lang=' + $rootScope.selectedLanguage.code;
$http.post(url, scope.registerVals).success(function(data, status, headers, config) { $http.post(url, scope.registerVals).success(function(data, status, headers, config) {
runAuth(data.id, data.apiToken); runAuth(data.id, data.apiToken);
if (status == 200) {
mixpanel.alias(data._id);
if (data.auth.facebook) {
mixpanel.register({'authType':'facebook','email':data.auth.facebook._json.email})
} else {
mixpanel.register({'authType':'email','email':data.auth.local.email})
}
mixpanel.register({'UUID':data._id,'language':data.preferences.language});
mixpanel.track('Registration');
}
}).error(errorAlert); }).error(errorAlert);
}; };
@@ -57,6 +67,11 @@ angular.module('habitrpg')
$http.post(ApiUrl.get() + "/api/v2/user/auth/local", data) $http.post(ApiUrl.get() + "/api/v2/user/auth/local", data)
.success(function(data, status, headers, config) { .success(function(data, status, headers, config) {
runAuth(data.id, data.token); runAuth(data.id, data.token);
if (status == 200) {
mixpanel.identify(data.id);
mixpanel.register({'UUID':data._id});
mixpanel.track('Login');
}
}).error(errorAlert); }).error(errorAlert);
}; };
@@ -121,13 +136,18 @@ angular.module('habitrpg')
// ------ Social ---------- // ------ Social ----------
hello.init({ hello.init({
facebook : window.env.FACEBOOK_KEY, facebook : window.env.FACEBOOK_KEY
}); });
$scope.socialLogin = function(network){ $scope.socialLogin = function(network){
hello(network).login({scope:'email'}).then(function(auth){ hello(network).login({scope:'email'}).then(function(auth){
$http.post(ApiUrl.get() + "/api/v2/user/auth/social", auth) $http.post(ApiUrl.get() + "/api/v2/user/auth/social", auth)
.success(function(data, status, headers, config) { .success(function(data, status, headers, config) {
if (status == 200) {
mixpanel.identify(data.id);
mixpanel.register({'UUID':data._id});
mixpanel.track('Login');
}
runAuth(data.id, data.token); runAuth(data.id, data.token);
}).error(errorAlert); }).error(errorAlert);
}, function( e ){ }, function( e ){

View File

@@ -320,6 +320,11 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', '
} }
$scope.message.content = ''; $scope.message.content = '';
$scope._sending = false; $scope._sending = false;
if (group.privacy == 'public'){
mixpanel.track('Group Chat',{'groupType':group.type,'privacy':group.privacy,'groupName':group.name,'message':message})
} else {
mixpanel.track('Group Chat',{'groupType':group.type,'privacy':group.privacy})
}
}, function(err){ }, function(err){
$scope._sending = false; $scope._sending = false;
}); });
@@ -431,6 +436,8 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', '
if (confirm(window.env.t('confirmGuild'))) { if (confirm(window.env.t('confirmGuild'))) {
group.$save(function(saved){ group.$save(function(saved){
if (saved.privacy == 'public') {mixpanel.track('Join Group',{'owner':true,'groupType':'guild','privacy':saved.privacy,'groupName':saved.name})}
else {mixpanel.track('Join Group',{'owner':true,'groupType':'guild','privacy':saved.privacy})}
$rootScope.hardRedirect('/#/options/groups/guilds/' + saved._id); $rootScope.hardRedirect('/#/options/groups/guilds/' + saved._id);
}); });
} }
@@ -445,6 +452,8 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', '
} }
group.$join(function(joined){ group.$join(function(joined){
if (joined.privacy == 'public') {mixpanel.track('Join Group',{'owner':false,'groupType':'guild','privacy':joined.privacy,'groupName':joined.name})}
else {mixpanel.track('Join Group',{'owner':false,'groupType':'guild','privacy':joined.privacy})}
$rootScope.hardRedirect('/#/options/groups/guilds/' + joined._id); $rootScope.hardRedirect('/#/options/groups/guilds/' + joined._id);
}) })
} }
@@ -510,6 +519,7 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', '
$scope.create = function(group){ $scope.create = function(group){
group.$save(function(){ group.$save(function(){
mixpanel.track('Join Group',{'owner':true,'groupType':'party','privacy':'private'});
$rootScope.hardRedirect('/#/options/groups/party'); $rootScope.hardRedirect('/#/options/groups/party');
}); });
} }
@@ -517,6 +527,7 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', '
$scope.join = function(party){ $scope.join = function(party){
var group = new Groups.Group({_id: party.id, name: party.name}); var group = new Groups.Group({_id: party.id, name: party.name});
group.$join(function(){ group.$join(function(){
mixpanel.track('Join Group',{'owner':false,'groupType':'party','privacy':'private'});
$rootScope.hardRedirect('/#/options/groups/party'); $rootScope.hardRedirect('/#/options/groups/party');
}); });
} }

View File

@@ -180,6 +180,7 @@ habitrpg.controller("InventoryCtrl",
$rootScope.selectedQuest = undefined; $rootScope.selectedQuest = undefined;
} }
$scope.questInit = function(){ $scope.questInit = function(){
mixpanel.track("Quest",{"owner":true,"response":"accept","questName":$scope.selectedQuest.key});
$rootScope.party.$questAccept({key:$scope.selectedQuest.key}, function(){ $rootScope.party.$questAccept({key:$scope.selectedQuest.key}, function(){
$rootScope.party.$get(); $rootScope.party.$get();
}); });

View File

@@ -87,6 +87,7 @@ habitrpg.controller('NotificationCtrl',
Notification.drop(User.user._tmp.drop.dialog); Notification.drop(User.user._tmp.drop.dialog);
} }
$rootScope.playSound('Item_Drop'); $rootScope.playSound('Item_Drop');
mixpanel.track("Acquire Item",{'itemName':after.key,'acquireMethod':'Drop'})
}); });
$rootScope.$watch('user.achievements.streak', function(after, before){ $rootScope.$watch('user.achievements.streak', function(after, before){

View File

@@ -21,7 +21,9 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N
if (direction === 'down') $rootScope.playSound('Minus_Habit'); if (direction === 'down') $rootScope.playSound('Minus_Habit');
else if (direction === 'up') $rootScope.playSound('Plus_Habit'); else if (direction === 'up') $rootScope.playSound('Plus_Habit');
} }
User.user.ops.score({params:{id: task.id, direction:direction}}) User.user.ops.score({params:{id: task.id, direction:direction}});
mixpanel.register({'Gold':Math.floor(User.user.stats.gp),'Health':Math.ceil(User.user.stats.hp),'Experience':Math.floor(User.user.stats.exp),'Level':User.user.stats.lvl,'Mana':Math.floor(User.user.stats.mp),'Class':User.user.stats.class,'subscription':User.user.purchased.plan.planId,'contributorLevel':User.user.contributor.level,'UUID':User.user._id});
mixpanel.track('Score Task',{'taskType':task.type,'direction':direction});
}; };
function addTask(addTo, listDef, task) { function addTask(addTo, listDef, task) {

View File

@@ -166,11 +166,13 @@ function($rootScope, User, $timeout, $state) {
return $timeout(function(){}); return $timeout(function(){});
} }
window.ga && ga('send', 'event', 'behavior', 'tour', k, i+1); window.ga && ga('send', 'event', 'behavior', 'tour', k, i+1);
mixpanel.track('Tutorial',{'tour':k+'-web','step':i+1,'complete':false});
} }
step.onHide = function(){ step.onHide = function(){
if (step.final) { // -2 indicates complete if (step.final) { // -2 indicates complete
var ups={};ups['flags.tour.'+k] = -2; var ups={};ups['flags.tour.'+k] = -2;
User.set(ups); User.set(ups);
mixpanel.track('Tutorial',{'tour':k+'-web','step':i+1,'complete':true});
} }
} }
}) })

View File

@@ -72,6 +72,7 @@ exports.createSubscription = function(data, cb) {
if (!data.gift) utils.txnEmail(data.user, 'subscription-begins'); if (!data.gift) utils.txnEmail(data.user, 'subscription-begins');
utils.ga.event('commerce', 'subscribe', data.paymentMethod, block.price).send(); utils.ga.event('commerce', 'subscribe', data.paymentMethod, block.price).send();
utils.ga.transaction(data.user._id, block.price).item(block.price, 1, data.paymentMethod.toLowerCase() + '-subscription', data.paymentMethod).send(); utils.ga.transaction(data.user._id, block.price).item(block.price, 1, data.paymentMethod.toLowerCase() + '-subscription', data.paymentMethod).send();
utils.mixpanel.track('purchase',{'distinct_id':data.user._id,'itemPurchased':block.key,'purchaseValue':block.price})
} }
data.user.purchased.txnCount++; data.user.purchased.txnCount++;
if (data.gift){ if (data.gift){
@@ -123,6 +124,7 @@ exports.buyGems = function(data, cb) {
if(isProduction) { if(isProduction) {
if (!data.gift) utils.txnEmail(data.user, 'donation'); if (!data.gift) utils.txnEmail(data.user, 'donation');
utils.ga.event('commerce', 'checkout', data.paymentMethod, amt).send(); utils.ga.event('commerce', 'checkout', data.paymentMethod, amt).send();
utils.mixpanel.track('purchase',{'distinct_id':data.user._id,'itemPurchased':'Gems','purchaseValue':amt})
//TODO ga.transaction to reflect whether this is gift or self-purchase //TODO ga.transaction to reflect whether this is gift or self-purchase
utils.ga.transaction(data.user._id, amt).item(amt, 1, data.paymentMethod.toLowerCase() + "-checkout", "Gems > " + data.paymentMethod).send(); utils.ga.transaction(data.user._id, amt).item(amt, 1, data.paymentMethod.toLowerCase() + "-checkout", "Gems > " + data.paymentMethod).send();
} }

View File

@@ -334,7 +334,7 @@ api.update = function(req, res, next) {
api.cron = function(req, res, next) { api.cron = function(req, res, next) {
var user = res.locals.user, var user = res.locals.user,
progress = user.fns.cron({ga:ga}), progress = user.fns.cron({ga:ga, mixpanel:utils.mixpanel}),
ranCron = user.isModified(), ranCron = user.isModified(),
quest = shared.content.quests[user.party.quest.key]; quest = shared.content.quests[user.party.quest.key];

View File

@@ -199,7 +199,8 @@ module.exports.locals = function(req, res, next) {
mods: require('./models/user').mods, mods: require('./models/user').mods,
tavern: tavern, // for world boss tavern: tavern, // for world boss
worldDmg: (tavern && tavern.quest && tavern.quest.extra && tavern.quest.extra.worldDmg) || {}, worldDmg: (tavern && tavern.quest && tavern.quest.extra && tavern.quest.extra.worldDmg) || {},
_: _ _: _,
MP_ID: nconf.get('MP_ID')
}); });
// Put query-string party (& guild but use partyInvite for backward compatibility) // Put query-string party (& guild but use partyInvite for backward compatibility)

View File

@@ -179,6 +179,8 @@ module.exports.setupConfig = function(){
baseUrl = nconf.get('BASE_URL'); baseUrl = nconf.get('BASE_URL');
module.exports.ga = require('universal-analytics')(nconf.get('GA_ID')); module.exports.ga = require('universal-analytics')(nconf.get('GA_ID'));
var mixpanel = require('mixpanel')
module.exports.mixpanel = mixpanel.init(nconf.get('MP_ID'));
}; };
var algorithm = 'aes-256-ctr'; var algorithm = 'aes-256-ctr';

View File

@@ -21,6 +21,11 @@ html(ng-app="habitrpg", ng-controller="RootCtrl", ng-class='{"applying-action":a
script(type='text/javascript'). script(type='text/javascript').
window.env = !{JSON.stringify(env)}; window.env = !{JSON.stringify(env)};
script(type='text/javascript').
(function(f,b){if(!b.__SV){var a,e,i,g;window.mixpanel=b;b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}var c=b;"undefined"!==typeof d?c=b[d]=[]:d="mixpanel";c.people=c.people||[];c.toString=function(b){var a="mixpanel";"mixpanel"!==d&&(a+="."+d);b||(a+=" (stub)");return a};c.people.toString=function(){return c.toString(1)+".people (stub)"};i="disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.union people.track_charge people.clear_charges people.delete_user".split(" ");
for(g=0;g<i.length;g++)f(c,i[g]);b._i.push([a,e,d])};b.__SV=1.2;a=f.createElement("script");a.type="text/javascript";a.async=!0;a.src="undefined"!==typeof MIXPANEL_CUSTOM_LIB_URL?MIXPANEL_CUSTOM_LIB_URL:"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";e=f.getElementsByTagName("script")[0];e.parentNode.insertBefore(a,e)}})(document,window.mixpanel||[]);
mixpanel.init(window.env.MP_ID);
!= env.getManifestFiles("app") != env.getManifestFiles("app")
//webfonts //webfonts

View File

@@ -3,7 +3,7 @@ html(ng-app='habitrpg', ng-controller='RootCtrl')
head head
meta(charset='utf-8') meta(charset='utf-8')
link(href='http://fonts.googleapis.com/css?family=Lato:400,700', rel='stylesheet', type='text/css') link(href='http://fonts.googleapis.com/css?family=Lato:400,700', rel='stylesheet', type='text/css')
title HabitRPG | Gamify Your Life title HabitRPG | Your Life the Role Playing Game
meta(name='description', content='') meta(name='description', content='')
meta(name='keywords', content='') meta(name='keywords', content='')
meta(name='author', content='') meta(name='author', content='')
@@ -33,6 +33,14 @@ html(ng-app='habitrpg', ng-controller='RootCtrl')
script(type='text/javascript', src='https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.1/ui-bootstrap.min.js') script(type='text/javascript', src='https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.1/ui-bootstrap.min.js')
script(type='text/javascript', src='https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.1/ui-bootstrap-tpls.min.js') script(type='text/javascript', src='https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.1/ui-bootstrap-tpls.min.js')
script(type='text/javascript').
(function (f, b) {if (!b.__SV) {var a, e, i, g;window.mixpanel = b;b._i = [];b.init = function (a, e, d) {function f(b, h) {var a = h.split(".");2 == a.length && (b = b[a[0]], h = a[1]);b[h] = function () {b.push([h].concat(Array.prototype.slice.call(arguments, 0)))}}var c = b;"undefined" !== typeof d ? c = b[d] = [] : d = "mixpanel";c.people = c.people || [];c.toString = function (b) {var a = "mixpanel";"mixpanel" !== d && (a += "." + d);b || (a += " (stub)");return a};c.people.toString = function () {return c.toString(1) + ".people (stub)"};i = "disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.union people.track_charge people.clear_charges people.delete_user".split(" ");
for (g = 0; g < i.length; g++)f(c, i[g]);b._i.push([a, e, d])};b.__SV = 1.2;a = f.createElement("script");a.type = "text/javascript";a.async = !0;a.src = "undefined" !== typeof MIXPANEL_CUSTOM_LIB_URL ? MIXPANEL_CUSTOM_LIB_URL : "//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";e = f.getElementsByTagName("script")[0];e.parentNode.insertBefore(a, e)}})(document, window.mixpanel || []);
mixpanel.init(window.env.MP_ID);
script(type='text/javascript').
mixpanel.track("Landing Page");
body(ng-controller='AuthCtrl') body(ng-controller='AuthCtrl')
include ./login-modal include ./login-modal
include ../shared/header/avatar include ../shared/header/avatar

View File

@@ -27,6 +27,11 @@ html(ng-app='habitrpg')
//FIXME for some reason this won't load when in footerCtrl.js#deferredScripts() //FIXME for some reason this won't load when in footerCtrl.js#deferredScripts()
script(type="text/javascript", src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5016f6cc44ad68a4", async="async") script(type="text/javascript", src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5016f6cc44ad68a4", async="async")
script(type='text/javascript').
(function (f, b) {if (!b.__SV) {var a, e, i, g;window.mixpanel = b;b._i = [];b.init = function (a, e, d) {function f(b, h) {var a = h.split(".");2 == a.length && (b = b[a[0]], h = a[1]);b[h] = function () {b.push([h].concat(Array.prototype.slice.call(arguments, 0)))}}var c = b;"undefined" !== typeof d ? c = b[d] = [] : d = "mixpanel";c.people = c.people || [];c.toString = function (b) {var a = "mixpanel";"mixpanel" !== d && (a += "." + d);b || (a += " (stub)");return a};c.people.toString = function () {return c.toString(1) + ".people (stub)"};i = "disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.union people.track_charge people.clear_charges people.delete_user".split(" ");
for (g = 0; g < i.length; g++)f(c, i[g]);b._i.push([a, e, d])};b.__SV = 1.2;a = f.createElement("script");a.type = "text/javascript";a.async = !0;a.src = "undefined" !== typeof MIXPANEL_CUSTOM_LIB_URL ? MIXPANEL_CUSTOM_LIB_URL : "//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";e = f.getElementsByTagName("script")[0];e.parentNode.insertBefore(a, e)}})(document, window.mixpanel || []);
mixpanel.init(window.env.MP_ID);
!= env.getManifestFiles("static") != env.getManifestFiles("static")
body body