Anonymous portfolio statistics (opens/downloads per image, cookieless) + privacy text

Counts go to customer.imagesbyolofsson.se/api/stats/hit via sendBeacon. No cookie, IP or id stored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Claude (for Linus)
2026-10-27 11:41:59 +01:00
parent 31d4e540ce
commit ce5676f552
2 changed files with 26 additions and 0 deletions
+17
View File
@@ -222,6 +222,21 @@ const uniqueMonths = [...new Map(allMonths.map(item => [item.name, item])).value
</style>
<script>
// --- ANONYM STATISTIK ---
// Räknare per dag och bild i kundportalen: ingen cookie, ingen IP, inget id.
const STATS_URL = 'https://customer.imagesbyolofsson.se/api/stats/hit';
function statsItem(src: string): string {
const file = (src.split('/').pop() || '').replace(/\.[A-Za-z0-9_-]{6,12}\.(jpe?g|webp|avif|png)$/i, '');
return ('portfolio/' + file.replace(/[^\w\-.]/g, '_')).slice(0, 150);
}
function stat(kind: 'view' | 'open' | 'download', item: string) {
try {
const body = new Blob([JSON.stringify({ kind, item })], { type: 'text/plain' });
navigator.sendBeacon?.(STATS_URL, body);
} catch { /* statistik får aldrig störa sidan */ }
}
stat('view', 'page/portfolio');
// --- FILTER LOGIK ---
// MULTI-select: flera ar + manader samtidigt. 'all' = samtligt.
let selectedYears = new Set(['all']);
@@ -358,6 +373,7 @@ const uniqueMonths = [...new Map(allMonths.map(item => [item.name, item])).value
visaMeny(false);
const url = urlForSize(size);
if (!url) { alert('Den storleken saknas for den har bilden.'); return; }
stat('download', statsItem(visibleItems[currentImageIndex]?.dataset.src || ''));
if (size === 'orig') {
// Losenordet sparas bara for fliken, aldrig i localStorage.
const sparat = sessionStorage.getItem('dlpw');
@@ -413,6 +429,7 @@ const uniqueMonths = [...new Map(allMonths.map(item => [item.name, item])).value
visaMeny(false);
lbImg.src = item.dataset.src || '';
stat('open', statsItem(item.dataset.src || ''));
if(lbDate) lbDate.innerText = item.dataset.date || '';
if(lbModel) lbModel.innerText = item.dataset.model || '';