mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 19:01:08 +02:00
feat(analytics): add Analytics Maturity metric to ManaScore and custom event tracking to 4 apps
Add new "Analytics Maturity" extended metric to ManaScore schema with 5 checks: pageViewTracking, customEvents, authTracking, landingTracking, publicDashboard. Populate analytics data across all 20 audit files. Document the metric in about.md. Add app-specific Umami custom event helpers and integrate tracking into: - ManaCore: 13 events (nav, onboarding, dashboard widgets, credits, settings) - Presi: 12 events (deck/slide CRUD, presentation start/exit, sharing) - Zitare: 9 events (quotes, favorites, categories, search, lists, language) - Mukke: 12 events (upload, library, playlists, projects, editor export) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f0233b8d31
commit
d2264f5360
46 changed files with 314 additions and 4 deletions
|
|
@ -2,6 +2,7 @@
|
|||
import { onMount } from 'svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { decksStore } from '$lib/stores/decks.svelte';
|
||||
import { PresiEvents } from '@manacore/shared-utils/analytics';
|
||||
import { PageHeader, ContextMenu, type ContextMenuItem } from '@manacore/shared-ui';
|
||||
import {
|
||||
Plus,
|
||||
|
|
@ -74,6 +75,7 @@
|
|||
});
|
||||
|
||||
if (deck) {
|
||||
PresiEvents.deckCreated();
|
||||
showCreateModal = false;
|
||||
newDeckTitle = '';
|
||||
newDeckDescription = '';
|
||||
|
|
@ -90,6 +92,7 @@
|
|||
async function handleDelete() {
|
||||
if (!deckToDelete) return;
|
||||
await decksStore.deleteDeck(deckToDelete.id);
|
||||
PresiEvents.deckDeleted();
|
||||
showDeleteModal = false;
|
||||
deckToDelete = null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
import { goto } from '$app/navigation';
|
||||
import { browser } from '$app/environment';
|
||||
import { decksStore } from '$lib/stores/decks.svelte';
|
||||
import { PresiEvents } from '@manacore/shared-utils/analytics';
|
||||
import { shareApi } from '$lib/api/client';
|
||||
import type { ShareLink } from '$lib/api/client';
|
||||
import type { Slide, SlideContent } from '@presi/shared';
|
||||
|
|
@ -93,8 +94,10 @@
|
|||
|
||||
if (editingSlide) {
|
||||
await decksStore.updateSlide(editingSlide.id, { content });
|
||||
PresiEvents.slideEdited();
|
||||
} else {
|
||||
await decksStore.createSlide(deckId, { content });
|
||||
PresiEvents.slideCreated();
|
||||
}
|
||||
|
||||
isSaving = false;
|
||||
|
|
@ -109,6 +112,7 @@
|
|||
async function handleDeleteSlide() {
|
||||
if (!slideToDelete) return;
|
||||
await decksStore.deleteSlide(slideToDelete.id);
|
||||
PresiEvents.slideDeleted();
|
||||
showDeleteModal = false;
|
||||
slideToDelete = null;
|
||||
}
|
||||
|
|
@ -135,6 +139,7 @@
|
|||
// Update order values
|
||||
newSlides.forEach((s, i) => (s.order = i + 1));
|
||||
await decksStore.reorderSlides(newSlides);
|
||||
PresiEvents.slideReordered(direction);
|
||||
}
|
||||
|
||||
function addBulletPoint() {
|
||||
|
|
@ -170,6 +175,7 @@
|
|||
try {
|
||||
const newShare = await shareApi.createShare(deckId);
|
||||
shareLinks = [newShare, ...shareLinks];
|
||||
PresiEvents.shareLinkCreated();
|
||||
} catch (e) {
|
||||
console.error('Failed to create share link:', e);
|
||||
} finally {
|
||||
|
|
@ -181,6 +187,7 @@
|
|||
try {
|
||||
await shareApi.deleteShare(shareId);
|
||||
shareLinks = shareLinks.filter((s) => s.id !== shareId);
|
||||
PresiEvents.shareLinkDeleted();
|
||||
} catch (e) {
|
||||
console.error('Failed to delete share link:', e);
|
||||
}
|
||||
|
|
@ -195,6 +202,7 @@
|
|||
const url = getShareUrl(share.shareCode);
|
||||
try {
|
||||
await navigator.clipboard.writeText(url);
|
||||
PresiEvents.shareLinkCopied();
|
||||
copiedLinkId = share.id;
|
||||
setTimeout(() => {
|
||||
copiedLinkId = null;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import { page } from '$app/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
import { decksStore } from '$lib/stores/decks.svelte';
|
||||
import { PresiEvents } from '@manacore/shared-utils/analytics';
|
||||
import type { Slide } from '@presi/shared';
|
||||
import {
|
||||
X,
|
||||
|
|
@ -28,8 +29,12 @@
|
|||
|
||||
const deckId = $page.params.id as string;
|
||||
|
||||
let maxSlideReached = $state(0);
|
||||
|
||||
onMount(() => {
|
||||
decksStore.loadDeck(deckId);
|
||||
decksStore.loadDeck(deckId).then(() => {
|
||||
PresiEvents.presentationStarted(decksStore.currentSlides.length);
|
||||
});
|
||||
|
||||
// Keyboard navigation
|
||||
window.addEventListener('keydown', handleKeydown);
|
||||
|
|
@ -92,6 +97,7 @@
|
|||
function nextSlide() {
|
||||
if (currentSlideIndex < decksStore.currentSlides.length - 1) {
|
||||
currentSlideIndex++;
|
||||
if (currentSlideIndex > maxSlideReached) maxSlideReached = currentSlideIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -126,6 +132,7 @@
|
|||
}
|
||||
|
||||
function exitPresentation() {
|
||||
PresiEvents.presentationExited(elapsedSeconds, maxSlideReached + 1);
|
||||
if (document.fullscreenElement) {
|
||||
document.exitFullscreen();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import { onMount, onDestroy } from 'svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { shareApi } from '$lib/api/client';
|
||||
import { PresiEvents } from '@manacore/shared-utils/analytics';
|
||||
import type { Slide } from '@presi/shared';
|
||||
import {
|
||||
CaretLeft,
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
const data = await shareApi.getByCode(shareCode);
|
||||
deck = data;
|
||||
slides = data.slides || [];
|
||||
PresiEvents.sharedDeckViewed();
|
||||
} catch (e) {
|
||||
error = e instanceof Error ? e.message : 'Failed to load shared deck';
|
||||
} finally {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue