Collecting user statistics on documentation sites can help creators understand common user behaviors, giving them more information to make decisions and create better experiences.
In this article, we'll learn how to use Appwrite and Vuepress to collect and store the following data:
- Likes (when a reader clicks a like button)
- Views (when a reader views the page)
We can find the finished code for this article on GitHub here.
Prerequisites
- Working knowledge of Javascript and Vue.js
- Docker installation
- An Appwrite instance; check out this article on how to set up an instance locally or via a one-click install on DigitalOcean or Gitpod
Installing Vuepress
Vuepress is a minimalistic static site generator with a Vue-powered theming system and a default theme that has been optimized for writing technical documentation.
We'll need to create a Vuepress starter project by navigating to the desired directory and running the command below in our terminal.
npx create-vuepress-site appwrite-stats && cd appwrite-stats
The command will create a project called appwrite-stats
which will interactively ask a series of questions that will be used to build our site's metadata. Let’s answer them accordingly.
Once it’s done creating the project, the second command will navigate into the project directory.
Once the installation completes, let's run the following command in the terminal:
cd docs && npm install && npm run dev
The command navigates into the docs
folder - which Vuepress creates during installation - installs all of the required dependencies, and then runs the build server at [http://localhost:8080](http://localhost:8080/)
.
When we visit http://localhost:8080
on our browser, we should see the following screen:
Installing Appwrite
Appwrite is an open-source end-to-end back-end server solution that enables developers to build applications faster.
To use Appwrite in our Vuepress application, we'll need to install the Appwrite SDK for web applications.
In the /appwrite-stats/docs
directory on our terminal, let's run the command below to install the Appwrite SDK:
npm install appwrite
Next, let's create a utils
folder, and in it, we'll add an index.js
file with the following content:
import { Client, Databases } from "appwrite";
const client = new Client()
.setEndpoint("API_ENDPOINT") // Your API Endpoint
.setProject("PROJECT_ID"); // Your project ID
export const database = new Databases(client);
Don't worry about the dummy values, we will fill them in later sections of this tutorial.
Setting up an Appwrite Database
First, let's ensure that the Docker desktop is running our local Appwrite instance:
Once the Appwrite instance is verified, let's go ahead to open localhost:80
(our specified port during Appwrite installation) in the browser to sign into Appwrite's console:
On the console, click the Create Project button, enter appwrite-stats
as the name, and click on Create.
On the Settings tab of the Home page of our newly created project, let's take note of our Project ID and API Endpoint.
Creating an Appwrite Collection and Attributes
On the left side of the Appwrite Console dashboard, click on the Database tab. Click on the Add Database button to create a new database. Creating a new database will lead us to the Collection page.
Next, we'll create a collection in our database tab by clicking the Add Collection button. After creating a Collection, go to the Permissions section on the Settings page. We want to assign Read and Update Access with a Role value of any
. We can customize these roles later to specify who has access to our database. We'll click on Update to save our changes.
Next, let's go to the Attributes tab on our collection to create the properties we want our document to have:
Let's create integer attributes of viewsCount and likesCount and set their default values to zero.
Creating an Appwrite Document
After creating the attributes, let's head to the Documents tab of our database.
Click on the Add Document button to create a new document.
We had already specified default values of zero for our attributes earlier, so we can click the Create button to create the document.
Let's also note and copy our Document ID, Collection ID, and Database ID, which we'll use to perform functions to update the values depending on the user action.
Building Components in Vuepress
Vuepress pages are written primarily in markdown format; however, being built with Vue.js, Vuepress lets us create and embed Vue.js components in our markdown pages.
Building a Likes Component
We'll build a "likes" component on our site's pages.
Users could click on the component to like a specific page and view the page's total number of likes.
To get started, let's navigate to the /src/.vuepress/components
folder in our project directory, create a file named likes-component.vue
, and paste in the following code:
<template>
<div class="like-container">
<button @click="likePage">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="30"
height="30"
>
<path fill="none" d="M0 0H24V24H0z" />
<path
d="M12.001 4.529c2.349-2.109 5.979-2.039 8.242.228 2.262 2.268 2.34 5.88.236 8.236l-8.48 8.492-8.478-8.492c-2.104-2.356-2.025-5.974.236-8.236 2.265-2.264 5.888-2.34 8.244-.228zm6.826 1.641c-1.5-1.502-3.92-1.563-5.49-.153l-1.335 1.198-1.336-1.197c-1.575-1.412-3.99-1.35-5.494.154-1.49 1.49-1.565 3.875-.192 5.451L12 18.654l7.02-7.03c1.374-1.577 1.299-3.959-.193-5.454z"
/>
</svg>
</button>
<p>{{ numberOfLikes }} likes</p>
</div>
</template>
<script>
import { database } from "../../utils/index.js";
export default {
data() {
return {
numberOfLikes: 0,
};
},
mounted() {
this.getLikesCount();
},
methods: {
async likePage() {
this.numberOfLikes++;
try {
await database.updateDocument(
'[DATABASE_ID]',
'[COLLECTION_ID]',
'[DOCUMENT_ID]',
{
likesCount: this.numberOfLikes,
}
);
this.getLikesCount();
} catch (error) {
console.log(error);
}
},
async getLikesCount() {
try {
let promise = await database.listDocuments(
"[DATABASE_ID]",
"[COLLECTION_ID]"
);
this.numberOfLikes = promise.documents[0].likesCount;
} catch (error) {
console.log(error);
}
},
},
};
</script>
<style lang="css">
.like-container {
display: flex;
align-items: center;
gap: 10px;
}
button {
cursor: pointer;
}
p {
font-size: 20px;
}
</style>
The code snippet above does the following:
- Imports the created
database
instance from the/utils/index.js
file. - The
getLikes
method gets invoked during the page load using the mounted lifecycle hook, the method gets invoked; the total number of existing likes is fetched from our Appwrite database and assigned to thenumberOfLikes
data variable. - When a user clicks on the button, the
@click= "likePage"
event handler invokes thelikePage
method, increments the number of likes, and stores the data on our database. Once done, thegetLikesCount
method gets invoked to get the current number of likes and store it in thenumberOfLikes
variable so that when a user refreshes the page, the data persists.
Building a Number-of-Views Component
We'll build a views-count
component on our site's pages. Users can see the total number of page views a particular page has.
In the /src/.vuepress/components
, create a views-component.vue
file, and paste in the following code snippet:
<template>
<div class="views-container">
<p>{{ numberOfViews }} Views</p>
</div>
</template>
<script>
import { database } from "../../utils/index.js";
export default {
data() {
return {
numberOfViews: 0,
};
},
mounted() {
this.addToViewCount();
},
methods: {
async addToViewCount() {
try {
await this.getViewCount();
this.numberOfViews++;
await database.updateDocument(
"[DATABASE_ID]",
"[COLLECTION_ID]",
"[DOCUMENT_ID]",
{
viewsCount: this.numberOfViews,
}
);
} catch (error) {
console.log(error);
}
},
async getViewCount() {
try {
let promise = await database.listDocuments(
"[DATABASE_ID]",
"[COLLECTION_ID]"
);
this.numberOfViews = promise.documents[0].viewsCount;
} catch (error) {
console.log(error);
}
},
},
};
</script>
<style lang="css">
.views-container {
font-size: 20px;
}
</style>
Let's analyze what the code snippet above does:
- It creates an HTML template with a
p
tag that displays the number of views. - It imports our Appwrite database instance from the
../../utils/index.js
file. - As their naming suggests, these two methods:
getViewCount
andaddToViewCount
, get the total number of page views and increment the total number of page views from our Appwrite database. - When the page first loads, using the
mounted
lifecycle hook, theaddToViewCount
method invokes thegetViewCount
method, and the total number of existing views is fetched from our Appwrite database and assigned to thenumberOfViews
data variable. Once that's done, thenumberOfViews
variable is incremented by one and then stored on our Appwrite database.
Using the Components in Our Markdown Files
Now, we've finished creating our components and can use them on any of our desired pages.
Let's use it in the using-vue.md
file located in the /src/guide
directory.
At the bottom of the page, we’ll add the following code snippet:
...
### Enjoyed this page? Give it a like:
<likes-component/>
### This page has:
<views-component/>
On the browser, let's go to the http://localhost:8080/guide/using-vue.html
page. Let's see the result of what we've got so far:
As we can see, when we click the like button, it increments the count, and when we leave to another page and back, the number of page views also increases.
Conclusion
This article discussed how to use Appwrite's database functionality and, more importantly, how to collect documentation statistics using Vuepress.