keen-analysis.js
A JavaScript Client for Keen.
Installation
Install this package from NPM Recommended
npm install keen-analysis --save
Public CDN
<script crossorigin src="https://cdn.jsdelivr.net/npm/keen-analysis@3/dist/keen-analysis.min.js"></script>
Project ID & API Keys
Login to Keen IO to create a project and grab the Project ID and Read Key from your project's Access page.
To run keen-analysis on your localhost you need to grab your access keys and update config.js
file.
const demoConfig = {
projectId: 'YOUR_PROJECT_ID',
readKey: 'YOUR_READ_KEY',
writeKey: 'YOUR_WRITE_KEY',
masterKey: 'YOUR_MASTER_KEY',
};
Getting started
The following examples demonstrate how to get up and running quickly with our API. This SDK can also contains basic HTTP wrappers that can be used to interact with every part of our platform.
If any of this is confusing, join our Slack community or send us a message.
Looking for tracking capabilities? Check out keen-tracking.js.
Upgrading from an earlier version of keen-js? Read this.
Setup and Running a Query
Create a new client
instance with your Project ID and Read Key, and use the .query()
method to execute an ad-hoc query. This client instance is the core of the library and will be required for all API-related functionality.
import KeenAnalysis from 'keen-analysis';
const client = new KeenAnalysis({
projectId: 'YOUR_PROJECT_ID',
readKey: 'YOUR_READ_KEY'
});
client
.query({
analysisType: 'count',
eventCollection: 'pageviews',
timeframe: 'this_31_days'
})
.then(res => {
})
.catch(err => {
});
Important: the res
response object returned in the example above will also include a query
object containing the analysis_type
and query parameters shaping the request. This query information is artificially appended to the response by this SDK, as this information is currently only provided by the API for saved queries. Why? Query parameters are extremely useful for intelligent response handling downstream, particularly by our own automagical visualization capabilities in keen-dataviz.js.
Async Await example
const getPageviews = async () => {
try {
const result = await client
.query({
analysisType: 'count',
eventCollection: 'pageviews',
timeframe: 'this_31_days'
});
console.log('Result', result);
return result;
} catch (error) {
console.log('Error', error);
}
}
Cache queries in the client
Client-side (browser) caching is based on IndexedDB API.
import KeenAnalysis from 'keen-analysis';
const client = new KeenAnalysis({
projectId: 'YOUR_PROJECT_ID',
masterKey: 'YOUR_MASTER_KEY',
cache: {
maxAge: 60 * 1000
}
});
client
.query({
analysisType: 'count',
eventCollection: 'pageviews',
timeframe: 'this_31_days',
cache: {
maxAge: 10 * 1000
}
})
.then(res => {
})
.catch(err => {
});
client
.query({
analysisType: 'count',
eventCollection: 'pageviews',
timeframe: 'this_14_days',
cache: false
})
.then(res => {
})
.catch(err => {
});
Local Queries
The Local Query Experimental Feature allows you to run queries on already
browser-side-cached or file-stored data.
This feature is available only in the NPM version of the library.
Local Query on the browser cache
import KeenAnalysis from 'keen-analysis';
import localQuery from 'keen-analysis/dist/modules/localQuery';
client
.query({
analysisType: 'extraction',
eventCollection: 'pageviews',
timeframe: 'this_30_days',
cache: {
maxAge: 1000 * 60 * 60 * 24
}
})
.then(responseJSON => {
localQuery({
data: responseJSON,
analysisType: 'count',
timeframe: 'this_7_days',
debug: true
})
.then(localQueryResponseJSON => {
})
.catch(localQueryError => {
console.log(localQueryError);
});
});
Local Query on the file
import localQuery from 'keen-analysis/dist/modules/localQuery';
localQuery({
file: 'dummy-data.csv',
analysisType: 'count',
timeframe: 'this_14_days'
})
.then(localQueryResponseJSON => {
})
.catch(localQueryError => {
});
The Local Query configuration
localQuery({
data: responseJSON,
file: 'dummy-data.csv',
analysisType: 'count',
timeframe: 'this_7_days',
debug: true,
onOutOfTimeframeRange: () => {},
})
.then(localQueryResponseJSON => {
})
.catch(localQueryError => {
});
Local Query in the Node.js environment
const KeenAnalysis = require('keen-analysis');
const localQuery = require('keen-analysis/dist/node/modules/localQuery').default;
Create a Saved Query
API reference: Saved Query
import KeenAnalysis from 'keen-analysis';
const client = new KeenAnalysis({
projectId: 'YOUR_PROJECT_ID',
masterKey: 'YOUR_MASTER_KEY'
});
client
.put({
url: client.url('queries', 'saved', 'daily-pageviews-this-14-days'),
api_key: client.config.masterKey,
params: {
refreshRate: 60 * 60 * 4,
query: {
analysisType: 'count',
eventCollection: 'pageviews',
timeframe: 'this_14_days'
},
metadata: {
displayName: 'Daily pageviews (this 14 days)',
visualization: {
chartType: "metric"
}
}
}
})
.then(res => {
})
.catch(err => {
});
Read Saved/Cached Queries
import KeenAnalysis from 'keen-analysis';
const client = new KeenAnalysis({
projectId: 'YOUR_PROJECT_ID',
readKey: 'YOUR_READ_KEY'
});
client
.query({
savedQueryName: 'pageviews-this-14-days'
})
.then(res => {
})
.catch(err => {
});
List Saved Queries
import KeenAnalysis from 'keen-analysis';
const client = new KeenAnalysis({
projectId: 'YOUR_PROJECT_ID',
masterKey: 'YOUR_MASTER_KEY'
});
client
.get({
url: client.url('queries', 'saved'),
api_key: client.config.masterKey
})
.then(res => {
})
.catch(err => {
});
Create Cached Datasets
import KeenAnalysis from 'keen-analysis';
const client = new KeenAnalysis({
projectId: 'PROJECT_ID',
masterKey: 'MASTER_KEY'
});
const newDatasetName = 'my-first-dataset';
client
.put({
url: client.url('datasets', newDatasetName),
api_key: client.config.masterKey,
params: {
displayName: 'Count Daily Product Purchases Over $100 by Country',
query: {
analysisType: 'count',
eventCollection: 'purchases',
filters: [
{
propertyName: 'price',
operator: 'gte',
propertyValue: 100
}
],
groupBy: 'ip_geo_info.country',
interval: 'daily',
timeframe: 'this_500_days'
},
indexBy: 'product.id'
}
})
.then(res => {
console.log('res', res);
})
.catch(err => {
});
Read Cached Datasets
import KeenAnalysis from 'keen-analysis';
const client = new KeenAnalysis({
projectId: 'YOUR_PROJECT_ID',
readKey: 'YOUR_READ_KEY'
});
client
.query({
datasetName: 'my-cached-dataset',
indexBy: 'customer.id',
timeframe: 'this_7_days'
})
.then(res => {
})
.catch(err => {
});
Cancel query
import KeenAnalysis from 'keen-analysis';
const client = new KeenAnalysis({
projectId: 'YOUR_PROJECT_ID',
readKey: 'YOUR_READ_KEY'
});
const queryPageviews = client.query({
analysisType: 'count',
eventCollection: 'pageviews',
timeframe: 'this_31_days'
});
queryPageviews.abort();
Timeout of the queries
Fetch API doesn't support timeout, but we can fix that
import KeenAnalysis from 'keen-analysis';
const client = new KeenAnalysis({
projectId: 'YOUR_PROJECT_ID',
readKey: 'YOUR_READ_KEY'
});
const queryPageviews = client.query({
analysisType: 'count',
eventCollection: 'pageviews',
timeframe: 'this_31_days'
});
setTimeout(() => {
queryPageviews.abort();
}, 1000 * 10);
queryPageviews
.then(res => {
console.log('response', res);
})
.catch(err => {
console.log('error', err);
});
Running multiple queries at once
client.run()
will Promise.all
array of queries.
Please note, that in general, we recommend running queries independently of each other.
This example is useful if you are rendering many results on one Keen-dataviz.js chart object.
import KeenAnalysis from 'keen-analysis';
const client = new KeenAnalysis({
projectId: 'YOUR_PROJECT_ID',
readKey: 'YOUR_READ_KEY'
});
const queryPageviews = client.query({
analysisType: 'count',
eventCollection: 'pageviews',
timeframe: 'this_14_days'
});
const queryFormSubmissions = client.query({
analysisType: 'count',
eventCollection: 'form_submissions',
timeframe: 'this_14_days'
});
client
.run([queryPageviews, queryFormSubmissions])
.then(res => {
})
.catch(err => {
});
Parsing query results
resultParsers
is an array of functions and the response from API will be parsed by each function.
import KeenAnalysis from 'keen-analysis';
const client = new KeenAnalysis({
projectId: 'YOUR_PROJECT_ID',
readKey: 'YOUR_READ_KEY',
resultParsers: [
(value) => {
return Math.round(value);
}
]
});
client.query({
analysisType: 'count',
eventCollection: 'pageviews',
timeframe: 'this_3_months'
})
.then(res => {
})
.catch(err => {
});
Optimise queries
Read the execution metadata to optimise queries and reduce your bill.
client.query({
analysisType: 'count',
eventCollection: 'pageviews',
timeframe: 'this_3_months',
includeMetadata: true
})
.then(res => {
})
.catch(err => {
});
For multiple queries you can define includeMetadata
in client constructor and this will be propagated to all queries.
import KeenAnalysis from 'keen-analysis';
const client = new KeenAnalysis({
projectId: 'YOUR_PROJECT_ID',
readKey: 'YOUR_READ_KEY',
includeMetadata: true,
});
Custom Host
You can set a custom domain for requests
const client = new KeenAnalysis({
projectId: 'PROJECT_ID',
readKey: 'YOUR_READ_KEY',
host: 'somehost.com'
});
Client instance methods
The following HTTP methods are exposed on the client instance:
.get(object)
.post(object)
.put(object)
.del(object)
These HTTP methods take a single argument and return a promise for the asynchronous response.
CamelCase conversion
All of the parameters provided in the camelCase format will be automatically converted into an API-digestible under_score format.
Upgrading from keen-js
There are several breaking changes from earlier versions of keen-js.
- All new HTTP methods: keen-js supports generic HTTP methods (
.get()
, .post()
, .put()
, and .del()
) for interacting with various API resources. The new Promise-backed design of this SDK necessitated a full rethinking of how these methods behave. Keen.Request
object has been removed: this object is no longer necessary for managing query requests.- Redesigned implementation of
client.url()
: This method previously included https://api.keen.io/3.0/projects/PROJECT_ID
plus a path
argument ('/events/whatever'). This design severely limited its utility, so we've revamped this method.
This method now references an internal collection of resource paths, and constructs URLs using client configuration properties like host
and projectId
:
const url = client.url('projectId');
Default resources:
- 'base': '
{protocol}
://{host}
', - 'version': '
{protocol}
://{host}
/3.0', - 'projects': '
{protocol}
://{host}
/3.0/projects', - 'projectId': '
{protocol}
://{host}
/3.0/projects/{projectId}
', - 'queries': '
{protocol}
://{host}
/3.0/projects/{projectId}
/queries' - 'datasets': '
{protocol}
://{host}
/3.0/projects/{projectId}
/datasets'
Non-matching strings will be appended to the base
resource, like so:
const url = client.url('/3.0/projects');
You can also pass in an object to append a serialized query string to the result, like so:
const url = client.url('events', { api_key: 'YOUR_API_KEY' });
Resources can be returned or added with the client.resources()
method, like so:
client.resources()
client.resources({
'new': '{protocol}://analytics.mydomain.com/my-custom-endpoint/{projectId}'
});
client.url('new');
Contributing
This is an open source project and we love involvement from the community! Hit us up with pull requests and issues.
Learn more about contributing to this project.
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:
Custom builds
Run the following commands to install and build this project:
# Clone the repo
$ git clone https://github.com/keen/keen-analysis.js.git && cd keen-analysis.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