mirror of
https://github.com/olehomelchenko/astrolabe-nvc.git
synced 2025-12-21 21:22:23 +00:00
feat: integrate GoatCounter analytics for event tracking across modals and snippets
This commit is contained in:
@@ -534,6 +534,11 @@
|
||||
<script src="src/js/panel-manager.js"></script>
|
||||
<script src="src/js/editor.js"></script>
|
||||
<script src="src/js/app.js"></script>
|
||||
|
||||
<!-- GoatCounter Analytics -->
|
||||
<script data-goatcounter="https://astrolabe.goatcounter.com/count"
|
||||
data-goatcounter-settings='{"allow_local": true}'
|
||||
async src="//gc.zgo.at/count.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -468,6 +468,8 @@ function openHelpModal() {
|
||||
const modal = document.getElementById('help-modal');
|
||||
if (modal) {
|
||||
modal.style.display = 'flex';
|
||||
// Track event
|
||||
Analytics.track('modal-help', 'Open Help modal');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,6 +485,8 @@ function openDonateModal() {
|
||||
const modal = document.getElementById('donate-modal');
|
||||
if (modal) {
|
||||
modal.style.display = 'flex';
|
||||
// Track event
|
||||
Analytics.track('modal-donate', 'Open Donate modal');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -210,6 +210,20 @@ const Toast = {
|
||||
}
|
||||
};
|
||||
|
||||
// Analytics utility: Track events with GoatCounter
|
||||
const Analytics = {
|
||||
track(eventName, title) {
|
||||
// Only track if GoatCounter is loaded
|
||||
if (window.goatcounter && window.goatcounter.count) {
|
||||
window.goatcounter.count({
|
||||
path: eventName,
|
||||
title: title || eventName,
|
||||
event: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Shared utility: Format bytes for display
|
||||
function formatBytes(bytes) {
|
||||
if (bytes === null || bytes === undefined) return 'N/A';
|
||||
|
||||
@@ -785,6 +785,9 @@ function openDatasetManager(updateURL = true) {
|
||||
if (updateURL) {
|
||||
URLState.update({ view: 'datasets', snippetId: null, datasetId: null });
|
||||
}
|
||||
|
||||
// Track event
|
||||
Analytics.track('modal-datasets', 'Open Dataset Manager');
|
||||
}
|
||||
|
||||
// Close dataset manager modal
|
||||
@@ -1139,6 +1142,9 @@ async function saveNewDataset() {
|
||||
|
||||
hideNewDatasetForm();
|
||||
await renderDatasetList();
|
||||
|
||||
// Track event
|
||||
Analytics.track('dataset-create', `Create dataset (${source})`);
|
||||
} catch (error) {
|
||||
errorEl.textContent = `Failed to save dataset: ${error.message}`;
|
||||
}
|
||||
@@ -1167,6 +1173,9 @@ async function deleteCurrentDataset() {
|
||||
|
||||
// Show success message
|
||||
Toast.success('Dataset deleted');
|
||||
|
||||
// Track event
|
||||
Analytics.track('dataset-delete', 'Delete dataset');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1295,6 +1304,9 @@ async function exportCurrentDataset() {
|
||||
// Show success message
|
||||
Toast.success(`Dataset "${dataset.name}" exported successfully`);
|
||||
|
||||
// Track event
|
||||
Analytics.track('dataset-export', `Export dataset (${dataset.format})`);
|
||||
|
||||
} catch (error) {
|
||||
Toast.error(`Failed to export dataset: ${error.message}`);
|
||||
}
|
||||
@@ -1394,6 +1406,9 @@ async function importDatasetFromFile(fileInput) {
|
||||
Toast.success(`Dataset "${datasetName}" imported successfully!`);
|
||||
}
|
||||
|
||||
// Track event
|
||||
Analytics.track('dataset-import', `Import dataset (${format})`);
|
||||
|
||||
} catch (error) {
|
||||
Toast.error(`Failed to import dataset: ${error.message}`);
|
||||
} finally {
|
||||
|
||||
@@ -835,6 +835,9 @@ function createNewSnippet() {
|
||||
renderSnippetList();
|
||||
selectSnippet(newSnippet.id);
|
||||
|
||||
// Track event
|
||||
Analytics.track('snippet-create', 'Create new snippet');
|
||||
|
||||
return newSnippet;
|
||||
}
|
||||
|
||||
@@ -859,6 +862,9 @@ function duplicateSnippet(snippetId) {
|
||||
// Show success message
|
||||
Toast.success('Snippet duplicated successfully');
|
||||
|
||||
// Track event
|
||||
Analytics.track('snippet-duplicate', 'Duplicate snippet');
|
||||
|
||||
return newSnippet;
|
||||
}
|
||||
|
||||
@@ -881,6 +887,9 @@ function createSnippetFromDataset(datasetName) {
|
||||
renderSnippetList();
|
||||
selectSnippet(newSnippet.id);
|
||||
|
||||
// Track event
|
||||
Analytics.track('snippet-from-dataset', 'Create snippet from dataset');
|
||||
|
||||
return newSnippet;
|
||||
}
|
||||
|
||||
@@ -992,6 +1001,9 @@ async function extractToDataset() {
|
||||
|
||||
// Show success message
|
||||
Toast.success(`Dataset "${datasetName}" created successfully!`);
|
||||
|
||||
// Track event
|
||||
Analytics.track('dataset-extract', 'Extract inline data to dataset');
|
||||
} catch (error) {
|
||||
errorEl.textContent = `Failed to create dataset: ${error.message}`;
|
||||
}
|
||||
@@ -1032,6 +1044,9 @@ function deleteSnippet(snippetId) {
|
||||
// Show success message
|
||||
Toast.success('Snippet deleted');
|
||||
|
||||
// Track event
|
||||
Analytics.track('snippet-delete', 'Delete snippet');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1121,6 +1136,9 @@ function publishDraft() {
|
||||
|
||||
// Show success message
|
||||
Toast.success('Snippet published successfully!');
|
||||
|
||||
// Track event
|
||||
Analytics.track('snippet-publish', 'Publish draft');
|
||||
}
|
||||
|
||||
// Revert draft to published spec
|
||||
@@ -1146,6 +1164,9 @@ function revertDraft() {
|
||||
|
||||
// Show success message
|
||||
Toast.success('Draft reverted to published version');
|
||||
|
||||
// Track event
|
||||
Analytics.track('snippet-revert', 'Revert draft');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1212,6 +1233,9 @@ function exportSnippets() {
|
||||
|
||||
// Show success message
|
||||
Toast.success(`Exported ${snippets.length} snippet${snippets.length !== 1 ? 's' : ''}`);
|
||||
|
||||
// Track event
|
||||
Analytics.track('snippets-export', `Export ${snippets.length} snippets`);
|
||||
}
|
||||
|
||||
// Normalize external snippet format to Astrolabe format
|
||||
@@ -1296,6 +1320,9 @@ function importSnippets(fileInput) {
|
||||
if (SnippetStorage.saveSnippets(existingSnippets)) {
|
||||
Toast.success(`Successfully imported ${importedCount} snippet${importedCount !== 1 ? 's' : ''}`);
|
||||
renderSnippetList();
|
||||
|
||||
// Track event
|
||||
Analytics.track('snippets-import', `Import ${importedCount} snippets`);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user