A backend-agnostic analytics/telemetry plugin for Tauri v2 apps. Send events to
any backend that implements the ingest protocol — point the plugin at your
own backend with InitOptions.host.
Add the Rust crate to src-tauri/Cargo.toml:
[dependencies]
tauri-plugin-telemetry = "0.1.1"[dependencies]
tauri-plugin-telemetry = { git = "https://github.com/lispking/tauri-plugin-telemetry" }Install the JavaScript guest bindings with your preferred package manager:
npm add tauri-plugin-telemetrynpm add https://github.com/lispking/tauri-plugin-telemetryRegister the plugin with Tauri:
src-tauri/src/main.rs
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_telemetry::init("APP_KEY"))
.run(tauri::generate_context!())
.expect("error while running tauri application");
}If you need to point the plugin at your own backend, use Builder::with_host:
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_telemetry::Builder::new("APP_KEY")
.with_host("https://analytics.myapp.com")
.build())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}For full control over all options, use with_options:
use tauri_plugin_telemetry::{Builder, InitOptions};
use std::time::Duration;
fn main() {
let opts = InitOptions {
host: Some("https://analytics.myapp.com".into()),
flush_interval: Some(Duration::from_secs(30)),
api_path: Some("/ingest".into()),
..Default::default()
};
tauri::Builder::default()
.plugin(Builder::new("APP_KEY").with_options(opts).build())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}Then add telemetry:allow-track-event to your Access Control List.
Send events from Rust via the EventTracker trait:
use tauri_plugin_telemetry::{init, EventTracker};
fn main() {
tauri::Builder::default()
.plugin(init("APP_KEY"))
.setup(|app| {
app.track_event("app_started", None);
Ok(())
})
.build(tauri::generate_context!())
.expect("error while running tauri application")
.run(|handler, event| match event {
tauri::RunEvent::Exit { .. } => {
handler.track_event("app_exited", None);
handler.flush_events_blocking();
}
_ => {}
})
}The trackEvent function is also available through the JavaScript guest bindings:
import { trackEvent } from "tauri-plugin-telemetry";
trackEvent("save_settings") // An event with no properties
trackEvent("screen_view", { name: "Settings" }) // An event with a custom propertyA few important notes:
- The plugin automatically enriches each event with useful information: OS, app version, locale, and other system properties.
- You're in control of what gets sent. No events are tracked automatically —
call
trackEventmanually (it's recommended to at least track one event at startup). - You don't need to await
trackEvent; it runs in the background. - Only string and number values are allowed in custom properties.
You can load the App Key from a .env file at compile time using the
dotenvy_macro crate. The .env file must be in the src-tauri directory.
use tauri_plugin_telemetry::{Builder, EventTracker, InitOptions};
use dotenvy_macro::dotenv;
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
let opts = InitOptions {
host: Some("https://analytics.myapp.com".into()),
..Default::default()
};
tauri::Builder::default()
.build(tauri::generate_context!())
.plugin(Builder::new(dotenv!("APP_KEY")).with_options(opts).build())
.expect("Error when building tauri app")
.run(|handler, event| match event {
tauri::RunEvent::Exit { .. } => {
handler.track_event("app_exited", None);
handler.flush_events_blocking();
}
tauri::RunEvent::Ready { .. } => {
handler.track_event("app_started", None);
}
_ => {}
});
}For AI/LLM integration instructions, see llms.txt
The plugin can point at any backend that implements its ingest protocol.
For most cases, with_host is enough:
tauri_plugin_telemetry::Builder::new("APP_KEY")
.with_host("https://analytics.myapp.com")
.build()All available options (with their defaults):
use tauri_plugin_telemetry::{Builder, InitOptions};
let opts = InitOptions {
host: Some("https://analytics.myapp.com".into()), // required
api_path: Some("/v1/events".into()), // default: /v1/events
app_key_header: Some("App-Key".into()), // default: App-Key
sdk_name: Some("myapp@1.0.0".into()), // default: <crate>@<version>
flush_interval: Some(Duration::from_secs(60)), // default: 60s release / 2s debug
..Default::default()
};
Builder::new("APP_KEY").with_options(opts).build()Inspired by the Aptabase analytics platform, which is a great option if you don't want to self-host.