mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 07:07:35 +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
|
* @param item
|
||||||
* @returns {String}
|
* @returns {String}
|
||||||
*/
|
*/
|
||||||
getIemKey (item) {
|
getItemKey (item) {
|
||||||
return item.key;
|
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`
|
* Shortcut to get the translated string without passing `req.language`
|
||||||
* @param {String} key - translation key
|
* @param {String} key - translation key
|
||||||
@@ -141,8 +153,8 @@ export class AbstractGoldItemOperation extends AbstractBuyOperation {
|
|||||||
|
|
||||||
analyticsData () {
|
analyticsData () {
|
||||||
return {
|
return {
|
||||||
itemKey: this.getIemKey(this.item),
|
itemKey: this.getItemKey(this.item),
|
||||||
itemType: 'Market',
|
itemType: this.getItemType(this.item),
|
||||||
acquireMethod: 'Gold',
|
acquireMethod: 'Gold',
|
||||||
goldCost: this.getItemValue(this.item),
|
goldCost: this.getItemValue(this.item),
|
||||||
};
|
};
|
||||||
@@ -175,8 +187,8 @@ export class AbstractGemItemOperation extends AbstractBuyOperation {
|
|||||||
|
|
||||||
analyticsData () {
|
analyticsData () {
|
||||||
return {
|
return {
|
||||||
itemKey: this.getIemKey(this.item),
|
itemKey: this.getItemKey(this.item),
|
||||||
itemType: 'Market',
|
itemType: this.getItemType(this.item),
|
||||||
acquireMethod: 'Gems',
|
acquireMethod: 'Gems',
|
||||||
gemCost: this.getItemValue(this.item) * 4,
|
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;
|
return planGemLimits.convRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
getIemKey () {
|
getItemKey () {
|
||||||
return 'gem';
|
return 'gem';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getItemType () {
|
||||||
|
return 'gems';
|
||||||
|
}
|
||||||
|
|
||||||
extractAndValidateParams (user, req) {
|
extractAndValidateParams (user, req) {
|
||||||
let key = this.key = get(req, 'params.key');
|
let key = this.key = get(req, 'params.key');
|
||||||
if (!key) throw new BadRequest(this.i18n('missingKeyParam'));
|
if (!key) throw new BadRequest(this.i18n('missingKeyParam'));
|
||||||
@@ -72,10 +76,4 @@ export class BuyGemOperation extends AbstractGoldItemOperation {
|
|||||||
analyticsLabel () {
|
analyticsLabel () {
|
||||||
return 'purchase gems';
|
return 'purchase gems';
|
||||||
}
|
}
|
||||||
|
|
||||||
analyticsData () {
|
|
||||||
let data = super.analyticsData();
|
|
||||||
data.itemKey = 'gem';
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,10 +46,4 @@ export class BuyHealthPotionOperation extends AbstractGoldItemOperation {
|
|||||||
message,
|
message,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
analyticsData () {
|
|
||||||
let data = super.analyticsData();
|
|
||||||
data.itemKey = 'Potion';
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ export class BuyQuestWithGoldOperation extends AbstractGoldItemOperation {
|
|||||||
return item.goldValue;
|
return item.goldValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getItemType () {
|
||||||
|
return 'quest';
|
||||||
|
}
|
||||||
|
|
||||||
extractAndValidateParams (user, req) {
|
extractAndValidateParams (user, req) {
|
||||||
let key = this.key = get(req, 'params.key');
|
let key = this.key = get(req, 'params.key');
|
||||||
if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
|
if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ export class BuyQuestWithGemOperation extends AbstractGemItemOperation {
|
|||||||
return item.value / 4;
|
return item.value / 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getItemType () {
|
||||||
|
return 'quest';
|
||||||
|
}
|
||||||
|
|
||||||
extractAndValidateParams (user, req) {
|
extractAndValidateParams (user, req) {
|
||||||
let key = this.key = get(req, 'params.key');
|
let key = this.key = get(req, 'params.key');
|
||||||
if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
|
if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ export class BuySpellOperation extends AbstractGoldItemOperation {
|
|||||||
return this.key;
|
return this.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getItemType () {
|
||||||
|
return 'spell';
|
||||||
|
}
|
||||||
|
|
||||||
multiplePurchaseAllowed () {
|
multiplePurchaseAllowed () {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ module.exports = function purchase (user, req = {}, analytics) {
|
|||||||
analytics.track('acquire item', {
|
analytics.track('acquire item', {
|
||||||
uuid: user._id,
|
uuid: user._id,
|
||||||
itemKey: key,
|
itemKey: key,
|
||||||
itemType: 'Market',
|
itemType: type,
|
||||||
acquireMethod: 'Gems',
|
acquireMethod: 'Gems',
|
||||||
gemCost: price * 4,
|
gemCost: price * 4,
|
||||||
quantityPurchased: quantity,
|
quantityPurchased: quantity,
|
||||||
|
|||||||
@@ -1213,6 +1213,16 @@ api.inviteToGroup = {
|
|||||||
results.push(...emailResults);
|
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);
|
res.respond(200, results);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ api.createUserTasks = {
|
|||||||
hitType: 'event',
|
hitType: 'event',
|
||||||
category: 'behavior',
|
category: 'behavior',
|
||||||
taskType: task.type,
|
taskType: task.type,
|
||||||
|
headers: req.headers,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -702,6 +703,7 @@ api.scoreTask = {
|
|||||||
category: 'behavior',
|
category: 'behavior',
|
||||||
taskType: task.type,
|
taskType: task.type,
|
||||||
direction,
|
direction,
|
||||||
|
headers: req.headers,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -186,6 +186,16 @@ function trackCronAnalytics (analytics, user, _progress, options) {
|
|||||||
headers: options.headers,
|
headers: options.headers,
|
||||||
loginIncentives: user.loginIncentives,
|
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) {
|
function awardLoginIncentives (user) {
|
||||||
|
|||||||
Reference in New Issue
Block a user