Un'applicazione Electron non è una pagina web anche se è costruita a partire da una, quindi qui non c'è nessun tag script: c'è un pacchetto e una chiamata per processo. Vedi misurare un'app per sapere che cosa ti offre. Il pacchetto Electron di Skomi non dipende da niente se non da Electron stesso.

Il codice sorgente, e un'app di dimostrazione che misura se stessa, stanno su skomi-sdk-electron.

Tre processi, tre righe

// main.js — start it once
const skomi = require('@skomi/electron').init({
    appId: 'your-app-id',
});

skomi.screen('launch');
// preload.js — expose it to the window
require('@skomi/electron/preload');
// renderer — wherever your routing lives
window.skomi.screen('checkout/review', { tier: 'gold' });

L'integrazione è tutta qui. L'identificativo dell'app viene da My Apps dentro Skomi. Non è un segreto e può stare nel tuo codice sorgente: identifica un'app invece di autenticarla, esattamente come fa un identificativo di sito.

⚠ Non rivolgerti allo snippet web nel tuo renderer. Quello misura un sito: vuole un nome host, un documento da guardare e una rete su cui poter contare, e una finestra di Electron non ha niente di tutto ciò nel modo in cui lui se lo aspetta. L'SDK esiste perché i problemi di un'applicazione desktop sono altri.

Dai un nome alle tue schermate

Non c'è nessuna cattura automatica, ed è deliberato: un percorso di rotta è come il tuo codice chiama una schermata, non come la chiameresti in un report. Fino a 20 proprietà per schermata: testo, numeri o booleani.

Che cosa l'SDK gestisce e che altrimenti dovresti scrivere

Funziona senza rete. Le schermate finiscono in coda sul disco, nella cartella dati dell'applicazione stessa, e sopravvivono all'uscita, al crash e a giorni senza rete. Un'applicazione desktop che riportasse soltanto mentre è connessa perderebbe esattamente le sessioni che contano.

Non conta due volte. Ogni schermata porta un identificativo coniato una volta sola e rimandato senza modifiche, quindi un lotto rimandato viene riconosciuto invece che contato di nuovo. Una coda senza quello trasforma la cosa che salva i tuoi dati nella cosa che li inventa.

Sopravvive a un orologio sbagliato. Ogni lotto registra quando è stato inviato, così il server può capire quanto è sfasato l'orologio della macchina e correggere il lotto. Altrimenti un portatile impostato a martedì prossimo riporta martedì prossimo.

Non lancia mai eccezioni nel tuo codice. Argomenti sbagliati, un server irraggiungibile, una cartella di profilo su cui non si può scrivere; tutto gestito internamente e segnalato attraverso onError se vuoi saperlo. L'analitica è la cosa meno importante che la tua applicazione fa.

In attesa del consenso

const skomi = require('@skomi/electron').init({ appId: '…', enabled: false });

// later, once the user has agreed
skomi.setEnabled(true);

Mentre è disabilitato non viene registrato niente, nemmeno messo in coda per dopo. Una schermata vista prima che qualcuno acconsentisse non è una schermata che dovresti mandare dopo.

Errori e crash

skomi.captureError(err, { screenName: 'checkout', fatal: false });

Messi in coda, salvati e rimandati come una schermata, e deduplicati con la stessa regola, che qui conta di più, perché un crash di solito viene mandato dalla coda all'avvio successivo.

⚠ captureUncaught è spento di serie, e pensaci prima di accenderlo. Attaccare un listener a uncaughtException è quello che impedisce a Node di uscire, quindi un sistema di segnalazione dei crash installato di serie trasformerebbe un crash fatale in un processo che continua a girare su uno stato corrotto. Con l'opzione accesa, la semantica viene rimessa a posto: la segnalazione viene scritta su disco in modo sincrono, il listener viene tolto, e l'errore viene rilanciato.

Opzioni

init({
    appId: '…',                     // required
    appVersion: app.getVersion(),   // default: asked of Electron
    origin: 'https://t.skomi.com',  // override for self-hosted
    enabled: true,                  // start false, switch on after consent
    flushIntervalMs: 10000,
    onError(error, context) { },    // 'screen' | 'flush' | 'transport' | 'rejected' | 'queue'
});

init collega il canale del renderer e svuota la coda all'uscita. Se vuoi un client di cui gestisci tu il ciclo di vita (niente IPC, niente aggancio all'uscita), usa invece createClient.

Che cosa un'app non riceve

⚠ Solo Analytics legge un'app. Le mappe di calore, le registrazioni di sessione e il widget di feedback sono prodotti per siti: hanno bisogno di una pagina in un browser, e in una finestra desktop non c'è niente a cui si possano attaccare. Un'app riporta schermate, sessioni, versioni, piattaforme ed errori, e questo è tutto.

Vedi misurare un'app per sapere che cosa ne fa la dashboard, e installare su MAUI o su Flutter se rilasci lo stesso prodotto anche lì.