Published
Edited
Jan 19, 2021
Importers
6 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
analyticsData = queryPageviews(notebooks)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
async function analytics(url = window.location.href) {
// Before we start counting visits, there are some urls (e.g. the observable thumbnail generator)
// and user-agents (e.g the Google crawler) that we would like not to show up in our statistics.
// We therefore check for those, and return early if a blacklisted url or user-agent is encountered
const blacklist = ['/thumbnail/', 'Embedworker'];
const userAgent = navigator.userAgent;
if (blacklist.some(blacklistedURL => url.includes(blacklistedURL))) return;
else if (userAgent.includes('Googlebot')) return;

// In order to get a very rough approximation of where the visitor is located, we query ipinfo.io.
// For reasons of data protection, the ip address itself is not stored in our database.
// This way, we solely store information which cannot be used for identifying an individual
const { country, region, city } = await fetch(
'https://ipinfo.io/json'
).then(res => res.json());

// Given the collected info, we create a uniqe id string including a timestamp,
// the url currently visited, the approximate visitor location, as well as the browsers user-agent
const id = `${new Date().toISOString()}::${url}::${country}::${region}::${city}::${
navigator.userAgent
}`;

// Eventually, we put the document in our CouchDB/Cloudant database
await fetch(db, {
method: 'post',
headers: new Headers({
Authorization: 'Basic ' + api_key,
'Content-Type': 'application/json'
}),
body: JSON.stringify({
_id: id
})
});
}
Insert cell
Insert cell
Insert cell
Insert cell
all_pageviews = {
const query = await fetch(db + '_all_docs', {
headers: new Headers({
Authorization: 'Basic ' + api_key
})
});
const { rows } = await query.json();
return rows;
}
Insert cell
Insert cell
async function queryPageviews(notebooks = [html`<a href>`.href]) {
const { rows } = await fetch(
db + '_design/pageviews/_view/by_url?group=true',
{
headers: new Headers({
Authorization: 'Basic ' + api_key
})
}
).then(res => res.json());
// we are deliberately not using the indexOf method, as sometimes notebooks are appended with
// querystrings or notebook collection attributes that we would like to ignore
return rows.filter(r => notebooks.find(n => r.key.includes(n)));
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more