PrithviGuardian / client /src /lib /userTracking.ts
Varad Bakshi
Fresh upload
e7427b5
Raw
History Blame Contribute Delete
6.75 kB
// User Analytics and Tracking System for प्रिथ्वी Guardian AI
interface UserSession {
sessionId: string;
startTime: Date;
endTime?: Date;
pageViews: string[];
actionsPerformed: string[];
modulesUsed: string[];
calculationsCount: number;
reportsGenerated: number;
timeSpent: number; // in minutes
}
interface UserAnalytics {
totalSessions: number;
totalUsers: number;
averageSessionTime: number;
mostUsedModules: Record<string, number>;
dailyActiveUsers: Record<string, number>;
featureUsage: Record<string, number>;
retentionRate: number;
}
class UserTrackingSystem {
private currentSession: UserSession | null = null;
private sessionKey = 'prithvi_user_session';
private analyticsKey = 'prithvi_analytics';
private userIdKey = 'prithvi_user_id';
constructor() {
this.initializeTracking();
}
private initializeTracking() {
// Generate unique user ID if not exists
if (!localStorage.getItem(this.userIdKey)) {
const userId = 'user_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
localStorage.setItem(this.userIdKey, userId);
}
// Start new session
this.startSession();
// Track page visibility changes
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
this.pauseSession();
} else {
this.resumeSession();
}
});
// Track before page unload
window.addEventListener('beforeunload', () => {
this.endSession();
});
}
startSession() {
const sessionId = 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
this.currentSession = {
sessionId,
startTime: new Date(),
pageViews: [window.location.pathname],
actionsPerformed: [],
modulesUsed: [],
calculationsCount: 0,
reportsGenerated: 0,
timeSpent: 0
};
localStorage.setItem(this.sessionKey, JSON.stringify(this.currentSession));
this.updateAnalytics('sessionStart');
}
trackPageView(path: string) {
if (!this.currentSession) return;
this.currentSession.pageViews.push(path);
this.updateSession();
this.updateAnalytics('pageView', { path });
}
trackAction(action: string, details?: any) {
if (!this.currentSession) return;
const actionLog = {
action,
timestamp: new Date(),
details
};
this.currentSession.actionsPerformed.push(JSON.stringify(actionLog));
this.updateSession();
this.updateAnalytics('action', { action });
}
trackModuleUsage(module: string) {
if (!this.currentSession) return;
if (!this.currentSession.modulesUsed.includes(module)) {
this.currentSession.modulesUsed.push(module);
}
this.updateSession();
this.updateAnalytics('moduleUsage', { module });
}
trackCalculation(module: string, type: string) {
if (!this.currentSession) return;
this.currentSession.calculationsCount++;
this.trackAction('calculation', { module, type });
this.trackModuleUsage(module);
this.updateSession();
}
trackReportGeneration(title: string) {
if (!this.currentSession) return;
this.currentSession.reportsGenerated++;
this.trackAction('reportGenerated', { title });
this.updateSession();
}
private updateSession() {
if (!this.currentSession) return;
const now = new Date();
this.currentSession.timeSpent = Math.round((now.getTime() - this.currentSession.startTime.getTime()) / 60000);
localStorage.setItem(this.sessionKey, JSON.stringify(this.currentSession));
}
private pauseSession() {
this.updateSession();
}
private resumeSession() {
// Session continues, just update time
this.updateSession();
}
endSession() {
if (!this.currentSession) return;
this.currentSession.endTime = new Date();
this.updateSession();
// Save to permanent storage
this.saveSessionToHistory();
this.updateAnalytics('sessionEnd');
this.currentSession = null;
localStorage.removeItem(this.sessionKey);
}
private saveSessionToHistory() {
if (!this.currentSession) return;
const historyKey = 'prithvi_session_history';
const history = JSON.parse(localStorage.getItem(historyKey) || '[]');
history.push(this.currentSession);
// Keep only last 100 sessions
if (history.length > 100) {
history.splice(0, history.length - 100);
}
localStorage.setItem(historyKey, JSON.stringify(history));
}
private updateAnalytics(eventType: string, data?: any) {
const analytics = this.getAnalytics();
const today = new Date().toISOString().split('T')[0];
switch (eventType) {
case 'sessionStart':
analytics.totalSessions++;
analytics.dailyActiveUsers[today] = (analytics.dailyActiveUsers[today] || 0) + 1;
break;
case 'moduleUsage':
analytics.mostUsedModules[data.module] = (analytics.mostUsedModules[data.module] || 0) + 1;
break;
case 'action':
analytics.featureUsage[data.action] = (analytics.featureUsage[data.action] || 0) + 1;
break;
}
localStorage.setItem(this.analyticsKey, JSON.stringify(analytics));
}
getAnalytics(): UserAnalytics {
const defaultAnalytics: UserAnalytics = {
totalSessions: 0,
totalUsers: 1,
averageSessionTime: 0,
mostUsedModules: {},
dailyActiveUsers: {},
featureUsage: {},
retentionRate: 100
};
const stored = localStorage.getItem(this.analyticsKey);
return stored ? { ...defaultAnalytics, ...JSON.parse(stored) } : defaultAnalytics;
}
getCurrentSession(): UserSession | null {
return this.currentSession;
}
getSessionHistory(): UserSession[] {
const historyKey = 'prithvi_session_history';
return JSON.parse(localStorage.getItem(historyKey) || '[]');
}
getUserId(): string {
return localStorage.getItem(this.userIdKey) || 'anonymous';
}
exportAnalyticsData(): string {
const data = {
userId: this.getUserId(),
analytics: this.getAnalytics(),
sessionHistory: this.getSessionHistory(),
currentSession: this.currentSession,
exportDate: new Date().toISOString()
};
return JSON.stringify(data, null, 2);
}
clearAnalyticsData() {
localStorage.removeItem(this.analyticsKey);
localStorage.removeItem('prithvi_session_history');
localStorage.removeItem(this.sessionKey);
// Don't clear user ID to maintain identity
}
}
// Create global instance
export const userTracking = new UserTrackingSystem();
// Export for use in components
export { UserTrackingSystem };
export type { UserSession, UserAnalytics };