How Meetily Implements Its Analytics Module for Usage Tracking
Meetily’s analytics module is implemented as a thin TypeScript client that forwards events to a Rust backend via Tauri commands, using a persistent JSON store for user identification, session management, and detailed usage metrics.
Meetily captures comprehensive usage data through a hybrid analytics architecture that splits processing between a frontend TypeScript client and a native Rust backend. According to the Zackriya-Solutions/meetily source code, this implementation keeps the UI layer lightweight while leveraging Rust’s performance for persistent storage and network operations.
Architecture of the Analytics Module
The analytics implementation follows a command-based architecture where the TypeScript client in frontend/src/lib/analytics.ts acts as a thin wrapper, while the Rust backend in frontend/src-tauri/src/analytics/analytics.rs handles data persistence and external forwarding. This separation allows the frontend to remain portable while the native side manages the analytics.json store and network calls.
TypeScript Client Layer
The Analytics class in frontend/src/lib/analytics.ts provides the public API used by the UI. It manages persistent user IDs, gathers device information from browser user-agent strings, and caches these values to attach to every tracked event. The client never writes directly to disk; instead, it invokes Tauri commands to trigger Rust-side operations.
Rust Backend Layer
The Rust implementation in frontend/src-tauri/src/analytics/analytics.rs exposes Tauri commands including init_analytics, track_event, start_analytics_session, and end_analytics_session. This layer reads and writes to the Tauri plugin-store, enriches events with runtime context, and forwards data to external analytics providers such as Plausible or PostHog.
Initialization and Persistent Storage
Analytics initialization begins when the TypeScript client calls Analytics.init(), which invokes the init_analytics command on the Rust side. This command establishes a persistent store at analytics.json via the Tauri plugin-store mechanism and marks the analytics system as ready for event ingestion.
The persistent store maintains counters and flags across application restarts, including total meeting counts, daily tallies, feature-use flags, and copy-count statistics. Helper methods such as updateMeetingCount, getMeetingsCountToday, and markFeatureUsed perform read-modify-write operations against these JSON entries through Rust command invocations.
User Identification and Device Fingerprinting
The module generates persistent user IDs that survive application restarts by storing them in the plugin-store. When Analytics.getPersistentUserId() is called, the client either retrieves an existing ID from the store or generates a new one, caching it in the class instance for the duration of the session.
Device identification relies on the browser’s user-agent string to extract platform, OS version, and CPU architecture details. These values are gathered during initialization and automatically attached to every event payload, enabling granular segmentation of usage data by hardware and operating system.
Event Tracking and Dispatch
All tracking flows through the generic track(eventName, properties?) method, which invokes the track_event Tauri command with the event name and a map of custom properties. Higher-level helper methods build richer payloads before calling this core function:
trackMeetingStarted– Logs meeting initiation with session IDstrackMeetingCompleted– Records duration, transcript segments, word counts, and words-per-minute metricstrackFeatureUsedEnhanced– Captures feature interactions with automatic platform data attachmenttrackSummaryGenerationStarted– Tracks AI processing pipeline steps
The Rust backend receives these commands, enriches them with additional runtime context, and forwards them to the configured analytics endpoint.
Session Management and Metrics
The analytics module maintains explicit session boundaries through start_analytics_session and end_analytics_session commands. The TypeScript client records timestamps, calculates session duration, and logs the number of meetings processed within that specific session window.
Persistent metrics stored in analytics.json include daily meeting counters and feature usage flags. These values enable the application to display usage statistics and enforce any potential limits without requiring network connectivity or external API calls.
Practical Implementation Examples
Initialize analytics when the application starts and identify the user:
// Initialise analytics when the app starts
await Analytics.init();
// Identify the user (once per session)
const userId = await Analytics.getPersistentUserId();
await Analytics.identify(userId);
Track meeting lifecycle events with detailed metrics:
// Track a meeting start
await Analytics.trackMeetingStarted('meeting‑123');
// When the meeting finishes, report metrics
await Analytics.trackMeetingCompleted('meeting‑123', {
duration_seconds: 342,
transcript_segments: 57,
transcript_word_count: 8420,
words_per_minute: 147.5,
meetings_today: await Analytics.getMeetingsCountToday()
});
Track feature usage with automatic platform data attachment:
// Track a feature use with platform data automatically attached
await Analytics.trackFeatureUsedEnhanced('transcript‑export', {
export_format: 'txt',
file_size_kb: 124
});
Summary
- Hybrid Architecture: The TypeScript client in
frontend/src/lib/analytics.tsforwards events to Rust commands infrontend/src-tauri/src/analytics/analytics.rs, separating UI logic from persistent storage and network operations. - Persistent Store: The Tauri plugin-store maintains
analytics.jsonfor user IDs, daily counters, and feature flags that survive application restarts. - Automatic Enrichment: Every event automatically includes device platform, OS version, and CPU architecture derived from the user-agent string.
- Session Tracking: Explicit
start_analytics_sessionandend_analytics_sessioncommands calculate duration and meeting counts per session. - Rich Event Payloads: Helper methods like
trackMeetingCompletedandtrackFeatureUsedEnhancedbuild detailed property maps including transcript metrics and export formats.
Frequently Asked Questions
How does Meetily store analytics data locally?
Meetily stores analytics data in a JSON file named analytics.json using Tauri’s plugin-store API. The Rust backend in frontend/src-tauri/src/analytics/analytics.rs handles all read and write operations, while the TypeScript client requests changes via Tauri commands. This approach ensures data persists across application restarts while keeping the frontend code agnostic to the underlying storage mechanism.
What types of events can the analytics module track?
The module tracks meetings lifecycle events (started, completed), feature usage interactions (exports, settings changes), transcription outcomes, backend connection status, summary generation steps, and UI interactions including page views and button clicks. Each event accepts a custom properties map allowing arbitrary metadata attachment.
How is user identity maintained across sessions?
The Analytics class generates a persistent user ID during first launch and stores it via the Tauri plugin-store. Subsequent sessions retrieve this ID from analytics.json through the getPersistentUserId() method, ensuring consistent user tracking without requiring login credentials or external identity providers.
Can the analytics module work offline?
Yes, the module maintains persistent counters and session data locally in analytics.json through the Tauri plugin-store. While event forwarding to external analytics providers requires network connectivity, local metrics aggregation, session tracking, and meeting counts function entirely offline, with data storage handled by the Rust backend.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →