Integration
In order to embed a chart, your application’s source code needs to be updated based on the below steps.
Server-side (backend)
Step 1 - Create a Secure Session with Zing
A secure session needs to be created with Zing in order to start embedding charts/dashboards. This should be done by calling the API:
POST https://console.getzingdata.com/api/v1/embed-sessions
An example of how to create a Zing session using NodeJS:
const url = 'https://console.getzingdata.com/api/v1/embed-sessions';
const payload = {
userData: {
email: loggedInUserEmail,
},
};
const options = {
headers: {
'Content-Type': 'application/json',
'x-zingdata-api': ZING_API_KEY,
},
};
const response = await axios.post(url, payload, options);
const oneTimeSessionToken = response.data.token;
This token created by the backend will need to be passed to the frontend for your end user to be able to view an embedded chart. You can expose an API from your backend for the frontend to fetch this token for each chart that you embed. A session token needs to be created for every chart you want to embed.
Step 2 - Generate Signed Embed URL
You can create signed one-time-use URLs for graphs/dashboards, which are more secure because they can’t be reused and are a way to ensure your server has validated each request. In order to generate the signed URL, add a new API endpoint in your server code.
A NodeJS example for this API endpoint is given below.
const crypto = require('crypto');
const uuid = require('uuid');
app.post('/api/generate-url', (req, res) => {
const { embedId, where } = req.body;
const baseUrl = 'https://console.getzingdata.com/embeds';
let parameters = `?nonce=${uuid.v4()}`;
parameters += `×tamp=${Math.floor(new Date().getTime() / 1000)}`;
parameters += `&embedId=${embedId}`;
if (where) {
parameters += `&where=${where}`;
}
const urlWithParameters = baseUrl + parameters;
const signature = crypto
.createHmac('sha256', Buffer.from(process.env.ZING_EMBED_SECRET, 'utf8'))
.update(Buffer.from(urlWithParameters, 'utf8'))
.digest('hex');
const finalUrl = `${urlWithParameters}&signature=${signature}`;
res.json({ url: finalUrl });
});
In here, the ZING_EMBED_SECRET is read from an environment variable.
Now let’s move on to the frontend updates.
Client-side (frontend)
-
Contact the Zing team and obtain the Zing key (REACT_APP_ZING_KEY).
-
Install the Zing SDK on your application’s front-end.
From NPM:
npm install --save @zingdata/zingdata-react
- Import the Zing CSS file in your main HTML or CSS file.
import "@zingdata/zingdata-react/dist/zing.css";
-
Call the API endpoint that you defined in your backend to fetch the Zing session token for each chart (E.g: zingToken).
-
Call the API endpoint that you defined in your backend to generate the signed embed URL for each chart.
- Payload should contain the embedId of the question and the where property (If dynamic filtering is required - where property is optional. More information about the where condition is given at the end of this guide.)
- This should be done for each embedded chart/dashboard in your application, as each chart/dashboard will have an immutable URL.
const fetchUrl = async (embedId, where) => {
const result = await axios.post(
'/api/generate-url',
{
embedId: embedId,
where: where,
},
{
headers: {
'Content-Type': 'application/json',
},
}
);
return result?.data?.url;
};
// Call the above function to fetch the generated URL
const signedUrl = await fetchUrl(embedId, where);
- Embed the chart using the SDK
Include the below code on the page where the chart/dashboard needs to be rendered.
import { ZingDataEmbed } from '@zingdata/zingdata-react';
<ZingDataEmbed
embedUrl={signedUrl}
apiKey={process.env.REACT_APP_ZING_API_KEY}
token={zingToken}
zingKey={process.env.REACT_APP_ZING_KEY}
className="mt-5" // optional
/>
- An optional className parameter can be passed to ZingDataEmbed if you need any custom styles to be applied to the container.
- embedUrl, token and apiKey properties are required.
- A question can be filtered from your application’s source code by adding a chart property: where. For instance, you could filter based on city, company, or any other field in your datasource to customize the chart to a specific context. The example below shows filtering based on the city.
where={JSON.stringify({
queryConstruct: {
where: [{
column: ['Prospect City'],
condition: '!=',
values: 'Boston'
}]
}
})}
This condition needs to be passed to the fetchUrl function in step 3 to be included in the signed URL.
Multiple conditions can be added to the where property as follows.
where={JSON.stringify({
queryConstruct: {
where: [
{
column: ['Prospect City'],
condition: '!=',
values: 'Boston'
},
{
column: ['Year'],
condition: '=',
values: '2023'
},
]
}
})}
The where property can have the following conditions.
- Equals (=) only returns results which match the value you input (e.g. “City = ‘New York’” will return results only where the city field for that row equals New York).
- Does Not Equal (!=) returns results which do not match the value you input (e.g. “City != ‘New York’” would return all cities except New York).
- Greater than (>) returns results which are greater than the value you input.
- Greater than or equal (>=) returns results which are greater than or equal to the value you input.
- Less than (<) returns results which are less than the value you input.
- Less than or equal (<=) returns results which are less than or equal to the value you input.
- Between (between) returns results which are between the two values you specify. For date fields this will be two dates.
- Includes (includes) returns results which include part or all of the value you input. For instance “City includes ‘San’” would return “San Francisco” and “San Diego” if those values are present in the data.
- Excludes (excludes) returns results which do not include any of the value you input. For instance “City excludes ‘San’” would return all cities which do not contain “San” in their name so “New York” and “Boston” would be part of the result set, but “San Diego” and “San Francisco” would not.
where conditions should not be defined for user specific data.
- Multiple charts/tables/dashboards can be embedded by using an embed ID for each chart/table/dashboard.