In previous posts on the Design blog, we've explored various ways for embedding Qlik Sense analytics. These have ranged from straightforward iFrames to more complex approaches like the Capabilities API, as well as more recent tools such as Nebula.js and Enigma.js.
Today, we’re going to be taking a quick look at a new library from Qlik called qlik-embed, but before diving into it, I would like to clarify that this library is currently in public preview and at the time of writing this blog, frequent updates as well as breaking changes are prone to happen (you can read more about that on qlik.dev or follow the Changelog for updated https://qlik.dev/changelog)
So what exactly is qlik-embed?
qlik-embed is a library for easily embedding data and analytics interfaces into your web apps while overcoming some of the concerns that usually arise when embedding content from one software application to another such as third-party cookies, cross-site request forgery, content security policy etc..
The library is designed to work with web apps from simple plain HTML ones to more modern frameworks like React etc.. That is in fact made easier since whichever qlik-embed flavor you use, the configuration options, the methods, and the properties will be similar.
If you are already embedding Qlik Sense content into your web applications, you can learn about the various reasons why qlik-embed would be a better solution on qlik.dev (https://qlik.dev/embed/qlik-embed/qlik-embed-introduction#why-qlik-embed-over-capability-api-or-nebulajs)
Web Components:
qlik-embed makes use of web components which are basically custom HTML elements in the form of <qlik-embed> </qlik-embed> HTML tags that allow you to configure properties of the content you’re embedding
You can find all supported web-components here:
analytics/chart
analytics/field
analytics/selections
analytics/sheet
classic/app
How to quickly get started?
Before getting started, it’s worth noting that there are several ways to connect qlik-embed web components to Qlik.
More information about Auth can be found here:
- Connect qlik-embed:https://qlik.dev/embed/qlik-embed/connect-qlik-embed
- Best Practices:https://qlik.dev/embed/qlik-embed/qlik-embed-auth-best-practice
You can connect to qlik-embed in these ways:
Qlik Cloud API keys (cookie-less)
Qlik Cloud OAuth2 clients (cookie-less)
Qlik Cloud interactive login (cookies)
Qlik Sense Enterprise Client Managed interactive login (cookies)
None (This is a more advanced option and requires handling authenticated requests using a custom authorization backend proxy - learn more about that here: https://qlik.dev/authenticate/jwt/jwt-proxy/)
In this post, we’re going to use OAuth2 Single-page-app from the Qlik Cloud tenant Management Console under oAuth:
Example using HTML Web Components: Reference page: https://qlik.dev/embed/qlik-embed/qlik-embed-webcomponent-quickstart
First thing we need to do is add a <script> element in the <head> tag to configure the call to the qlik-embed library and set up the attributes relevant to the connection we choose.
<script
crossorigin="anonymous"
type="application/javascript"
src="https://cdn.jsdelivr.net/npm/@qlik/embed-web-components"
data-host="<QLIK_TENANT_URL>"
data-client-id="<QLIK_OAUTH2_CLIENT_ID>"
data-redirect-uri="<WEB_APP_CALLBACK_URI>"
data-access-token-storage="session"
>
</script>
data-host is the URL to your Qlik Cloud tenant. For example https://example.us.qlikcloud.com/
data-client-id is the client ID for the single-page application OAuth2 client registered for this web application.
data-redirect-uri is the location of the web page the OAuth2 client will call back to when authorization requests are made from your web application to your Qlik tenant. This web page should be added to your web application.
web-component:
<qlik-embed ui="classic/app" app-id="<APP_ID>"></qlik-embed>
oauth-callback.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script
crossorigin="anonymous"
type="application/javascript"
data-host="<QLIK_TENANT_URL>"
src="https://cdn.jsdelivr.net/npm/@qlik/embed-web-components/dist/oauth-callback.js"
></script>
</head>
</html>
You can fork the full example here and change the “Tenant URL” and the rest of the attributes to your own tenant after creating the OAuth SPA config:https://replit.com/@ouadielim/qlik-embed-HTML-Web-Components#index.html
result:
Example using React:
In React, you can use qlik’s embed-react library package: npm install @qlik/embed-react (https://www.npmjs.com/package/@qlik/embed-react)
Then, you can import QlikEmbed and QlikEmbedConfig from @qlik/embed-react.React’s context is used to pass in the hostConfig that you configure to point to your Qlik Cloud Tenant (host) and use the OAuth 2 config (clientId). The redirect URI needs to point to a page which is similar to what we did above in HTML web components.
import { QlikEmbed, QlikEmbedConfig } from "@qlik/embed-react";
const hostConfig = {
host: "<QLIK_CLOUD_TENANT>",
clientId: "<CLIENT_ID>",
redirectUri: "https://localhost:5173/oauth-callback.html",
accessTokenStorage: "session",
authType: "Oauth2",
};
const appId = "<APP_ID>";
const sheetId = ""; // sheet id or empty string
export default () => (
<QlikEmbedConfig.Provider value={hostConfig}>
<div className="container">
<h1>Qlik Embed with React</h1>
<div className="selections-bar">
<QlikEmbed ui="analytics/selections" appId={appId} />
</div>
<div className="viz">
<QlikEmbed ui="classic/app" app={appId} sheet={sheetId} />
</div>
<div className="viz">
<QlikEmbed ui="analytics/chart" appId={appId} objectId="hRZaKk" />
</div>
</div>
</QlikEmbedConfig.Provider>
);
You can clone the full React example here:https://github.com/ouadie-limouni/qlik-embed-react
result:
Limitations ?
There are a few limitations to qlik-embed as it continues to develop into a more stable and robust library - you can read more about those on qlik.dev:https://qlik.dev/embed/qlik-embed/qlik-embed-limitations
Like I mentioned at the very beginning, qlik-embed is new and evolving quickly, I invite you to test it to get familiar with it early and stay tuned for more updates and bug fixes as they come out using the Changelog page.
I hope you found this post helpful, please let me know in the comments below if you have any questions!
Thanks- Ouadie
...View More
What if you could prepare data (join, transform, STORE, etc.) using Qlik script - WITHOUT creating a standalone app - without sheets? Would you like that? Well, would you? Well now you can - introducing our new script object and script editor - with data preview and more! Watch this #qlik#SaaSin60 to learn more!
We have now added the ability to create Qlik scripts directly from the hub, ana managed in the catalog - using a new and improved script editor. Users can now build and deploy Qlik scripts upstream of analytics apps, which can be executed and result in output files in formats such as QVD and PARQUET that can be stored in the hub and used for analytics and AutoML applications. The script editor also now includes a data preview feature, allowing users to get better insight when developing scripts. This provides our customers with an improved workflow for preparing data, while setting the stage for future enhancements to analytics data prep capabilities.
This topic has been covered before, but we have a new generation of Qlik users and I found some of the content not always easily explained. Here is my spin to help you get started working with multiple dates / calendars. Sample App and data attached!
New features are always being added to Qlik Sense. Today I will provide an update on three topics I have blogged about this year. The topics are:
NL Insights
Straight table
Filter pane
NL Insights
The NL Insights object, which use to be found in the Dashboard bundle, is now a standard chart object. It now “fully supports the Qlik Cloud UI in multiple languages, accessibility requirements, and reporting / exporting.” The functionality of the NL Insights object has also been updated so that it is easier to add insights for the visualizations in an app by allowing developers to simply select a chart they would like interpreted. Once a NL Insight object is added to a sheet, the developer can click on the Add chart button to see a list of objects that are on the current sheet. Natural language insights will be shown for the selected visualization. This is easier for the developer and removes the need to manually select dimensions and measures.
Filter Pane
At its basis, the filter pane provides a list box that the user can use to make selections. By default, when a user makes a selection in a filter pane, the selection toolbar pops up prompting the user to confirm the selection, as seen in the image below.
It is now possible to turn off the selection toolbar and immediately confirm the selection when it is made. This can be done in the properties window by unchecking the Show selection toolbar checkbox.This is useful if the filter pane is displayed as a grid, versus column, and the filter pane is being used as a button bar.
Note that when the selection toolbar is off, users can still access the select all, select alternative and select excluded options via the sheet toolbar.
Straight Table
The straight table can now be downloaded as an image or multi-page PDF up to 50 pages. Simply right-click on the straight table, select Download and click on Image or PDF.
There are always new features being added to Qlik Cloud. Use Qlik Help to stay up to date or subscribe to the news feed.
Thanks,
Jennell
...View More
The ability to make data-driven decisions in real-time is a cornerstone for many businesses. Using Qlik AutoML's real-time prediction API let's you seamlessly integrate predictions on the fly in your web applications.
In this guide, we will walk through the process of leveraging Qlik AutoML's real-time prediction capabilities using Node.js.
Before using the API, we first need to create an ML experiment in Qlik cloud and deploy it.
Creating the AutoML Experiment and deploying it
There are lots of help articles around this topic, but for our simple case, we will be using a Customer Churn dataset to train our model (You will find the file attached at the end of this post).
Start by creating a new ML experiment from your Qlik cloud hub
After uploading the Training file, select the “churned” column as the target to make our predictions. Make sure to de-select the “AdditionalFeatureSpend” and “DaysSinceLastService” columns if you want to follow along with this example.The features (columns) selected in this step should later on match the schema of the input dataset we want to get real-time prediction on.
Once we run the experiment to train the model, the best performing algorithm is automatically selected, you can now reconfigure a different version or simply press Deploy to create a new ML deployment, let’s do the latter.
In the Deployment screen, you can run predictions on new apply datasets right in the hub, or in our case, we will use the Real-time prediction API to programmatically make predictions from our node.js app.
Creating the node.js app to make real-time predictions
Head to the Real-time predictions pane as shown above, this is where we will be able to grab the API URL.
To interact with the real-time prediction API, you'll require an API key from Qlik Cloud. Users with the 'Developer' role have the necessary privileges to generate this key. You can learn more about generating one here.
Setting up the Environment
Begin by initializing a Node.js environment and installing the necessary packages, run:
npm init -y
then
npm install axios dotenv fs
API Configuration
In the .env file, define the Real-time prediction API URL and the API Key:
API_KEY=eyJhb....
API_URL=https://....
Next, create an index.js file and include the following:
Data prep:
We read from the csv file using fs and format the data to align with the real-time prediction API's requirements
const axios = require('axios');
const fs = require('fs');
require('dotenv').config();
const api_url = process.env.API_URL;
const api_key = process.env.API_KEY;
const rawData = fs.readFileSync('./customer-churn-apply-subset.csv', 'utf8');
const rows = rawData.split('\n').slice(1).filter(line => line.trim() !== '').map(row => {
const [
AccountID, Territory, Country, DeviceType, Promotion, HasRenewed, PlanType,
BaseFee, NumberOfPenalties, CurrentPeriodUsage, PriorPeriodUsage, ServiceRating,
ServiceTickets, StartMonth, StartWeek, CustomerTenure, Churned
] = row.split(',');
return {
"AccountID": AccountID,
"Territory": Territory,
"Country": Country,
"DeviceType": DeviceType,
"Promotion": Promotion,
"HasRenewed": HasRenewed,
"PlanType": PlanType,
"BaseFee": parseFloat(BaseFee),
"NumberOfPenalties": parseInt(NumberOfPenalties, 10),
"CurrentPeriodUsage": parseFloat(CurrentPeriodUsage),
"PriorPeriodUsage": parseFloat(PriorPeriodUsage),
"ServiceRating": parseFloat(ServiceRating),
"ServiceTickets": parseInt(ServiceTickets, 10),
"StartMonth": StartMonth,
"StartWeek": StartWeek,
"CustomerTenure": parseFloat(CustomerTenure),
};
});
const formattedRows = rows.map(record => [
record.AccountID,
record.Territory,
record.Country,
record.DeviceType,
record.Promotion,
record.HasRenewed,
record.PlanType,
record.BaseFee,
record.NumberOfPenalties,
record.CurrentPeriodUsage,
record.PriorPeriodUsage,
record.ServiceRating,
record.ServiceTickets,
record.StartMonth,
record.StartWeek,
record.CustomerTenure
]);
Crafting the API Request:
here, we define the headers and body content for the POST request to the API.Notice that the schema matches the features we used to train our model.
const json_data = {
"rows": formattedRows,
"schema": [
{"name": "AccountID"},
{"name": "Territory"},
{"name": "Country"},
{"name": "DeviceType"},
{"name": "Promotion"},
{"name": "HasRenewed"},
{"name": "PlanType"},
{"name": "BaseFee"},
{"name": "NumberOfPenalties"},
{"name": "CurrentPeriodUsage"},
{"name": "PriorPeriodUsage"},
{"name": "ServiceRating"},
{"name": "ServiceTickets"},
{"name": "StartMonth"},
{"name": "StartWeek"},
{"name": "CustomerTenure"},
]
};
const headers = {
'Authorization': `Bearer ${api_key}`,
'Content-type': 'application/json',
'Accept': 'text/json',
};
Sending the Request & Handling Response
We utilize axios to transmit the data and receive real-time prediction results (you can use any http client for this)
axios.post(
api_url,
json_data,
{
headers: headers,
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error("Error:", error);
});
Now you can run the node app:
node index.js
The result we get are the predictions of the Customer Churn for our apply dataset with the second column representing whether the customer is predicted to Churn or not, 3rd column is the probability of Churned_no, and the 4th column is the probability of Churned_yes.
We can compare these results to the ones we get on the hub if we were to create predictions there:
With Qlik AutoML's real-time prediction API at your fingertips, you’re now ready to integrate real-time predictions into your web apps whether it’s to enrich your visualizations or build interactive what-if scenarios, you can easily make impactful real-time decisions.
API docs: https://qlik.dev/apis/rest/automl-real-time-predictions
You can find the full code and dataset files used below.
...View More
Insight Advisor – our intelligent AI-assistant supports a variety of advanced insight generation and automation experiences including search driven insights, conversational analytics, and analysis types – our unique framework for choosing a type of advanced analysis and generating visualizations, NLG, and even smart sheets. You’ll get a look at key driver analysis, to uncover the factors driving a selected metric. And you’ll get a deeper dive into how you can customize insight generation and natural language processing through our business logic layer.