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

> Learn how to add custom analytics tracking to Meetily's Rust backend. Extend AnalyticsClient with track_event to add arbitrary event properties and expose new events via Tauri commands.

- Repository: [Zackriya Solutions/meetily](https://github.com/Zackriya-Solutions/meetily)
- Tags: how-to-guide
- Published: 2026-08-04

---

**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`](https://github.com/Zackriya-Solutions/meetily/blob/main/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`](https://github.com/Zackriya-Solutions/meetily/blob/main/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`](https://github.com/Zackriya-Solutions/meetily/blob/main/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`](https://github.com/Zackriya-Solutions/meetily/blob/main/analytics.rs) lines 456-459:

```rust
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`](https://github.com/Zackriya-Solutions/meetily/blob/main/analytics.rs) lines 128-135:

```rust
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`](https://github.com/Zackriya-Solutions/meetily/blob/main/commands.rs). Follow the existing pattern from `track_feature_used` at lines 131-138:

```rust
// 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:

```typescript
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`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/analytics/mod.rs) | Module re-exports |
| [`frontend/src-tauri/src/analytics/analytics.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/analytics/analytics.rs) | Core `AnalyticsClient`, `AnalyticsConfig`, session handling |
| [`frontend/src-tauri/src/analytics/commands.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/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`](https://github.com/Zackriya-Solutions/meetily/blob/main/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.