feat(analytics): initial Habitica-owned solution

This commit is contained in:
Phillip Thelen
2026-04-07 15:33:57 -05:00
committed by Kalista Payne
parent 746fcfff49
commit e6ffd69148
90 changed files with 762 additions and 2479 deletions
@@ -198,7 +198,6 @@ import dailyIcon from '@/assets/svg/daily.svg?raw';
import todoIcon from '@/assets/svg/todo.svg?raw';
import rewardIcon from '@/assets/svg/reward.svg?raw';
import * as Analytics from '@/libs/analytics';
import { mapState } from '@/libs/store';
export default {
@@ -438,14 +437,6 @@ export default {
return false;
},
changeMirrorPreference (newVal) {
Analytics.track({
eventName: 'mirror tasks',
eventAction: 'mirror tasks',
eventCategory: 'behavior',
hitType: 'event',
mirror: newVal,
group: this.group._id,
}, { trackOnClient: true });
const groupsToMirror = this.user.preferences.tasks.mirrorGroupTasks || [];
if (newVal) { // we're turning copy ON for this group
groupsToMirror.push(this.group._id);
@@ -240,7 +240,6 @@
<script>
import { mapState } from '@/libs/store';
import * as Analytics from '@/libs/analytics';
import notifications from '@/mixins/notifications';
import closeX from '../ui/closeX';
@@ -276,11 +275,6 @@ export default {
this.$store.state.party.data = party;
this.user.party._id = party._id;
Analytics.updateUser({
partyID: party._id,
partySize: 1,
});
this.$root.$emit('bv::hide::modal', 'create-party-modal');
await this.$router.push('/party');
},
@@ -314,7 +314,6 @@ import extend from 'lodash/extend';
import groupUtilities from '@/mixins/groupsUtilities';
import styleHelper from '@/mixins/styleHelper';
import { mapGetters } from '@/libs/store';
import * as Analytics from '@/libs/analytics';
import participantListModal from './participantListModal';
import groupFormModal from './groupFormModal';
import groupGemsModal from '@/components/groups/groupGemsModal';
@@ -560,7 +559,6 @@ export default {
if (this.isParty) {
data.type = 'party';
Analytics.updateUser({ partySize: null, partyID: null });
this.$store.state.partyMembers = [];
}
@@ -334,7 +334,6 @@ import orderBy from 'lodash/orderBy';
import * as quests from '@/../../common/script/content/quests';
import getItemInfo from '@/../../common/script/libs/getItemInfo';
import { mapState } from '@/libs/store';
import * as Analytics from '@/libs/analytics';
import navigationBack from '@/assets/svg/navigation_back.svg?raw';
import questDialogContent from '../shops/quests/questDialogContent';
@@ -421,11 +420,6 @@ export default {
async questInit () {
this.loading = true;
Analytics.updateUser({
partyID: this.group._id,
partySize: this.group.memberCount,
});
const groupId = this.group._id || this.user.party._id;
const key = this.selectedQuest;
@@ -123,7 +123,6 @@
<script>
import orderBy from 'lodash/orderBy';
import * as Analytics from '@/libs/analytics';
import { mapGetters, mapActions } from '@/libs/store';
import MemberDetails from '../memberDetails';
import createPartyModal from '../groups/createPartyModal';
@@ -236,22 +235,8 @@ export default {
},
async createOrInviteParty () {
if (this.user.party._id) {
await Analytics.track({
eventName: 'Header Party CTA',
eventAction: 'Header Party CTA',
eventCategory: 'behavior',
hitType: 'event',
state: 'Find Party Members',
});
this.$router.push('/looking-for-party');
} else {
await Analytics.track({
eventName: 'Header Party CTA',
eventAction: 'Header Party CTA',
eventCategory: 'behavior',
hitType: 'event',
state: 'Get Started',
});
this.$root.$emit('bv::show::modal', 'create-party-modal');
}
},
@@ -114,7 +114,6 @@ import { mapState } from '@/libs/store';
import notifications from '@/mixins/notifications';
import guide from '@/mixins/guide';
import { CONSTANTS, setLocalSetting } from '@/libs/userlocalManager';
import * as Analytics from '@/libs/analytics';
import yesterdailyModal from './tasks/yesterdailyModal';
import newStuff from './news/modal';
@@ -648,15 +647,6 @@ export default {
// Reset daily analytics actions
setLocalSetting(CONSTANTS.keyConstants.TASKS_SCORED_COUNT, 0);
setLocalSetting(CONSTANTS.keyConstants.TASKS_CREATED_COUNT, 0);
} else {
// Note a failed cron event, for our records and investigation
Analytics.track({
eventName: 'cron failed',
eventAction: 'cron failed',
eventCategory: 'behavior',
hitType: 'event',
responseCode: response.status,
}, { trackOnClient: true });
}
// Sync
@@ -433,9 +433,6 @@ import lockableLabel from '@/components/tasks/modal-controls/lockableLabel';
import notificationsMixin from '@/mixins/notifications';
import paymentsMixin from '@/mixins/payments';
// analytics
import * as Analytics from '@/libs/analytics';
export default {
components: {
selectTranslatedArray,
@@ -536,16 +533,6 @@ export default {
this.close();
},
submit () {
if (this.paymentData.group && !this.paymentData.newGroup) {
Analytics.track({
hitType: 'event',
eventName: 'group plan upgrade',
eventAction: 'group plan upgrade',
eventCategory: 'behavior',
demographics: this.upgradedGroup.demographics,
type: this.paymentData.group.type,
}, { trackOnClient: true });
}
this.paymentData = {};
this.$root.$emit('bv::hide::modal', 'payments-success-modal');
},
-11
View File
@@ -6,7 +6,6 @@ import { mapState } from '@/libs/store';
import encodeParams from '@/libs/encodeParams';
import notificationsMixin from '@/mixins/notifications';
import { CONSTANTS, setLocalSetting } from '@/libs/userlocalManager';
import * as Analytics from '@/libs/analytics';
const { STRIPE_PUB_KEY } = import.meta.env;
@@ -207,16 +206,6 @@ export default {
alert(`Error while redirecting to Stripe: ${checkoutSessionResult.error.message}`);
throw checkoutSessionResult.error;
}
if (paymentType === 'groupPlan') {
Analytics.track({
hitType: 'event',
eventName: 'group plan create',
eventAction: 'group plan create',
eventCategory: 'behavior',
demographics: appState.newGroup.demographics,
type: appState.newGroup.type,
}, { trackOnClient: true });
}
} catch (err) {
console.error('Error while redirecting to Stripe', err); // eslint-disable-line
alert(`Error while redirecting to Stripe: ${err.message}`);
-10
View File
@@ -3,7 +3,6 @@ import Vue from 'vue';
import scoreTask from '@/../../common/script/ops/scoreTask';
import notifications from './notifications';
import { mapState } from '@/libs/store';
import * as Analytics from '@/libs/analytics';
import { CONSTANTS, getLocalSetting, setLocalSetting } from '@/libs/userlocalManager';
export default {
@@ -58,15 +57,6 @@ export default {
const tasksScoredCount = getLocalSetting(CONSTANTS.keyConstants.TASKS_SCORED_COUNT);
if (!tasksScoredCount || tasksScoredCount < 2) {
Analytics.track({
eventName: 'task scored',
eventAction: 'task scored',
eventCategory: 'behavior',
hitType: 'event',
uuid: user._id,
taskType: task.type,
direction,
}, { trackOnClient: true });
if (!tasksScoredCount) {
setLocalSetting(CONSTANTS.keyConstants.TASKS_SCORED_COUNT, 1);
} else {
-2
View File
@@ -130,7 +130,6 @@ import PrivacyBanner from '@/components/header/banners/privacy';
import AppFooter from '@/components/appFooter';
import notificationsDisplay from '@/components/notifications';
import { mapState } from '@/libs/store';
import * as Analytics from '@/libs/analytics';
import BuyModal from '@/components/shops/buyModal.vue';
import SelectMembersModal from '@/components/selectMembersModal.vue';
import notifications from '@/mixins/notifications';
@@ -276,7 +275,6 @@ export default {
}
}
Analytics.updateUser();
return this.loadAllTranslations();
}).then(() => {
this.$store.state.isUserLoaded = true;
-10
View File
@@ -1,6 +1,5 @@
import Vue from 'vue';
import VueRouter from 'vue-router';
import * as Analytics from '@/libs/analytics';
import getStore from '@/store';
import handleRedirect from './handleRedirect';
@@ -318,15 +317,6 @@ router.beforeEach(async (to, from, next) => {
router.app.$root.$emit('update-party');
}
if (to.name === 'lookingForParty') {
Analytics.track({
hitType: 'event',
eventName: 'View Find Members',
eventAction: 'View Find Members',
eventCategory: 'behavior',
}, { trackOnClient: true });
}
// Redirect old guild urls
if (to.hash.indexOf('#/options/groups/guilds/') !== -1) {
const splits = to.hash.split('/');
-8
View File
@@ -1,6 +1,5 @@
import axios from 'axios';
import Vue from 'vue';
import * as Analytics from '@/libs/analytics';
export async function getChat (store, payload) {
const response = await axios.get(`/api/v4/groups/${payload.groupId}/chat?limit=400`);
@@ -17,13 +16,6 @@ export async function postChat (store, payload) {
url += `?previousMsg=${payload.previousMsg}`;
}
if (group.type === 'party') {
Analytics.updateUser({
partyID: group.id,
partySize: group.memberCount,
});
}
const response = await axios.post(url, {
message: payload.message,
});
@@ -1,7 +1,6 @@
import axios from 'axios';
import omit from 'lodash/omit';
import findIndex from 'lodash/findIndex';
import * as Analytics from '@/libs/analytics';
import { loadAsyncResource } from '@/libs/asyncResource';
export async function getPublicGuilds (store, payload) {
@@ -74,7 +73,6 @@ export async function join (store, payload) {
if (invitationI !== -1) invitations.parties.splice(invitationI, 1);
user.party._id = groupId;
Analytics.updateUser({ partyID: groupId });
// load the party members so that they get shown in the header
store.dispatch('party:getMembers');
}
@@ -18,7 +18,6 @@ import * as shops from './shops';
import * as snackbars from './snackbars';
import * as worldState from './worldState';
import * as news from './news';
import * as analytics from './analytics';
import * as faq from './faq';
import * as blockers from './blockers';
@@ -44,7 +43,6 @@ const actions = flattenAndNamespace({
snackbars,
worldState,
news,
analytics,
faq,
blockers,
});
@@ -1,26 +1,6 @@
import axios from 'axios';
import * as Analytics from '@/libs/analytics';
// export async function initQuest (store) {
// }
export async function sendAction (store, payload) { // eslint-disable-line import/prefer-default-export, max-len
// @TODO: Maybe move this to server
let partyData = {};
if (store.state.party && store.state.party.data) {
partyData = {
partyID: store.state.party.data._id,
partySize: store.state.party.data.memberCount,
};
} else {
partyData = {
partyID: store.state.user.data.party._id,
partySize: store.state.partyMembers.data.length,
};
}
Analytics.updateUser(partyData);
const response = await axios.post(`/api/v4/groups/${payload.groupId}/${payload.action}`);
// @TODO: Update user?
-10
View File
@@ -3,7 +3,6 @@ import Vue from 'vue';
import compact from 'lodash/compact';
import omit from 'lodash/omit';
import { loadAsyncResource } from '@/libs/asyncResource';
import * as Analytics from '@/libs/analytics';
import { CONSTANTS, getLocalSetting, setLocalSetting } from '@/libs/userlocalManager';
export function fetchUserTasks (store, options = {}) {
@@ -112,15 +111,6 @@ export async function create (store, createdTask) {
}
const tasksCreatedCount = getLocalSetting(CONSTANTS.keyConstants.TASKS_CREATED_COUNT);
if (!tasksCreatedCount || tasksCreatedCount < 2) {
const uuid = store.state.user.data._id;
Analytics.track({
eventName: 'task created',
eventAction: 'task created',
eventCategory: 'behavior',
hitType: 'event',
uuid,
taskType: taskRes.type,
}, { trackOnClient: true });
if (!tasksCreatedCount) {
setLocalSetting(CONSTANTS.keyConstants.TASKS_CREATED_COUNT, 1);
} else {