Public Access
1
0

feat: enhance blog post view counter with individual tracking and display

This commit is contained in:
2025-08-24 23:36:11 -04:00
parent 9b2f5d5840
commit 3416ee171c
3 changed files with 78 additions and 40 deletions

View File

@@ -9,15 +9,20 @@ eleventyExcludeFromCollections: true
<div class="space-y-8">
{%- for post in collections.general | reverse -%}
<div class="card">
<h2 class="text-2xl font-bold">
<h2 class="text-2xl font-bold mb-1">
<a href="{{ post.url }}" class="text-blue-400 hover:underline">{{ post.data.title }}</a>
</h2>
<p class="text-gray-400 mb-4">
{{ post.date | readableDate }}
</p>
<div class="flex items-center text-gray-400 mb-4">
<i class="fas fa-calendar mr-2"></i>
<p>{{ post.date | readableDate }}</p>
<span class="mx-2 text-gray-600">|</span>
<i class="fas fa-eye mr-2"></i>
<span class="view-count" data-view-count data-slug="{{ post.fileSlug }}">...</span>
</div>
{% if post.data.excerpt %}
<p class="text-gray-300">{{ post.data.excerpt }}</p>
{% endif %}
</div>
{%- endfor -%}
</div>
<script src="/js/view-counter.js"></script>

View File

@@ -3,8 +3,8 @@ title: "Junos ZTP with Dnsmasq DHCP in OPNsense"
date: "2025-08-14"
layout: "post.njk"
tags: "general"
description: "Stop configuring your new lab devices manually!"
excerpt: "Stop configuring your new lab devices manually! This guide will show you how to 'Zero Touch' provision Junos devices!"
description: "Stop configuring your new lab devices manually! This guide will show you how to 'Zero Touch' provision Junos devices!"
excerpt: "Stop configuring your new lab devices manually!"
sitemapPriority: 0.8
sitemapChangefreq: "weekly"
image: "/assets/images/8.14.25/junos+opnsense.jpg"

View File

@@ -1,37 +1,70 @@
document.addEventListener('DOMContentLoaded', () => {
const viewCountElement = document.querySelector('[data-view-count]');
// Select all elements that are designated to display view counts.
const viewCountElements = document.querySelectorAll('[data-view-count]');
if (viewCountElement) {
const slug = viewCountElement.dataset.slug;
// Function to fetch and display the view count
const getViews = async () => {
try {
const response = await fetch(`/api/views/${slug}`);
if (!response.ok) throw new Error('Failed to fetch views');
const data = await response.json();
viewCountElement.textContent = `${data.count} views`;
} catch (error) {
console.error('Error getting views:', error);
viewCountElement.textContent = 'Could not load views';
// If no such elements are found, do nothing.
if (viewCountElements.length === 0) {
return;
}
};
// Function to increment the view count
const incrementView = async () => {
try {
// Use a flag in localStorage to prevent incrementing on every refresh
// Process each view count element found on the page.
viewCountElements.forEach(element => {
const slug = element.dataset.slug;
if (!slug) {
// Skip if the element is missing the data-slug attribute.
return;
}
// Check if the element is on a single post page by looking for a `.post-meta` parent.
// This distinguishes a single post view (which should be counted) from a list view.
const isSinglePost = element.closest('.post-meta');
if (isSinglePost) {
// On a single post page, increment the view count.
const viewed = localStorage.getItem(`viewed-${slug}`);
if (!viewed) {
await fetch(`/api/views/${slug}`, { method: 'POST' });
localStorage.setItem(`viewed-${slug}`, 'true');
}
} catch (error) {
console.error('Error incrementing view:', error);
}
};
// Run the functions
incrementView().then(getViews);
// Only increment if the user hasn't viewed this post in the current session.
if (!viewed) {
fetch(`/api/views/${slug}`, { method: 'POST' })
.then(response => {
if (!response.ok) throw new Error('Network response was not ok');
return response.json();
})
.then(data => {
element.textContent = data.count ?? 'Error';
// Mark as viewed to prevent re-counting on refresh.
localStorage.setItem(`viewed-${slug}`, 'true');
})
.catch(error => {
console.error(`Error incrementing view count for slug ${slug}:`, error);
element.textContent = 'N/A';
});
} else {
// If already viewed in this session, just fetch the count without incrementing.
fetch(`/api/views/${slug}`)
.then(response => {
if (!response.ok) throw new Error('Network response was not ok');
return response.json();
})
.then(data => {
element.textContent = data.count ?? 0;
})
.catch(error => {
console.error(`Error fetching view count for slug ${slug}:`, error);
element.textContent = 'N/A';
});
}
} else {
// On a list page (like the main blog page), just fetch and display the count.
fetch(`/api/views/${slug}`)
.then(response => response.json())
.then(data => {
element.textContent = data.count ?? 0;
})
.catch(error => {
console.error(`Error fetching view count for slug ${slug}:`, error);
element.textContent = 'N/A';
});
}
});
});