keen-dataviz.js
A JavaScript data visualization library for Keen.
Install with NPM
npm install keen-dataviz --save
Live Demos
Chart types
Built-in themes and color palettes
Custom CSS theme builder
https://github.com/keen/theme-builder -
Live Demo
Example
import KeenDataviz from 'keen-dataviz';
import KeenAnalysis from 'keen-analysis';
import 'keen-dataviz/dist/keen-dataviz.css';
const chart = new KeenDataviz({
container: '#my-chart-div',
title: 'New Customers per Week',
subtitle: 'chart subtitle',
});
const client = new KeenAnalysis({
projectId: 'YOUR_PROJECT_ID',
readKey: 'YOUR_READ_KEY'
});
client
.query({
analysisType: 'count',
eventCollection: 'pageviews',
timeframe: 'this_7_days',
interval: 'daily'
})
.then(results => {
chart
.render(results);
})
.catch(error => {
chart
.message(error.message);
});
React Component
https://github.com/keen/keen-react-charts
Webpack boilerplate
https://github.com/keen/keen-dataviz-webpack-boilerplate
Install with CDN
Include keen-dataviz.js and keen-dataviz.css within your page or project.
<html>
<head>
<meta charset="utf-8">
<script crossorigin src="https://cdn.jsdelivr.net/npm/keen-analysis@3"></script>
<link href="https://cdn.jsdelivr.net/npm/keen-dataviz@3/dist/keen-dataviz.min.css" rel="stylesheet" />
<script crossorigin src="https://cdn.jsdelivr.net/npm/keen-dataviz@3/dist/keen-dataviz.min.js"></script>
</head>
<body>
<div id="some_container"></div>
<style>
#some_container {
width: 400px;
height: 250px;
}
</style>
<script>
const chart = new KeenDataviz({
container: '#some_container',
title: 'New Customers per Week'
});
const client = new KeenAnalysis({
projectId: 'YOUR_PROJECT_ID',
readKey: 'YOUR_READ_KEY'
});
client
.query({
analysisType: 'count',
eventCollection: 'pageviews',
timeframe: 'this_14_days',
interval: 'daily'
})
.then(function(results){
chart
.render(results);
})
.catch(function(error){
chart
.message(error.message);
});
</script>
</body>
</html>
Configuration
Chart type
Specify the visualization type. If no type is set, the library will automatically set the best option.
Full list of the supported chart types
const chart = new KeenDataviz({
container: '#some_container',
type: 'area'
});
Date Format
Date formatting is possible by passing either a string or function to dateFormat
. In either case, this value will be set as the axis.x.tick.format
configuration property. As a built-in feature of C3.js, functions are used as an iterator, receiving the date for each interval in milliseconds.
const chart = new KeenDataviz({
container: '#some_container',
dateFormat: '%Y-%m'
});
const chart = new KeenDataviz({
container: '#some_container',
dateFormat: function(ms){
const date = new Date(ms);
return date.getFullYear();
}
});
Date Localization: Dates will be localized to the browser's timezone by default. This is generally desirable, but there are some instances where you may wish to retain the timezones that are returned by the API. You can disable this behavior in any C3.js-based visualization by setting axis.x.localtime
to false
:
const chart = new KeenDataviz({
container: '#some_container',
axis: {
x: {
localtime: false
}
}
});
Multiple query results on one chart
const client = new KeenAnalysis({
projectId: 'YOUR_PROJECT_ID',
readKey: 'YOUR_READ_KEY'
});
const queryPageviews = client
.query({
analysisType: 'count',
eventCollection: 'pageviews',
timeframe: 'this_30_days',
interval: 'daily'
});
const queryFormSubmissions = client
.query({
analysisType: 'count',
eventCollection: 'form_submissions',
timeframe: 'this_30_days',
interval: 'daily'
});
client
.run([queryPageviews, queryFormSubmissions])
.then(results => {
const chart = new KeenDataviz({
container: '#some_container',
results,
labelMapping: {
'pageviews count': 'Pageviews',
'form_submissions count': 'Forms collected'
}
});
})
.catch(err => {
console.error(err);
});
Refresh every 1 minute
const chart = new KeenDataviz({
container: '#some_container',
clearOnRender: true,
transition: {
duration: 0
}
});
const fetchResultsAndRender = () => {
client
.query({
analysisType: 'count',
eventCollection: 'pageviews',
timeframe: 'previous_60_minutes',
interval: 'minutely'
})
.then(results => {
chart.render(results);
});
};
const intervalTime = 60 * 1000;
setInterval( () => {
fetchResultsAndRender();
}, intervalTime);
fetchResultsAndRender();
C3 options
All of the options are passed to C3. See https://c3js.org/reference.html
const chart = new KeenDataviz({
container: '#some_container',
axis: {
x: {
localtime: false
}
},
transition: {
duration: 3000
},
zoom: {
enabled: true
},
grid: {
x: {
show: true
},
y: {
show: true
}
},
size: {
},
onrendered: () => {
}
});
Hide the Title
const chart = new KeenDataviz({
container: '#some_container',
title: false
});
Legend
const chart = new KeenDataviz({
container: '#some_container',
legend: {
show: true,
position: 'right',
alignment: 'center',
label: {
textMaxLength: 12
},
pagination: {
offset: 0,
limit: 5
},
tooltip: {
show: true,
pointer: true
},
}
});
Legend sort
Default method of sorting is by column name ASC. You can use your own sorting function
const chart = new KeenDataviz({
container: '#some_container',
legend: {
show: true,
position: 'right',
sort: function (columns) {
const columnsSorted = [];
columns.forEach(column => {
if (column[0] !== 'x') {
let sumOfValues = column.slice(1).reduce((acc = 0, item) => {
return acc + item;
});
columnsSorted.push({ columnName: column[0], columnSum: sumOfValues});
}
});
columnsSorted.sort(function(a, b) {
return b.columnSum - a.columnSum;
});
return columnsSorted.map(item => item.columnName);
}
}
});
Custom colors
const chart = new KeenDataviz({
container: '#some_container',
colors: ['#1167c5', 'green', '#000000']
});
Color Palettes
const chart = new KeenDataviz({
container: '#some_container',
palette: 'autocollector'
});
Color mapping
const chart = new KeenDataviz({
container: '#some_container',
colorMapping: {
'some_label_1': '#c51111',
'some_label_2': '#11c53b'
}
});
Label mapping
const chart = new KeenDataviz({
container: '#some_container',
labelMapping: {
'long_complex_key_name': 'Human readable label',
}
});
Label mapping RegExp
const chart = new KeenDataviz({
container: '#some_container',
labelMappingRegExp: [
[/anytext/, 'Purchases'],
[/lorem ipsum/gi, 'Visits']
]
});
Label mapping dimensions: Column, Row, Both
const chart = new KeenDataviz({
container: '#some_container',
labelMapping: {
'long_complex_key_name': 'Human readable label',
},
labelMappingDimension: 'column'
});
Error mapping
const chart = new KeenDataviz({
container: '#some_container',
errorMapping: {
'No data to display': 'my custom message 123'
}
});
Hide error messages
const chart = new KeenDataviz({
container: '#some_container',
showErrorMessages: false
});
Custom labels for funnels
const chart = new KeenDataviz({
container: '#some_container',
labels: [
'Step 1',
'Step 2',
'Step 3'
]
});
Render results
By default you can pass results with a configuration object
const client = new KeenAnalysis({
projectId: 'YOUR_PROJECT_ID',
readKey: 'YOUR_READ_KEY'
});
client
.query({
analysisType: 'count',
eventCollection: 'pageviews',
timeframe: 'this_160_days'
})
.then(results => {
const chart = new KeenDataviz({
container: '#some_container',
results
});
})
.catch(err => {
});
The same, but with render function:
const chart = new KeenDataviz({
container: '#some_container',
showLoadingSpinner: true
});
const client = new KeenAnalysis({
projectId: 'YOUR_PROJECT_ID',
readKey: 'YOUR_READ_KEY'
});
client
.query({
analysisType: 'count',
eventCollection: 'pageviews',
timeframe: 'this_30_days'
})
.then(results => {
chart.render(results);
})
.catch(err => {
});
Render as a Promise
const chart = new KeenDataviz({
container: '#some_container',
renderAsPromise: true
});
chart
.render(results)
.then({
})
.catch(err => {
});
Loading spinner animation (aka prepare())
Long query response time? Use a loading spinner to let users know, that data is loading.
const chart = new KeenDataviz({
container: '#some_container',
showLoadingSpinner: true
});
const client = new KeenAnalysis({
projectId: 'YOUR_PROJECT_ID',
readKey: 'YOUR_READ_KEY'
});
client
.query({
analysisType: 'count',
eventCollection: 'pageviews',
timeframe: 'this_160_days'
})
.then(results => {
chart.render(results);
})
.catch(err => {
});
Sort groups
Determine how groupBy results are sorted (asc
for ascending, desc
for descending).
const chart = new KeenDataviz({
container: '#some_container',
sortGroups: 'asc'
});
Sort intervals
Determine how interval results are sorted (asc
for ascending, desc
for descending).
const chart = new KeenDataviz({
container: '#some_container',
sortIntervals: 'desc'
});
Stacked chart
Create a stacked chart, used to break down and compare parts of a whole.
const chart = new KeenDataviz({
container: '#some_container',
stacking: 'normal'
});
Sparkline chart
Create chart without axis, grid and legend
const chart = new KeenDataviz({
container: '#some_container',
sparkline: true
})
Extraction Table Columns Order
const chart = new KeenDataviz({
container: '#some_container',
table: {
columns: ['favourite_fruit', 'user.email', 'keen.created_at']
}
});
const chart = new KeenDataviz({
container: '#some_container',
table: {
pagination: {
limit: 10
}
}
});
Custom data parser
const chart = new KeenDataviz({
container: '#some_container',
});
const result = {
'clicks': [3, 14, 7, 22, 11, 55, 11, 22],
'views': [14, 58, 11, 32, 11, 23, 45, 66]
};
function customParser(data){
const ds = new KeenDataset();
Object.keys(data).forEach(dataKey => {
ds.appendColumn(dataKey);
data[dataKey].forEach((item, itemIndex) => {
ds.set([dataKey, itemIndex+1], item);
});
});
return ds;
}
chart
.render(customParser(result));
Mapping values of a table column
const chart = new KeenDataviz({
container: '#some_container',
type: 'table',
table: {
mapValues: {
'keen.timestamp': (value) => {
return value.toUpperCase();
}
}
}
})
Chart render only when visible
const chart = new KeenDataviz({
container: '#some_container',
renderOnVisible: true
})
Partial interval visual indicator
By default, it's enabled for all charts with relative time frames starting with this_
eg. this_x_hours.
To hide it, use a configuration property:
partialIntervalIndicator: false
Deprecation warnings
You can turn off deprecation warnings with
const chart = new Keen.Dataviz({
container: '#container',
showDeprecationWarnings: false
});
Download results
You can add button to enable download results from chart.
const chart = new Keen.Dataviz({
container: '#container',
ui: {
buttons: {
download: {
label: 'Download as a JPG file',
type: 'jpg',
}
}
}
});
Save charts as JPG/PNG files
chart.exportImage();
chart.exportImage({ quality: 1, bgcolor: 'blue' });
Export data to a file
chart.exportData();
chart.exportData('csv');
Execution metadata
You can easily show execution metadata if it's available. By defualt this option is set to true.
const chart = new Keen.Dataviz({
container: '#container',
ui: {
executionMetadata: true
}
});
Copy to clipboard
By default this feature is switched on. When you click on a point on the chart the result's value is copied to clipboard. When you select a group of points then sum of their values are copied.
const chart = new Keen.Dataviz({
container: '#container',
utils: {
clickToCopyToClipboard: false,
}
});
Advanced usage:
Additional resources:
Support:
Need a hand with something? Shoot us an email at team@keen.io. We're always happy to help, or just hear what you're building! Here are a few other resources worth checking out:
Learn more about the Dataviz API
Contributing
This is an open source project and we love involvement from the community! Hit us up with pull requests and issues. The more contributions the better!
Learn about contributing to this project.
Custom builds
Run the following commands to install and build this project:
# Clone the repo
$ git clone https://github.com/keen/keen-dataviz.js.git && cd keen-dataviz.js
# Install project dependencies
$ npm install
# Build project with Webpack
$ npm run build
# Build and launch to view demo page
$ npm run start
# Run Jest tests
$ npm run test