mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 22:57:21 +01:00
Analytics: More / improved tracking (#10608)
* WIP(analytics): add / improve tracking * fix(groups): revert attempt at tracking on group model * fix(analytics): track questing based on user data * each buy-operation now has a getItemType method - typo getItemKey - removed unneeded overrides
This commit is contained in:
@@ -38,10 +38,22 @@ export class AbstractBuyOperation {
|
||||
* @param item
|
||||
* @returns {String}
|
||||
*/
|
||||
getIemKey (item) {
|
||||
getItemKey (item) {
|
||||
return item.key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the item type
|
||||
* @param item
|
||||
* @returns {String}
|
||||
*/
|
||||
getItemType (item) {
|
||||
if (!item.type)
|
||||
throw new NotImplementedError('item doesn\'t have a type property');
|
||||
|
||||
return item.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut to get the translated string without passing `req.language`
|
||||
* @param {String} key - translation key
|
||||
@@ -141,8 +153,8 @@ export class AbstractGoldItemOperation extends AbstractBuyOperation {
|
||||
|
||||
analyticsData () {
|
||||
return {
|
||||
itemKey: this.getIemKey(this.item),
|
||||
itemType: 'Market',
|
||||
itemKey: this.getItemKey(this.item),
|
||||
itemType: this.getItemType(this.item),
|
||||
acquireMethod: 'Gold',
|
||||
goldCost: this.getItemValue(this.item),
|
||||
};
|
||||
@@ -175,8 +187,8 @@ export class AbstractGemItemOperation extends AbstractBuyOperation {
|
||||
|
||||
analyticsData () {
|
||||
return {
|
||||
itemKey: this.getIemKey(this.item),
|
||||
itemType: 'Market',
|
||||
itemKey: this.getItemKey(this.item),
|
||||
itemType: this.getItemType(this.item),
|
||||
acquireMethod: 'Gems',
|
||||
gemCost: this.getItemValue(this.item) * 4,
|
||||
};
|
||||
|
||||
@@ -135,10 +135,4 @@ export class BuyArmoireOperation extends AbstractGoldItemOperation {
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
analyticsData () {
|
||||
let data = super.analyticsData();
|
||||
data.itemKey = 'Armoire';
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,14 @@ export class BuyGemOperation extends AbstractGoldItemOperation {
|
||||
return planGemLimits.convRate;
|
||||
}
|
||||
|
||||
getIemKey () {
|
||||
getItemKey () {
|
||||
return 'gem';
|
||||
}
|
||||
|
||||
getItemType () {
|
||||
return 'gems';
|
||||
}
|
||||
|
||||
extractAndValidateParams (user, req) {
|
||||
let key = this.key = get(req, 'params.key');
|
||||
if (!key) throw new BadRequest(this.i18n('missingKeyParam'));
|
||||
@@ -72,10 +76,4 @@ export class BuyGemOperation extends AbstractGoldItemOperation {
|
||||
analyticsLabel () {
|
||||
return 'purchase gems';
|
||||
}
|
||||
|
||||
analyticsData () {
|
||||
let data = super.analyticsData();
|
||||
data.itemKey = 'gem';
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,10 +46,4 @@ export class BuyHealthPotionOperation extends AbstractGoldItemOperation {
|
||||
message,
|
||||
];
|
||||
}
|
||||
|
||||
analyticsData () {
|
||||
let data = super.analyticsData();
|
||||
data.itemKey = 'Potion';
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,10 @@ export class BuyQuestWithGoldOperation extends AbstractGoldItemOperation {
|
||||
return item.goldValue;
|
||||
}
|
||||
|
||||
getItemType () {
|
||||
return 'quest';
|
||||
}
|
||||
|
||||
extractAndValidateParams (user, req) {
|
||||
let key = this.key = get(req, 'params.key');
|
||||
if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
|
||||
|
||||
@@ -26,6 +26,10 @@ export class BuyQuestWithGemOperation extends AbstractGemItemOperation {
|
||||
return item.value / 4;
|
||||
}
|
||||
|
||||
getItemType () {
|
||||
return 'quest';
|
||||
}
|
||||
|
||||
extractAndValidateParams (user, req) {
|
||||
let key = this.key = get(req, 'params.key');
|
||||
if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
|
||||
|
||||
@@ -18,6 +18,10 @@ export class BuySpellOperation extends AbstractGoldItemOperation {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
getItemType () {
|
||||
return 'spell';
|
||||
}
|
||||
|
||||
multiplePurchaseAllowed () {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ module.exports = function purchase (user, req = {}, analytics) {
|
||||
analytics.track('acquire item', {
|
||||
uuid: user._id,
|
||||
itemKey: key,
|
||||
itemType: 'Market',
|
||||
itemType: type,
|
||||
acquireMethod: 'Gems',
|
||||
gemCost: price * 4,
|
||||
quantityPurchased: quantity,
|
||||
|
||||
@@ -1213,6 +1213,16 @@ api.inviteToGroup = {
|
||||
results.push(...emailResults);
|
||||
}
|
||||
|
||||
let analyticsObject = {
|
||||
uuid: user._id,
|
||||
hitType: 'event',
|
||||
category: 'behavior',
|
||||
groupType: group.type,
|
||||
headers: req.headers,
|
||||
};
|
||||
|
||||
res.analytics.track('group invite', analyticsObject);
|
||||
|
||||
res.respond(200, results);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -175,6 +175,7 @@ api.createUserTasks = {
|
||||
hitType: 'event',
|
||||
category: 'behavior',
|
||||
taskType: task.type,
|
||||
headers: req.headers,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -702,6 +703,7 @@ api.scoreTask = {
|
||||
category: 'behavior',
|
||||
taskType: task.type,
|
||||
direction,
|
||||
headers: req.headers,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -186,6 +186,16 @@ function trackCronAnalytics (analytics, user, _progress, options) {
|
||||
headers: options.headers,
|
||||
loginIncentives: user.loginIncentives,
|
||||
});
|
||||
|
||||
if (user.party && user.party.quest && !user.party.quest.RSVPNeeded && !user.party.quest.completed && user.party.quest.key && !user.preferences.sleep) {
|
||||
analytics.track('quest participation', {
|
||||
category: 'behavior',
|
||||
uuid: user._id,
|
||||
user,
|
||||
questName: user.party.quest.key,
|
||||
headers: options.headers,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function awardLoginIncentives (user) {
|
||||
|
||||
Reference in New Issue
Block a user