Skip to content

Commit c924e37

Browse files
author
Your Name
committed
Restore podcast link and visitor counter
Bring back the podcast entry points and reintroduce traffic counters with a 92-visitor baseline.
1 parent 68d4c2d commit c924e37

1 file changed

Lines changed: 213 additions & 0 deletions

File tree

index.html

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,35 @@
317317
animation: counterPulse 0.4s ease;
318318
}
319319

320+
.traffic-counter {
321+
display: flex;
322+
align-items: center;
323+
justify-content: center;
324+
gap: 0.75rem;
325+
margin-top: 0.75rem;
326+
font-size: 0.9rem;
327+
color: var(--text-secondary);
328+
}
329+
330+
.traffic-metric {
331+
display: inline-flex;
332+
align-items: center;
333+
gap: 0.35rem;
334+
}
335+
336+
.traffic-value {
337+
font-weight: 600;
338+
color: var(--accent);
339+
}
340+
341+
.traffic-value.updated {
342+
animation: counterPulse 0.4s ease;
343+
}
344+
345+
.traffic-separator {
346+
color: var(--border);
347+
}
348+
320349
@keyframes counterPulse {
321350
0% { transform: scale(1); }
322351
50% { transform: scale(1.15); color: var(--accent-bright); }
@@ -796,6 +825,7 @@
796825
<a href="#examples">Examples</a>
797826
<a href="#install">Install</a>
798827
<a href="#configure">Configure</a>
828+
<a href="podcast.html">Podcast</a>
799829
<a href="#changelog">Changelog</a>
800830
<a href="#faq">FAQ</a>
801831
<a href="https://github.com/Persistence-AI" class="github-btn" target="_blank" rel="noopener" style="text-decoration: none;">
@@ -870,6 +900,17 @@ <h3 style="font-size: 1.2rem; margin-bottom: 1rem; color: var(--text-primary);">
870900
</div>
871901
</div>
872902
</div>
903+
<div class="traffic-counter" id="traffic-counter">
904+
<div class="traffic-metric">
905+
<span class="traffic-value" id="visitor-count">0</span>
906+
<span class="traffic-label">visitors</span>
907+
</div>
908+
<span class="traffic-separator">|</span>
909+
<div class="traffic-metric">
910+
<span class="traffic-value" id="pageview-count">0</span>
911+
<span class="traffic-label">page views</span>
912+
</div>
913+
</div>
873914
</div>
874915
<div class="more-options">
875916
<a href="#install">More options →</a>
@@ -2373,6 +2414,7 @@ <h2 style="margin-bottom: 2rem;">
23732414
<a href="#changelog">Changelog</a>
23742415
<a href="https://github.com/Persistence-AI" target="_blank" rel="noopener">Persistence Zero</a>
23752416
<a href="https://persistence-ai.github.io/Landing/docs/" target="_blank" rel="noopener">Documentation</a>
2417+
<a href="https://persistence-ai.github.io/Landing/podcast.html" target="_blank" rel="noopener">Podcast</a>
23762418
<a href="https://discord.gg/persistenceai" target="_blank" rel="noopener">Discord</a>
23772419
<a href="https://x.com/AiPersiste65218" target="_blank" rel="noopener">X.com</a>
23782420
</div>
@@ -2397,6 +2439,16 @@ <h2 style="margin-bottom: 2rem;">
23972439
total: 0
23982440
};
23992441

2442+
const TRAFFIC_GIST_ID = '';
2443+
const TRAFFIC_READ_ENABLED = Boolean(TRAFFIC_GIST_ID);
2444+
const TRAFFIC_WRITE_ENDPOINT = '';
2445+
const TRAFFIC_WRITE_ENABLED = Boolean(TRAFFIC_WRITE_ENDPOINT);
2446+
2447+
let trafficStats = {
2448+
visitors: 92,
2449+
pageViews: 92
2450+
};
2451+
24002452
// Session management
24012453
function getOrCreateSessionId() {
24022454
let sessionId = sessionStorage.getItem('persistenceai_session_id');
@@ -2522,6 +2574,166 @@ <h2 style="margin-bottom: 2rem;">
25222574
return num.toLocaleString('en-US');
25232575
}
25242576

2577+
function updateTrafficDisplay(animate = false) {
2578+
const visitorEl = document.getElementById('visitor-count');
2579+
const pageViewEl = document.getElementById('pageview-count');
2580+
2581+
if (visitorEl) {
2582+
visitorEl.textContent = formatNumber(trafficStats.visitors);
2583+
if (animate) {
2584+
visitorEl.classList.add('updated');
2585+
setTimeout(() => visitorEl.classList.remove('updated'), 400);
2586+
}
2587+
}
2588+
2589+
if (pageViewEl) {
2590+
pageViewEl.textContent = formatNumber(trafficStats.pageViews);
2591+
if (animate) {
2592+
pageViewEl.classList.add('updated');
2593+
setTimeout(() => pageViewEl.classList.remove('updated'), 400);
2594+
}
2595+
}
2596+
}
2597+
2598+
function loadTrafficFromStorage() {
2599+
const stored = localStorage.getItem('persistenceai_traffic_stats');
2600+
if (!stored) {
2601+
return;
2602+
}
2603+
try {
2604+
const parsed = JSON.parse(stored);
2605+
trafficStats = {
2606+
visitors: parseInt(parsed.visitors || 0, 10),
2607+
pageViews: parseInt(parsed.pageViews || 0, 10)
2608+
};
2609+
} catch (e) {
2610+
console.error('Error parsing stored traffic stats:', e);
2611+
}
2612+
}
2613+
2614+
function saveTrafficToStorage() {
2615+
localStorage.setItem('persistenceai_traffic_stats', JSON.stringify(trafficStats));
2616+
}
2617+
2618+
function getDateKey() {
2619+
return new Date().toISOString().split('T')[0];
2620+
}
2621+
2622+
async function getVisitorFingerprint() {
2623+
const input = [
2624+
navigator.userAgent,
2625+
navigator.language,
2626+
screen.width,
2627+
screen.height,
2628+
screen.colorDepth,
2629+
Intl.DateTimeFormat().resolvedOptions().timeZone || 'unknown'
2630+
].join('|');
2631+
const encoded = new TextEncoder().encode(input);
2632+
const hashBuffer = await crypto.subtle.digest('SHA-256', encoded);
2633+
return Array.from(new Uint8Array(hashBuffer))
2634+
.map((b) => b.toString(16).padStart(2, '0'))
2635+
.join('');
2636+
}
2637+
2638+
function getFallbackFingerprint() {
2639+
const key = 'persistenceai_fallback_fingerprint';
2640+
let fingerprint = localStorage.getItem(key);
2641+
if (!fingerprint) {
2642+
fingerprint = `fp_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
2643+
localStorage.setItem(key, fingerprint);
2644+
}
2645+
return fingerprint;
2646+
}
2647+
2648+
async function refreshTrafficFromGist() {
2649+
if (!TRAFFIC_READ_ENABLED) {
2650+
return;
2651+
}
2652+
try {
2653+
const response = await fetch(`https://api.github.com/gists/${TRAFFIC_GIST_ID}`);
2654+
if (!response.ok) {
2655+
return;
2656+
}
2657+
const gist = await response.json();
2658+
const filename = Object.keys(gist.files || {})[0];
2659+
if (!filename) {
2660+
return;
2661+
}
2662+
const content = gist.files[filename].content;
2663+
const parsed = JSON.parse(content);
2664+
if (parsed && parsed.visitors && parsed.pageViews) {
2665+
trafficStats = {
2666+
visitors: parseInt(parsed.visitors.total || 0, 10),
2667+
pageViews: parseInt(parsed.pageViews.total || 0, 10)
2668+
};
2669+
updateTrafficDisplay();
2670+
saveTrafficToStorage();
2671+
}
2672+
} catch (e) {
2673+
console.error('Error fetching traffic stats:', e);
2674+
}
2675+
}
2676+
2677+
async function trackPageView() {
2678+
let fingerprint = '';
2679+
try {
2680+
fingerprint = await getVisitorFingerprint();
2681+
} catch (e) {
2682+
fingerprint = getFallbackFingerprint();
2683+
}
2684+
2685+
const today = getDateKey();
2686+
2687+
if (!TRAFFIC_WRITE_ENABLED) {
2688+
const seenKey = 'persistenceai_visitor_seen';
2689+
if (!localStorage.getItem(seenKey)) {
2690+
trafficStats.visitors += 1;
2691+
localStorage.setItem(seenKey, 'true');
2692+
}
2693+
trafficStats.pageViews += 1;
2694+
updateTrafficDisplay(true);
2695+
saveTrafficToStorage();
2696+
return;
2697+
}
2698+
2699+
try {
2700+
const response = await fetch(TRAFFIC_WRITE_ENDPOINT, {
2701+
method: 'POST',
2702+
headers: {
2703+
'Content-Type': 'application/json'
2704+
},
2705+
body: JSON.stringify({
2706+
type: 'pageView',
2707+
fingerprint,
2708+
date: today
2709+
})
2710+
});
2711+
2712+
if (!response.ok) {
2713+
return;
2714+
}
2715+
2716+
const result = await response.json();
2717+
if (result && result.stats && result.stats.visitors && result.stats.pageViews) {
2718+
trafficStats = {
2719+
visitors: parseInt(result.stats.visitors.total || 0, 10),
2720+
pageViews: parseInt(result.stats.pageViews.total || 0, 10)
2721+
};
2722+
updateTrafficDisplay(true);
2723+
saveTrafficToStorage();
2724+
}
2725+
} catch (e) {
2726+
console.error('Error tracking page view:', e);
2727+
}
2728+
}
2729+
2730+
async function initializeTrafficStats() {
2731+
loadTrafficFromStorage();
2732+
updateTrafficDisplay();
2733+
await refreshTrafficFromGist();
2734+
await trackPageView();
2735+
}
2736+
25252737
// Track copy event by platform with rate limiting
25262738
async function trackCopy(platform) {
25272739
// Determine platform
@@ -2678,6 +2890,7 @@ <h2 style="margin-bottom: 2rem;">
26782890
// Initialize counter on page load
26792891
document.addEventListener('DOMContentLoaded', function() {
26802892
initializeCounter();
2893+
initializeTrafficStats();
26812894

26822895
// Auto-detect platform and show appropriate command
26832896
const platform = detectPlatform();

0 commit comments

Comments
 (0)