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 che cosa ti dà. Il pacchetto Electron di Skomi non dipende da niente se non da Electron stesso.

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

Tre processi, tre righe

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

skomi.screen('launch');
// preload.js — esponilo alla finestra
require('@skomi/electron/preload');
// renderer — dovunque viva il tuo instradamento
window.skomi.screen('checkout/review', { tier: 'gold' });

L'integrazione è tutta qui. L'identificativo dell'app viene da Le mie app dentro Skomi. Non è un segreto e appartiene al 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 quindici giorni senza rete. Un'applicazione desktop che riportasse soltanto mentre è connessa perderebbe esattamente le sessioni che contano.

Non conta a doppio. 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 svuotato, così il server può capire quanto è fuori squadra l'orologio della macchina e correggere il lotto. Altrimenti un portatile impostato a martedì prossimo riporta martedì prossimo.

Non lancia mai dentro il 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 });

// più avanti, dopo che la persona ha acconsentito
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 ascoltatore 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, l'ascoltatore viene tolto, e l'errore viene rilanciato.

Opzioni

init({
    appId: '…',                     // obbligatorio
    appVersion: app.getVersion(),   // di serie: chiesta a Electron
    origin: 'https://t.skomi.com',  // da sovrascrivere se ospiti tu
    enabled: true,                  // parti da false, accendi dopo il consenso
    flushIntervalMs: 10000,
    onError(error, context) { },    // 'screen' | 'flush' | 'transport' | 'rejected' | 'queue'
});

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

Che cosa un'app non riceve

Solo l'analitica 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 che cosa la dashboard ci fa, e installare su MAUI o su Flutter se rilasci lo stesso prodotto anche lì.