How to Add Custom Analytics Tracking to Meetily's Rust Backend

Add custom analytics tracking to Meetily by extending the AnalyticsClient with arbitrary event properties via track_event, optionally exposing new events as Tauri commands in commands.rs.

Meetily's Rust backend ships with a privacy-first analytics subsystem designed for minimal overhead and maximum flexibility. This article walks through the architecture of that system—centered on AnalyticsConfig, AnalyticsClient, and Tauri command bindings—and demonstrates how to instrument your own custom events without modifying core infrastructure.

Understanding Meetily's Analytics Architecture

The analytics pipeline consists of three coordinated components:

  • AnalyticsConfig – Stores the API key, optional host URL, and enable flag. Defined at frontend/src-tauri/src/analytics/analytics.rs lines 38-41.
  • AnalyticsClient – The HTTP client that serializes and POSTs events. Provides track_event, identify, start_session, and domain-specific helpers like track_meeting_started at lines 78-150.
  • analytics::commands – Tauri-exposed async functions that bridge Rust analytics to the frontend. Located in frontend/src-tauri/src/analytics/commands.rs.

Initialization Flow

  1. init_analytics reads persisted AnalyticsConfig and instantiates a singleton AnalyticsClient.
  2. start_analytics_session generates a UUID-based session stored in a global Arc<RwLock<Option<UserSession>>>.
  3. Event tracking calls serialize to JSON and POST to the configured host—only if enabled is true.
  4. Frontend invocation happens through Tauri invoke calls, keeping UI code free of networking logic.

This design guarantees opt-in privacy: the enabled flag gates all network traffic, and the HashMap<String, String> properties parameter accepts arbitrary data without client modifications.

Adding a Custom Analytics Event

Step 1: Configure Analytics at Runtime

Initialize the client with your credentials. This pattern appears in analytics.rs lines 456-459:

use meetily::analytics::{AnalyticsConfig, create_analytics_client};

let config = AnalyticsConfig {
    api_key: std::env::var("MEETILY_ANALYTICS_KEY").unwrap_or_default(),
    host: Some("https://analytics.meetily.app".into()),
    enabled: true,
};

let client = create_analytics_client(config).await;

Step 2: Track Events Directly from Rust

Access the global ANALYTICS_CLIENT singleton and call track_event with custom properties. This mirrors the helper pattern at analytics.rs lines 128-135:

use std::collections::HashMap;
use meetily::analytics::ANALYTICS_CLIENT;

pub async fn track_custom_event() -> Result<(), String> {
    let mut props = HashMap::new();
    props.insert("feature".into(), "dark_mode".into());
    props.insert("enabled".into(), "true".into());

    if let Some(client) = ANALYTICS_CLIENT.read().await.clone() {
        client.track_event("feature_toggled", Some(props)).await?;
    }
    Ok(())
}

The track_event signature accepts:

  • event_name: String – The event identifier.
  • properties: Option<HashMap<String, String>> – Arbitrary key-value pairs.

Step 3: Expose as a Tauri Command (Optional)

For frontend access, add a thin wrapper in commands.rs. Follow the existing pattern from track_feature_used at lines 131-138:

// In frontend/src-tauri/src/analytics/commands.rs
#[tauri::command]
pub async fn track_dark_mode_enabled(is_enabled: bool) -> Result<(), String> {
    let mut props = HashMap::new();
    props.insert("enabled".to_string(), is_enabled.to_string());

    analytics::track_event("dark_mode_toggled".into(), Some(props)).await
}

Step 4: Invoke from TypeScript

Call the command from your frontend:

import { invoke } from '@tauri-apps/api/tauri';

await invoke('track_dark_mode_enabled', { isEnabled: true });

Key Files Reference

File Purpose
frontend/src-tauri/src/analytics/mod.rs Module re-exports
frontend/src-tauri/src/analytics/analytics.rs Core AnalyticsClient, AnalyticsConfig, session handling
frontend/src-tauri/src/analytics/commands.rs Tauri command bindings for frontend invocation

Design Principles for Custom Analytics

When adding custom analytics tracking to Meetily's Rust backend, observe these constraints:

  • Check the enabled flag – Always verify ANALYTICS_CLIENT contains a valid client before tracking.
  • Use string properties – The HashMap<String, String> design intentionally avoids serialization complexity; cast non-string types before insertion.
  • Prefer thin wrappers – Domain-specific helpers (like track_meeting_started) improve readability but aren't required—track_event handles all cases.
  • Respect session scope – The global UserSession attaches automatically; don't manually manage session IDs in custom events.

Summary

  • Meetily's analytics subsystem centers on AnalyticsConfig, AnalyticsClient, and Tauri commands in three core files.
  • Custom events use track_event with arbitrary HashMap<String, String> properties—no client modification needed.
  • Frontend integration requires only a thin command wrapper and a TypeScript invoke call.
  • Privacy guarantees are enforced by the enabled flag checked before every network request.

Frequently Asked Questions

How do I disable analytics entirely in a self-hosted deployment?

Set enabled: false in AnalyticsConfig during initialization. No events will queue or transmit. The check happens inside track_event before any HTTP request is constructed.

Can I change the analytics provider without modifying the core client?

Yes. The host field in AnalyticsConfig accepts any HTTPS endpoint. The client POSTs a JSON payload compatible with most analytics providers. For incompatible formats, subclass AnalyticsClient and override the POST logic in analytics.rs.

What happens if track_event is called before initialization?

The ANALYTICS_CLIENT global holds None until init_analytics completes. All track_event calls safely no-op when the client is uninitialized—no panics or errors propagate to the caller.

Are there rate limits or batching for high-frequency events?

The current AnalyticsClient implementation fires one HTTP POST per event with no built-in batching. For high-frequency instrumentation, wrap calls in a local buffer and flush periodically using track_event with aggregated properties.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →