Add analytics link to page headers, event tracking to calculator, update deploy script
- Add analytics.html to STATIC_FILES in deploy.sh - Add trackEvent/getVisitorId to script.js with page_view, show_results, copy_email hooks - Add "Analytics →" nav link to index.html and market.html headers Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6bedd5c074
commit
8843af6402
4 changed files with 40 additions and 3 deletions
|
|
@ -13,7 +13,7 @@ ENV_FILE="${REPO_DIR}/server/.env"
|
|||
COMPOSE_FILE="${REPO_DIR}/docker-compose.yml"
|
||||
|
||||
# Static files to deploy to Apache web root
|
||||
STATIC_FILES=(index.html auth.js script.js config.json market.html market-script.js)
|
||||
STATIC_FILES=(index.html auth.js script.js config.json market.html market-script.js analytics.html)
|
||||
|
||||
# ── Colours ───────────────────────────────────────────────────────────────────
|
||||
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; BOLD='\033[1m'; NC='\033[0m'
|
||||
|
|
|
|||
|
|
@ -215,6 +215,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<a href="analytics.html" class="text-xs text-brand-500 hover:underline">Analytics →</a>
|
||||
<div id="userInfo" class="hidden flex items-center gap-2">
|
||||
<span id="userDisplay" class="text-sm font-medium text-gray-700 dark:text-gray-300"></span>
|
||||
<button onclick="signOut()" class="p-1.5 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors" title="Sign out">
|
||||
|
|
|
|||
|
|
@ -35,7 +35,9 @@
|
|||
<h1 class="text-xl font-bold text-brand-700 dark:text-brand-400">SLA Brief Advisor</h1>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400 mt-0.5">eCom Content Factory</p>
|
||||
</div>
|
||||
<button id="darkToggle" class="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors" title="Toggle dark mode">
|
||||
<div class="flex items-center gap-3">
|
||||
<a href="analytics.html" class="text-xs text-brand-500 hover:underline">Analytics →</a>
|
||||
<button id="darkToggle" class="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors" title="Toggle dark mode">
|
||||
<svg id="sunIcon" class="w-5 h-5 hidden" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"/></svg>
|
||||
<svg id="moonIcon" class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/></svg>
|
||||
</button>
|
||||
|
|
|
|||
36
script.js
36
script.js
|
|
@ -29,6 +29,36 @@ let currentStep = 1;
|
|||
let activeStages = [false, false, false, false, false, false, false, false];
|
||||
let lastCalculationData = null;
|
||||
|
||||
// ---- Usage Tracking ----
|
||||
const TRACK_API = (() => {
|
||||
if (location.hostname === 'localhost' || location.hostname === '127.0.0.1') return null;
|
||||
const base = location.pathname.replace(/\/[^/]*$/, '');
|
||||
return `${base}/api/events`;
|
||||
})();
|
||||
|
||||
async function getVisitorId() {
|
||||
const raw = [
|
||||
navigator.language,
|
||||
screen.width + 'x' + screen.height,
|
||||
screen.colorDepth,
|
||||
Intl.DateTimeFormat().resolvedOptions().timeZone,
|
||||
navigator.hardwareConcurrency || '',
|
||||
].join('|');
|
||||
const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(raw));
|
||||
return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('');
|
||||
}
|
||||
|
||||
function trackEvent(event, metadata = {}) {
|
||||
if (!TRACK_API) return;
|
||||
getVisitorId().then(visitor_id => {
|
||||
fetch(TRACK_API, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ event, page: 'calculator', visitor_id, metadata }),
|
||||
}).catch(() => {});
|
||||
});
|
||||
}
|
||||
|
||||
// ---- Bootstrap ----
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
await initAuth();
|
||||
|
|
@ -37,6 +67,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
initStepper();
|
||||
initDatePickers();
|
||||
bindEvents();
|
||||
trackEvent('page_view');
|
||||
});
|
||||
|
||||
async function loadConfig() {
|
||||
|
|
@ -664,6 +695,8 @@ function intVal(id) {
|
|||
// ---- Render Results ----
|
||||
function renderResults(data) {
|
||||
lastCalculationData = data;
|
||||
const briefType = document.getElementById('briefType').selectedOptions[0]?.text;
|
||||
trackEvent('show_results', { briefType });
|
||||
|
||||
// Verdict banner
|
||||
const banner = document.getElementById('verdictBanner');
|
||||
|
|
@ -948,8 +981,9 @@ function csvEscape(str) {
|
|||
// ---- Copy for Email (Rich HTML) ----
|
||||
function copyForEmail() {
|
||||
if (!lastCalculationData) return;
|
||||
const data = lastCalculationData;
|
||||
const briefType = document.getElementById('briefType').selectedOptions[0]?.text || '';
|
||||
trackEvent('copy_email', { briefType });
|
||||
const data = lastCalculationData;
|
||||
|
||||
// Inline styles for Outlook compatibility
|
||||
const tbl = 'border-collapse:collapse;width:100%;font-family:Calibri,Arial,sans-serif;font-size:13px;';
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue