mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 14:47:53 +01:00
Analytics: track challenge and task events (#9885)
* feat(analytics): track challenge and task events * feat(analytics): add more challenge events Also tweaks data for better troubleshooting utility * refactor(analytics): include IDs for challenges/groups * refactor(analytics): term for award challenge is "close"
This commit is contained in:
@@ -257,6 +257,16 @@ api.createChallenge = {
|
|||||||
privacy: group.privacy,
|
privacy: group.privacy,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
res.analytics.track('challenge create', {
|
||||||
|
uuid: user._id,
|
||||||
|
hitType: 'event',
|
||||||
|
category: 'behavior',
|
||||||
|
challengeID: response._id,
|
||||||
|
groupID: group._id,
|
||||||
|
groupName: group.privacy === 'private' ? null : group.name,
|
||||||
|
groupType: group._id === TAVERN_ID ? 'tavern' : group.type,
|
||||||
|
});
|
||||||
|
|
||||||
res.respond(201, response);
|
res.respond(201, response);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -315,6 +325,16 @@ api.joinChallenge = {
|
|||||||
let chalLeader = await User.findById(response.leader).select(nameFields).exec();
|
let chalLeader = await User.findById(response.leader).select(nameFields).exec();
|
||||||
response.leader = chalLeader ? chalLeader.toJSON({minimize: true}) : null;
|
response.leader = chalLeader ? chalLeader.toJSON({minimize: true}) : null;
|
||||||
|
|
||||||
|
res.analytics.track('challenge join', {
|
||||||
|
uuid: user._id,
|
||||||
|
hitType: 'event',
|
||||||
|
category: 'behavior',
|
||||||
|
challengeID: challenge._id,
|
||||||
|
groupID: group._id,
|
||||||
|
groupName: group.privacy === 'private' ? null : group.name,
|
||||||
|
groupType: group._id === TAVERN_ID ? 'tavern' : group.type,
|
||||||
|
});
|
||||||
|
|
||||||
res.respond(200, response);
|
res.respond(200, response);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -351,6 +371,17 @@ api.leaveChallenge = {
|
|||||||
|
|
||||||
// Unlink challenge's tasks from user's tasks and save the challenge
|
// Unlink challenge's tasks from user's tasks and save the challenge
|
||||||
await Bluebird.all([challenge.unlinkTasks(user, keep), challenge.save()]);
|
await Bluebird.all([challenge.unlinkTasks(user, keep), challenge.save()]);
|
||||||
|
|
||||||
|
res.analytics.track('challenge leave', {
|
||||||
|
uuid: user._id,
|
||||||
|
hitType: 'event',
|
||||||
|
category: 'behavior',
|
||||||
|
challengeID: challenge._id,
|
||||||
|
groupID: challenge.group._id,
|
||||||
|
groupName: challenge.group.privacy === 'private' ? null : challenge.group.name,
|
||||||
|
groupType: challenge.group._id === TAVERN_ID ? 'tavern' : challenge.group.type,
|
||||||
|
});
|
||||||
|
|
||||||
res.respond(200, {});
|
res.respond(200, {});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -679,6 +710,17 @@ api.deleteChallenge = {
|
|||||||
|
|
||||||
// Close channel in background, some ops are run in the background without `await`ing
|
// Close channel in background, some ops are run in the background without `await`ing
|
||||||
await challenge.closeChal({broken: 'CHALLENGE_DELETED'});
|
await challenge.closeChal({broken: 'CHALLENGE_DELETED'});
|
||||||
|
|
||||||
|
res.analytics.track('challenge delete', {
|
||||||
|
uuid: user._id,
|
||||||
|
hitType: 'event',
|
||||||
|
category: 'behavior',
|
||||||
|
challengeID: challenge._id,
|
||||||
|
groupID: challenge.group._id,
|
||||||
|
groupName: challenge.group.privacy === 'private' ? null : challenge.group.name,
|
||||||
|
groupType: challenge.group._id === TAVERN_ID ? 'tavern' : challenge.group.type,
|
||||||
|
});
|
||||||
|
|
||||||
res.respond(200, {});
|
res.respond(200, {});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -717,6 +759,18 @@ api.selectChallengeWinner = {
|
|||||||
|
|
||||||
// Close channel in background, some ops are run in the background without `await`ing
|
// Close channel in background, some ops are run in the background without `await`ing
|
||||||
await challenge.closeChal({broken: 'CHALLENGE_CLOSED', winner});
|
await challenge.closeChal({broken: 'CHALLENGE_CLOSED', winner});
|
||||||
|
|
||||||
|
res.analytics.track('challenge close', {
|
||||||
|
uuid: user._id,
|
||||||
|
hitType: 'event',
|
||||||
|
category: 'behavior',
|
||||||
|
challengeID: challenge._id,
|
||||||
|
challengeWinnerID: winner._id,
|
||||||
|
groupID: challenge.group._id,
|
||||||
|
groupName: challenge.group.privacy === 'private' ? null : challenge.group.name,
|
||||||
|
groupType: challenge.group._id === TAVERN_ID ? 'tavern' : challenge.group.type,
|
||||||
|
});
|
||||||
|
|
||||||
res.respond(200, {});
|
res.respond(200, {});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import common from '../../../common';
|
|||||||
import Bluebird from 'bluebird';
|
import Bluebird from 'bluebird';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import logger from '../../libs/logger';
|
import logger from '../../libs/logger';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
const MAX_SCORE_NOTES_LENGTH = 256;
|
const MAX_SCORE_NOTES_LENGTH = 256;
|
||||||
|
|
||||||
@@ -166,6 +167,16 @@ api.createUserTasks = {
|
|||||||
res.respond(201, tasks.length === 1 ? tasks[0] : tasks);
|
res.respond(201, tasks.length === 1 ? tasks[0] : tasks);
|
||||||
|
|
||||||
tasks.forEach((task) => {
|
tasks.forEach((task) => {
|
||||||
|
// Track when new users (first 7 days) create tasks
|
||||||
|
if (moment().diff(user.auth.timestamps.created, 'days') < 7) {
|
||||||
|
res.analytics.track('task create', {
|
||||||
|
uuid: user._id,
|
||||||
|
hitType: 'event',
|
||||||
|
category: 'behavior',
|
||||||
|
taskType: task.type,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
taskActivityWebhook.send(user.webhooks, {
|
taskActivityWebhook.send(user.webhooks, {
|
||||||
type: 'created',
|
type: 'created',
|
||||||
task,
|
task,
|
||||||
@@ -241,6 +252,16 @@ api.createChallengeTasks = {
|
|||||||
|
|
||||||
// If adding tasks to a challenge -> sync users
|
// If adding tasks to a challenge -> sync users
|
||||||
if (challenge) challenge.addTasks(tasks);
|
if (challenge) challenge.addTasks(tasks);
|
||||||
|
|
||||||
|
tasks.forEach((task) => {
|
||||||
|
res.analytics.track('task create', {
|
||||||
|
uuid: user._id,
|
||||||
|
hitType: 'event',
|
||||||
|
category: 'behavior',
|
||||||
|
taskType: task.type,
|
||||||
|
challengeID: challenge._id,
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -654,16 +675,16 @@ api.scoreTask = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Track when new users (first 7 days) score tasks
|
||||||
* TODO: enable score task analytics if desired
|
if (moment().diff(user.auth.timestamps.created, 'days') < 7) {
|
||||||
res.analytics.track('score task', {
|
res.analytics.track('task score', {
|
||||||
uuid: user._id,
|
uuid: user._id,
|
||||||
hitType: 'event',
|
hitType: 'event',
|
||||||
category: 'behavior',
|
category: 'behavior',
|
||||||
taskType: task.type,
|
taskType: task.type,
|
||||||
direction
|
direction,
|
||||||
});
|
});
|
||||||
*/
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,16 @@ api.createGroupTasks = {
|
|||||||
let tasks = await createTasks(req, res, {user, group});
|
let tasks = await createTasks(req, res, {user, group});
|
||||||
|
|
||||||
res.respond(201, tasks.length === 1 ? tasks[0] : tasks);
|
res.respond(201, tasks.length === 1 ? tasks[0] : tasks);
|
||||||
|
|
||||||
|
tasks.forEach((task) => {
|
||||||
|
res.analytics.track('task create', {
|
||||||
|
uuid: user._id,
|
||||||
|
hitType: 'event',
|
||||||
|
category: 'behavior',
|
||||||
|
taskType: task.type,
|
||||||
|
groupID: group._id,
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user