This the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Embedded Analytics

Zing Data’s embedded analytics capability lets you embed charts, tables, and interactive querying capabilities within your app or website with just a few lines of code.

Embed Zing’s powerful data visualization and querying capabilities in your own application.

Note: Embedded analytics is available only on the Pro tier, and must be enabled for your account by the Zing team - it is not enabled by default.

Reach out to the Zing team to see a demo and learn more about pricing.

Capabilities

Zing charts, tables, and interactive querying functionality can be embedded in your app via Zing’s React SDK.

Providing users embedded analytics can:

  • Improve user retention
  • Help users understand their usage of your product and drive upgrades
  • Compare performance to peers (e.g. conversion rate compared to peers in a segment)
  • Create new revenue sources (such as offering advanced analytics and reporting functionality as an add-on)

Zing’s React SDK allows developers to get up and running with rich charting, querying, and visualization capabilities without having to maintain complex data architecture, or build visualizations from scratch.

Benefit from Zing’s robust data analysis and querying capabilities and get up and running in minutes:
* Easy visual querying
* Natural language based querying
* SQL typehead for power users
* Flexible graph formatting (including specifying colors, date formatting, sorting, and more)
* Export to PNG or CSV

When you’re setting up embedded analytics you can control the features you want to show up on the embeds.

For example, if you want to disallow exporting as a PNG, you can simply turn off that capability in the admin panel and no user will have that option from the embed.

Update frequency

Choose refresh frequency to optimize data freshness while minimizing database load.

Update frequency options include:

  • Full-live
  • Every minute
  • Every 5 minutes
  • Every 15 minutes
  • Every 30 minutes
  • Every hour

Authentication and data visibility

  • Inherit user access controls from your app if you’d like to customize end-user experiences based on user id, role, entitlement, or other attributes
  • Limit chart visibility to verified sessions for improved security
  • Apply chart-level controls

Getting Started

Zing’s embeds also support secure authentication using a Single Sign On provider, session-based authentication, and row level security. Speak to our team to learn more.

1 - Setup and Preparation

Create required keys and tokens for embedding.
  1. Visit the Zing console and click on Organizations.
  2. The organization that has embeds enabled will have a “Pro” badge.
  3. Click on Settings for the organization and click on the Embeds tab.
  4. Generate an API key for your organization (E.g.: 7bf7aa96-dee0-4750-b97c-3bd13864de81).
    • This API key will be used to authorize the organization for embedded charts/tables.
    • Along with the API key, an embed secret will be generated for you which will be used to create an immutable signed URL for your embeds.
    • Make sure you don’t expose the API Key or the Embed Secret publicly as this will be used to authenticate your organization.
  5. Admins of the organization will have the ability to create multiple API keys per organization and activate/deactivate an API key anytime.
  6. Create your questions on the Zing Web App or Mobile App.
  7. To generate an embed ID for a question, click on the three dot menu for a saved question and click on Embed Options.
  8. All questions embed IDs were generated for, will appear under the Embeds tab on the organization page of the Zing console.
  9. Embed IDs can be enabled and disabled when required.

2 - Integration

Install the SDK and create the signed URL required for embedding.

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. 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, 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 += `&timestamp=${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)

  1. Install the Zing SDK on your application’s front-end.

From NPM:

npm install --save @zingdata/zingdata-react
  1. Import the Zing CSS file in your main HTML or CSS file.
import "@zingdata/zingdata-react/dist/zing.css";
  1. Call the API endpoint that you defined in your backend to fetch the Zing session token for each chart (E.g: zingToken).

  2. 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 in your application, as each chart 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);
  1. Embed the chart using the SDK

Include the below code on the page where the chart needs to be rendered.

import { ZingDataChart } from '@zingdata/zingdata-react';

<ZingDataChart
  embedUrl={signedUrl}
  apiKey={process.env.REACT_APP_ZING_API_KEY}
  token={zingToken}
  className="mt-5"
/>
  • An optional className parameter can be passed to ZingDataChart if you need any custom styles to be applied to the container.
  • embedUrl, token and apiKey properties are required.
  1. The 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.

  1. Multiple charts/tables can be embedded by using an embed ID for each chart/table.

3 - Row Level Security for Embedded Charts

Filter your chart based on who views it.

Row Level Security allows you to control access to data in a database by row, so that a logged in user can only view the data they are authorized for. You will be able to control “Who sees what in the chart?” by including a RLS filter to the question.

Steps

  1. Ask a question via the Zing Web App or Mobile App with a Row Level Security filter. Refer this guide for more information on how to create a question with an RLS filter.
  2. Embed the chart by following the steps under the Setup and Preparation and the Integration sections.
  3. Send the logged in user’s data when creating a session with Zing via your backend code. The information sent in the payload will be used for RLS filtering.

An example of how to create a session token in NodeJS is shown below.

const url = 'https://console.getzingdata.com/api/v1/embed-sessions';

const payload = {
 userData: {
  email: loggedInUserEmail,
  role: loggedInUserRole,
  username: loggedInUserUsername,
  name: loggedInUserName,
 },
};

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;

How to use this one-time token is explained in the Integration steps.

That’s it. 🎉

The resulting chart for a query with RLS filtering will have different results based on the logged in user in your application. By excluding certain data from the dataset based on the logged in user would reduce access of data by users who are unauthorized to view them.