mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 20:41:09 +02:00
feat(analytics): add automatic auth event tracking via shared-auth
Add inline Umami tracking to @manacore/shared-auth authService for login, signup, logout, SSO, and social auth events. Tracks both success and failure with auth method metadata. This automatically covers all web apps without any per-app code changes. No-ops silently in environments without Umami (mobile, SSR). Tracked events: login, login_failed, signup, signup_failed, logout, password_reset_requested (with method: email/google/apple/sso) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2c26fce736
commit
f043db2b05
2 changed files with 44 additions and 2 deletions
|
|
@ -67,6 +67,23 @@ injectUmamiAnalytics(html) → <script defer src="stats.mana.how/script.js" d
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Automatisches Auth-Tracking
|
||||||
|
|
||||||
|
Auth-Events werden automatisch in `@manacore/shared-auth` getrackt (alle Web-Apps):
|
||||||
|
|
||||||
|
| Event | Wann | Data |
|
||||||
|
|-------|------|------|
|
||||||
|
| `login` | Erfolgreicher Login | `{ method: 'email' \| 'google' \| 'apple' \| 'sso' }` |
|
||||||
|
| `login_failed` | Login fehlgeschlagen | `{ method: 'email' \| 'google' \| 'apple' }` |
|
||||||
|
| `signup` | Erfolgreiche Registrierung | `{ method: 'email' }` |
|
||||||
|
| `signup_failed` | Registrierung fehlgeschlagen | `{ method: 'email' }` |
|
||||||
|
| `logout` | Benutzer hat sich abgemeldet | - |
|
||||||
|
| `password_reset_requested` | Passwort-Reset angefragt | - |
|
||||||
|
|
||||||
|
Diese Events erfordern **keinen Code in den einzelnen Apps** — sie werden automatisch vom shared Auth-Service ausgelöst.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Custom Event Tracking
|
## Custom Event Tracking
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,20 @@ import {
|
||||||
getAppSettings as getAppSettingsFromToken,
|
getAppSettings as getAppSettingsFromToken,
|
||||||
} from './jwtUtils';
|
} from './jwtUtils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inline analytics helper - tracks auth events via Umami if available.
|
||||||
|
* No-ops silently in environments without Umami (mobile, SSR, dev).
|
||||||
|
*/
|
||||||
|
function trackAuth(event: string, data?: Record<string, string | number | boolean>): void {
|
||||||
|
if (typeof window !== 'undefined' && (window as any).umami?.track) {
|
||||||
|
try {
|
||||||
|
(window as any).umami.track(event, data);
|
||||||
|
} catch {
|
||||||
|
// Silently ignore tracking errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default storage keys
|
* Default storage keys
|
||||||
*/
|
*/
|
||||||
|
|
@ -108,9 +122,11 @@ export function createAuthService(config: AuthServiceConfig) {
|
||||||
// SSO cookie is nice-to-have, don't fail login if this fails
|
// SSO cookie is nice-to-have, don't fail login if this fails
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trackAuth('login', { method: 'email' });
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error signing in:', error);
|
console.error('Error signing in:', error);
|
||||||
|
trackAuth('login_failed', { method: 'email' });
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: error instanceof Error ? error.message : 'Unknown error during sign in',
|
error: error instanceof Error ? error.message : 'Unknown error during sign in',
|
||||||
|
|
@ -154,9 +170,11 @@ export function createAuthService(config: AuthServiceConfig) {
|
||||||
|
|
||||||
// Mana Core Auth returns user data immediately on registration
|
// Mana Core Auth returns user data immediately on registration
|
||||||
// User needs to sign in separately to get tokens
|
// User needs to sign in separately to get tokens
|
||||||
|
trackAuth('signup', { method: 'email' });
|
||||||
return { success: true, needsVerification: false };
|
return { success: true, needsVerification: false };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error signing up:', error);
|
console.error('Error signing up:', error);
|
||||||
|
trackAuth('signup_failed', { method: 'email' });
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: error instanceof Error ? error.message : 'Unknown error during sign up',
|
error: error instanceof Error ? error.message : 'Unknown error during sign up',
|
||||||
|
|
@ -180,6 +198,7 @@ export function createAuthService(config: AuthServiceConfig) {
|
||||||
}).catch((err) => console.error('Error logging out on server:', err));
|
}).catch((err) => console.error('Error logging out on server:', err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trackAuth('logout');
|
||||||
await service.clearAuthStorage();
|
await service.clearAuthStorage();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error signing out:', error);
|
console.error('Error signing out:', error);
|
||||||
|
|
@ -209,6 +228,7 @@ export function createAuthService(config: AuthServiceConfig) {
|
||||||
return { success: false, error: errorData.message || 'Password reset failed' };
|
return { success: false, error: errorData.message || 'Password reset failed' };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trackAuth('password_reset_requested');
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error sending password reset email:', error);
|
console.error('Error sending password reset email:', error);
|
||||||
|
|
@ -344,14 +364,18 @@ export function createAuthService(config: AuthServiceConfig) {
|
||||||
* Sign in with Google
|
* Sign in with Google
|
||||||
*/
|
*/
|
||||||
async signInWithGoogle(idToken: string): Promise<AuthResult> {
|
async signInWithGoogle(idToken: string): Promise<AuthResult> {
|
||||||
return service.signInWithSocial(idToken, endpoints.googleSignIn);
|
const result = await service.signInWithSocial(idToken, endpoints.googleSignIn);
|
||||||
|
trackAuth(result.success ? 'login' : 'login_failed', { method: 'google' });
|
||||||
|
return result;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sign in with Apple
|
* Sign in with Apple
|
||||||
*/
|
*/
|
||||||
async signInWithApple(identityToken: string): Promise<AuthResult> {
|
async signInWithApple(identityToken: string): Promise<AuthResult> {
|
||||||
return service.signInWithSocial(identityToken, endpoints.appleSignIn);
|
const result = await service.signInWithSocial(identityToken, endpoints.appleSignIn);
|
||||||
|
trackAuth(result.success ? 'login' : 'login_failed', { method: 'apple' });
|
||||||
|
return result;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -693,6 +717,7 @@ export function createAuthService(config: AuthServiceConfig) {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
console.log('SSO: Successfully authenticated via session cookie');
|
console.log('SSO: Successfully authenticated via session cookie');
|
||||||
|
trackAuth('login', { method: 'sso' });
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// SSO failed - this is expected if user hasn't logged in anywhere
|
// SSO failed - this is expected if user hasn't logged in anywhere
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue