Create an API-based Chart
Please be sure of your agent type and version and pick the right documentation accordingly.
This is the documentation of the forest-express-sequelize
and forest-express-mongoose
Node.js agents that will soon reach end-of-support.
forest-express-sequelize
v9 and forest-express-mongoose
v9 are replaced by @forestadmin/agent
v1.
Please check your agent type and version and read on or switch to the right documentation.
Create an API-based Chart
Creating an API-based Chart
Sometimes, charts data are complicated and closely tied to your business. Forest Admin allows you to code how the chart is computed. Choose API as the data source when configuring your chart.

Forest Admin will make the HTTP call to Smart Chart URL when retrieving the chart values for the rendering.
Value API-based Chart
On our Live Demo, we have a MRR
value chart which computes our Monthly Recurring Revenue. This chart queries the Stripe API to get all charges made in the current month (in March for this example).
When serializing the data, we use the Liana.StatSerializer()
serializer. Check the value
syntax below.
{ value: <number> }
const P = require('bluebird');
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-sequelize');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const moment = require('moment');
...
router.post('/stats/mrr', (req, res) => {
let mrr = 0;
let from = moment.utc('2018-03-01').unix();
let to = moment.utc('2018-03-31').unix();
return stripe.charges
.list({
created: { gte: from, lte: to }
})
.then((response) => {
return P.each(response.data, (charge) => {
mrr += charge.amount;
});
})
.then(() => {
let json = new Liana.StatSerializer({
value: mrr
}).perform();
res.send(json);
});
});
...
module.exports = router;

Repartition API-based Chart
On our Live Demo, we have a Charges
repartition chart which shows a repartition chart distributed by credit card country. This chart queries the Stripe API to get all charges made in the current month (in March for this example) and check the credit card country.
When serializing the data, we use the Liana.StatSerializer()
serializer. Check the value
syntax below.
{
value: [{
key: <string> ,
value: <number>
}, {
key: <string> ,
value: <number>
}, …]
}
const _ = require('lodash');
const P = require('bluebird');
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-sequelize');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const moment = require('moment');
router.post(
'/stats/credit-card-country-repartition',
Liana.ensureAuthenticated,
(req, res) => {
let repartition = [];
let from = moment.utc('2018-03-01').unix();
let to = moment.utc('2018-03-20').unix();
return stripe.charges
.list({
created: { gte: from, lte: to },
})
.then((response) => {
return P.each(response.data, (charge) => {
let country = charge.source.country || 'Others';
let entry = _.find(repartition, { key: country });
if (!entry) {
repartition.push({ key: country, value: 1 });
} else {
entry.value++;
}
});
})
.then(() => {
let json = new Liana.StatSerializer({
value: repartition,
}).perform();
res.send(json);
});
}
);
module.exports = router;

Time-based API-based Chart
On our Live Demo, we have a Charges
time-based chart which shows the number of charges per day. This chart queries the Stripe API to get all charges made in the current month (in March for this example) and group data by day.
When serializing the data, we use the Liana.StatSerializer()
serializer. Check the value
syntax below.
{
value: [{
label: <string> ,
values: { value: <number> }
}, {
label: <string> ,
values: { value: <number> }
}, …]
}
const _ = require('lodash');
const P = require('bluebird');
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-sequelize');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const moment = require('moment');
router.post('/stats/charges-per-day', (req, res) => {
let values = [];
let from = moment.utc('2018-03-01').unix();
let to = moment.utc('2018-03-31').unix();
return stripe.charges
.list({
created: { gte: from, lte: to },
})
.then((response) => {
return P.each(response.data, (charge) => {
let date = moment.unix(charge.created).startOf('day').format('LLL');
let entry = _.find(values, { label: date });
if (!entry) {
values.push({ label: date, values: { value: 1 } });
} else {
entry.values.value++;
}
});
})
.then(() => {
let json = new Liana.StatSerializer({
value: values,
}).perform();
res.send(json);
});
});
module.exports = router;

Objective API-based Chart
Creating an Objective Smart Chart means you'll be fetching your data from an external API endpoint:

This endpoint must return data with the following format:
{
value: {
value: xxxx,
objective: yyyy
}
}
Here's how you could implement it:
// [...]
const Liana = require('forest-express-sequelize');
// [...]
router.post('/stats/some-objective', (req, res) => {
// fetch your data here (a promise must be returned)
.then(() => {
let json = new Liana.StatSerializer({
value: {
value: fetchedValue,
objective: fetchedObjective
}
}).perform();
res.send(json);
}
}
Last updated
Was this helpful?