Use page views and likes to sort lists and display social-proofs

In this tutorial, I will explain how to add data-driven features to your website. By data-driven, I mean features that rely on data generated by website users — think recommendations, personalisation, social proofs and similar.

The project consists of two pages — “list.html” with the list of alphabet letters and “item.html” with an individual letter as specified in URL params.

In the first part of the tutorial, I’ll show you how to do some basic stuff:

  1. add “x people viewed this page” badge
  2. add “like” feature
  3. show number of “likes” on a page and the list of links to the pages
  4. sort page links by likes and views.

Whether you have an online shop or a static website, you can do that literally in minutes. You will need a database, load balancing, cron jobs… I’m kidding!

You won’t need any of that, just some basic knowledge of JavaScript and a free DataDrivenJS account.

DataDrivenJS works like a database which you can populate with data generated by your website’s users, the same way you send data to your web analytics. But, unlike web analytics, DataDrivenJS won’t show you any pie charts. Instead, it will allow you to access your analytics data directly from the site using good old JavaScript.

0. The Tutorial Source Files

Take a look at the initial version and then at the final version to understand what we are going to do. You can download the sources of both versions from github.

1. The Setup

First, you need to sign up for DataDrivenJS. Once you have the account and you are signed in to the DD.Console, add the project and name it, for example, “The Letters Tutorial”. A minute later, you will be able to copy the DD.js script tag, customised with your project settings.

DD.js script that you need to add on your website is responsible for two things:

  • sending the user’s data from the browser to the tracking servers
  • reading the historical data from the servers, so you can use it on the site

Tip: you can download and serve the script from your own server, just remember to preserve the params in the script’s URL or add the params to the data layer. You could also use the npm package. Check the docs for the details.

We have two pages in our project (list.html and item.html) and we need to add the tag to both of them. You can place it at the end of the <body> tag or in the <head> tag.

2. Tracking the Data

Unsurprisingly, when you create a project you start with no data at all. So let’s track a couple of visits so we have some data to play with.

Life-Saving Tip: A visit’s data is available 30 minutes after the last tracked data point. If you don’t want to wait that long, call DD.tracker.stop() in the browser’s console and it will be available a minute later.

In the top right corner of the console, there’s a link activating the Dev Mode.

Tip: if you are working on your computer without a localhost, simply leave the URL field blank, select ‘I will manually enable the Dev Mode’ and click Open. Once a new browser tab opens, replace its URL with your local address — starting with file:/// …

By default, the service tracks some common visit properties like user’s screenWidth or the URL of a referring website. While in the Dev Mode, you can preview what data is being tracked in the browser’s console.

3. The Data

Once you have tracked a couple of visits — try tracking them in new incognito windows to emulate different users — go to the Tracked Data in the DD.Console. You will see there all the data from the visits that were already completed.

You will notice that there are two types of data: properties and meta events. Each visit can have exactly one value per property, but n values per metaevent. For example, a visit may have exactly one start time, therefore, the startTime is a property. However, during a visit, a visitor can open multiple pages so the URL — a datapoint containing information which pages were visited — needs to be of a metaevent type. This distinction is very important.

4. Creating a Data Feed with Page Views

In order to use the tracked data on your site, you need to create a data feed. A data feed is a subset of all your data, filtered and/or aggregated in some way, that you can use on your website without any authorisation.

Before you can use the tracked data on your site, you need to create a public Data Feed

In this tutorial, we need to create a data feed with the list of the letter pages and their respective page view count, so we can display that data on the item.html page.

item.html page

Since each letter has its own, unique URL and visited URLs are automatically tracked as metaevents, we could simply count how many times each URL was tracked.

Tip: at this point, you may want to have the documentation opened.

First, we need to add the following query in JavaScript to the item.js:

// create data feed, it has to be named so you can manage it
// in the DD.Console
var feed = DD.data.feed('Letter Page Views');
// select URLs and their count as 'views' into the feed
feed.select(
DD.data.datapoints.metaevent('URL')
.contains('/item.html').as('URL'),
DD.data.datapoints.metaevent('URL')
.contains('/item.html').count().as('views')
);

which will create a data feed like this one below

[
{"URL":"localhost:3000//item.html...", "views":310},
{"URL":"localhost:3000//item.html...", "views":290},
...
]

Note: only the URLs containing “item.html” phrase will be included in the feed, and the count value will be returned using the “views” alias.

However, the feed won’t be created until we make the first attempt to select some data from it using the DD.reader.read method:

// create data feed, it has to be named so you can manage it
// in the DD.Console
var feed = DD.data.feed('Letter Page Views');
// select URLs and their count as 'views' into the feed
feed.select(
DD.data.datapoints.metaevent('URL')
.contains('/item.html').as('URL'),
DD.data.datapoints.metaevent('URL')
.contains('/item.html').count().as('views')
);
// read the entire data feed:
DD.reader.read(feed, {}, function(response){
console.log('Results:',response.results)
})

This is a perfectly valid code, but if you open item.html in a browser, you might get a warning in the browser’s console that the data feed you requested doesn’t exist:

Why? Because, if the feed doesn’t exist yet, it needs to be created and you have to be authorised to create feeds. Otherwise, anyone could access all your data.

So how do you get authorised?

5. Authorising New Data Feeds

The very first request to read a data feed needs to be made in the Dev Mode. If you are not in the Dev Mode yet, sign in to your project in DD.Console and click the link in the top right corner to enable it.

Try to run the code again. This time, you will get the data from the feed.

It is required that window in which you are testing your website is opened by the window with DD.Console. Otherwise, you will get the following error:

{code: "NOT_CONNECTED", message: "Open the window with the website from the Console in order to authorise your requests."}

Tip: The first requests takes some time as the feed has to be created and sent to the load balancer. The consecutive requests will be returned immediately, just try again if you don’t believe me.

Reading the Data Using Feed Queries

When we read the data feed and pass an empty object as the second argument, like in the code below:

// read the entire data feed:
DD.reader.read(feed, {}, function(response){
console.log(response)
})

we download the entire content of the feed.

Since feeds can contain lots of data, it’s worth considering using a feed query to read just a portion of it. In this case, we only need the number of views for the currently viewed URL:

// prepare a query
var query = DD.data.feedQuery()
.select(DD.data.feedColumn('views'))
.where(DD.data.feedColumn('URL').equals(window.location.href));
// read a subset of the data feed:
DD.reader.read(feed, query, function(response){
console.log(response.results)
})

Now, the response will contain just a single row, or no rows at all, if there are no matching URLs in the dataset:

DD.reader.read (feed, query, function(response){
if (response.results[0]) {
// someone viewed this letter
}else{
// no one viewed this letter
}
});

Scheduling the Auto-Refreshing of the Data Feed

If you switch browser tabs back to DD.Console, you will notice that it now shows the table with the contents of your feed. This data in the feed won’t be updated, ever!, unless you manually refresh its content in the DD.Console or schedule the auto-refreshing.

You may opt-in to get the data from the updated feed over email. Just add the recipients —each of the recipients will get an invite and will need to sign up before they start getting the emails.

Tip: At the moment, the highest frequency is once per hour, but try to be reasonable — if your feed contains data from the past year, perhaps it will be enough to refresh the data feed once a week, say on Monday at 7 am. This way, you will also avoid flooding your mailbox if you opted-in for email updates.

Tracking Custom Data — The Likes

We could show the page views because the visited URLs are automatically tracked as metaevents. But what about the likes?

First, we need to add a “like” button and track a custom metaevent when someone clicks it:

likeBtn.addEventListener('click',function(e){
DD.tracker.trackMetaEvent('liked',letterID);
});

Important: Remember what I told you about the difference between metaevents and properties? If you would track likes using a property instead of a metaevent, you would get the data only about the last letter that a user liked during a visit!

Creating a Data Feed with Likes

The page views that we added above were based on all the page views that happened during the visits. If a single user would visit a page 10 times, all those page views would be taken into account. If we would count likes the same way, users could easily “hack” our ranking by liking the same letter multiple times.

To avoid that, our feed needs to count only one like of the same letter per user:

// count unique visitors who liked each letter
var feed = DD.data.feed('Letter Likes'); 
feed.select([
DD.data.datapoints.metaevent("liked"),
DD.data.datapoints.property("visitorID")
.countDistinct().as('likes')
]);

The visitorID property contains an automatically assigned ID, stored in the Local Storage. Unless a user cleans up her browser data or visit the site using a different browser than we’re covered.

Tip: If your website had an account authorisation, you could track a hash of a user’s login — track pseudonymised data whenever possible — as a property. Then you could use it instead of a visitorID for better results.

To show the number of likes on item.html, we need to prepare a feed query to read just one letter instead of the entire feed and handle a case when nobody likes it:

// we need only the current letter!
var query = DD.data.feedQuery()
.select(DD.data.feedColumn('likes'))
.where(DD.data.feedColumn('liked').equals(letterID));
// read the feed using the query
DD.reader.read (feed, query, function(response){
if (response.results[0]) {
// yay, someone likes this letter!
}else{
// no one likes this letter
}
});

Reading Likes from the Existing Data Feed

There’s one last thing we need to do — use the feed with the likes to enhance our list of letters:

If you switch back to the DD.Console and look above the table with the data, you will notice the public data feed key:

Using the key you can access the existing feed without writing its schema. Simply pass it as the first argument instead of the feed object in the list.js:

DD.reader.read (feedKey, {}, function(response){
console.log(response);
// use the response.results to show likes and for sorting
});

In the DD.Console, go to the list of data feeds, select the Letter Page Views and copy its key:

The same way you have just used likes and views, you could, for example track purchased products and build bestsellers in your shop.

Anyway, that’s it for now. Almost!

I have a favour to ask. DataDrivenJS is still early in the beta testing. Your feedback will mean the world to me. Thanks!

Tip: If you don’t want to miss the next parts of this tutorial then follow DataDrivenJS on Medium or on Product Hunt.