Setting Up Realtime Post View Counts on GatsbyJS & Netlify with Firebase
Since my blog is a static site that doesn't have backend, I ran into the problem of not being able to track & show the view counts of my blog posts. By having view counts in my blog, it would help readers feels engaged and knows the worth of each of my posts.
So in this post I would like to show you the solution to tackle the problem by using Google Firebase's realtime database!
Firebase Set up
- Sign in to Firebase and add new project. You can name it whatever you want.
- Create a realtime database and choose the "start it test mode".
- Next is to create a Web App in your Project Setting. Make sure to disable Firebase hosting and click on "Register app".
- Go to "Rules" in Realtime Database menu and set
read
,write
totrue
and click on "Publish". this allow us to update data without signing in.
Gatsby Set up
- You need to install these 2 firebase dependencies inside your Gatsby Project. I use yarn for my package manager.
yarn install firebase gatsby-plugin-firebase
- Add the require dotenv at the top and gatsby-plugin-firebase inside your
gatsby-config.js
file.
gatsby-config.js
require("dotenv").config({ path: `.env.${process.env.NODE_ENV}`, }) module.exports = { plugins: [ ...otherPlugins, { resolve: 'gatsby-plugin-firebase', options: { credentials: { apiKey: process.env.GATSBY_API_KEY, authDomain: process.env.GATSBY_AUTH_DOMAIN, databaseURL: process.env.GATSBY_DATABASE_URL, projectId: process.env.GATSBY_PROJECT_ID, storageBucket: process.env.GATSBY_STORAGE_BUCKET, messagingSenderId: process.env.GATSBY_MESSAGING_SENDER_ID, appId: process.env.GATSBY_APP_ID, }, }, }, ], };
- create a
.env.development
file at the root of your gatsby site and have your previously made firebase credential values inside it. You can access these values again in your project setting under Web App.
.env.development
GATSBY_API_KEY='your_values_here' GATSBY_AUTH_DOMAIN='your_values_here' GATSBY_DATABASE_URL='your_values_here' GATSBY_PROJECT_ID='your_values_here' GATSBY_STORAGE_BUCKET='your_values_here' GATSBY_MESSAGING_SENDER_ID='your_values_here' GATSBY_APP_ID='your_values_here' GATSBY_MEASUREMENT_ID='your_values_here'
- Since I'm using Netlify for my
.env.production / deployment environment
I need to put these values insideenvironment variables
in my netlify settings as shown below. Different hosting has different settings be mindful for that. NOTE: I forgot to add GATSBY_ in front of all the variables in the pic. Gatsby requires GATSBY_ naming convention for build .env variables as shown in this forum chat.
Implementing the View Counts
- Create a new file called
increment-views.js
inside a newlib
folder inside your src and use the code below.
src
| lib
| increment-views.js
increment-views.js
import firebase from 'gatsby-plugin-firebase'; const incrementViews = async (id) => { const ref = firebase.database().ref(`/views`).child(id); ref.transaction((currentViews) => { return currentViews + 1; }); }; export default incrementViews;
- Create a new component file called
ViewCounter.js
inside your components folder and use the code below.
src
| components
| ViewCounter.js
ViewCounter.js
import React, { useEffect, useState } from 'react'; import firebase from 'gatsby-plugin-firebase'; import 'firebase/database'; import incrementViews from '../lib/increment-views'; const ViewCounter = ({ id }) => { const [viewCount, setViewCount] = useState(''); useEffect(() => { // 1 is displayed for a split second and then the correct count // This is a workaround const onViews = (newViews) => { setViewCount(newViews.val() === 1 ? 0 : newViews.val()); }; incrementViews(id); firebase.database().ref(`/views`).child(id).on(`value`, onViews); return () => { if (firebase.database()) { firebase.database().ref(`/views`).child(id).off(`value`, onViews); } }; }, [id]); return ( <div> {viewCount ? viewCount : `---`} views </div> ); }; export default ViewCounter;
- Now you can use ViewCounter component on the posts pages inside gatsby, here is how I use mine (I remove other code to make it easier to understand).
src
| templates
| SinglePost.js
SinglePost.js
import React, { Fragment } from 'react' import ViewCounter from '../components/ViewCounter'; export const SinglePost= ({ slug }) => ( <main> <ViewCounter id={slug}/> </main> ) export default SinglePost
That's it !
Now every time someone visits your post, the view will be incremented. This is what it looks on my webpage and firebase's RTDB respectively. Hope you find this post useful, and if it is please leave a comment. Thanks for reading !
My Blog Post with Views
Firebase Database