Votes and Views Part 1
How to have views and votes on a static created website? In a server side website (php/react/etc) you would pull the counters from the database and inject in the code while serving. This website is static generated by Zola, every time i publish an article. Also cloudflare doesn’t gives you access logs in the free version.
I could use Google Analytics to track people, but that would includes cookies and send a lot of data to Google. As a real engineer i wrote my own small version. This first article is about the client side, next part will be about the AWS backend.
Design
Up&Down vote, like/dislike are common among websites with content. The old style Youtube had 2 counters, one for like and another for dislike. Reddit uses a single number. Since the traffic on my blog is very low i keep it simple and just have some 1 counter.
Other criteria:
- Intuitive interface
- Responsive changes
- Prevent multiple votes
- No Cookies
My first iteration looks like this in the list: and like this on the article page top:
I use the icons from fontawesome.com.
With just this: <i class="fa-solid fa-circle-up"></i>
you have a nice icon for an up vote. The eye shows the views and plus sign to read more.
Implementation
In the template code this shows as the following:
A simple onclick for that points to a javascript function. vote('down','{{ post.permalink }}')
The view and vote counters are wrapped in a span with a specific id. id="VOTE#{{ post.permalink }}"
later this is used to update the counter dynamically.
The vote script does a GET request to the RestAPI on AWS.
First to prevent multiple votes i use LocalStorage. It stores the page and the action, if you try to upvote or downvote twice it refuses.
The item is VOTE#https://jacob.verhoeks.org/votes-and-views-1/
.
I expected the referer in the javascript to reflect the page the requests origins, but the browser uses the root url. To work around, i use a custom header: X-Referer
to pass it on the backend.
No Post data or GET url parameter required.
The restapi /vote/up
will do a ADD 1
in the counter for that page and returns the new value. /vote/down
does add ADD -1
.
The document.getElementById("VOTE#"+page).innerHTML= xhr.response.Count
locates the right span that counts the vote count and updates the DOM dynamically.
Views
Views don’t have an interactive option, they are registered whenever you visit a page. For this there is a javascript function that loads on every view. It sends a view update to the system. Besides the page i store the windows and viewport size to see how people watch my blog. Also the language is interesting to see where people come from.
Updating mode
To update the page while normally browsing there is a function running and every page view, it retries all votes and views for the website and update the DOM if it exists on the page.
Backend
Next blog will be about the backend. I uses CDK / Typescript / API Gateway / DynamoDB , but no lambda’s.