Technical Articles
Quickly integrate SAP Analytics Cloud with other systems using custom widgets
In your customer projects, you may have the need to integrate SAP Analytics Cloud with other systems, SAP or non-SAP systems, in order to pull data from them into SAP Analytics Cloud or send a write action to these external systems.
You can do it with Post Message API and OData connection. In this blog post, I would like to introduce another way, which I think might be more generic, user friendly and reusable – using the custom widgets in SAP Analytics Cloud, analytics designer.
I would like to share with you a demo, code example, and some frequently asked questions.
Demo
Let’s first look at a demo about how to get public data using public data API and how to create a purchase order item in S/4HANA Cloud using SAP API Business Hub.
(source: The COVID Tracking Project https://covidtracking.com/, and license page: https://covidtracking.com/about-data/license)
(the system dialog in the demo)
Get Public Data via Data API
The first custom widget pulls data from the website using its public data API. https://covidtracking.com/data/api.
(source: The COVID Tracking Project https://covidtracking.com/, and license page: https://covidtracking.com/about-data/license)
It simply sends the get request to the website, then pulls back the data, which you can use in SAP Analytics Cloud.
Try it by yourself
- Create a folder structure like c:\web\covid\
- Copy following code and save it as c:\web\covid\index.json
{ "eula": "", "vendor": "SAP", "license": "", "id": "com.sap.sac.sample.ajax.covid", "version": "1.0.0", "name": "Ajax Covid Widget", "newInstancePrefix": "AjaxCovid", "description": "A sample custom widget wrapped jQuery ajax covid get/post", "webcomponents": [ { "kind": "main", "tag": "com-sap-sample-ajax-covid", "url": "http://localhost:3000/covid/main.js", "integrity": "", "ignoreIntegrity": true } ], "properties": { "width": { "type": "integer", "default": 1 }, "height": { "type": "integer", "default": 1 } }, "methods": { "get": { "description": "Wrapper for jQuery get", "parameters": [ { "name": "url", "type": "string", "description": "" } ], "returnType": "string[]" } }, "events": { } }
- Copy following code and save it as c:\web\covid\main.js
var getPromisify = (url, data, dataType) => { return new Promise((resolve, reject) => { $.get(url, data, (response, status, xhr) => { if (status === 'success') { resolve({ response, status, xhr }) } else { const err = new Error('xhr error') err.target = xhr reject(err) } }, dataType) }) } (function () { const template = document.createElement('template') template.innerHTML = ` <style> </style> <div id="root" style="width: 100%; height: 100%;"> </div> ` class MainWebComponent extends HTMLElement { // ------------------ // Scripting methods // ------------------ async get (url, data, dataType) { const r = await getPromisify(url, data, dataType) return [ r.response.positiveCasesViral, r.response.positiveIncrease, r.response.hospitalizedCurrently ] } } customElements.define('com-sap-sample-ajax-covid', MainWebComponent) })()
- Upload c:\web\covid\index.json to SAP Analytics Cloud as a custom widget
- Start your local web server. I personally like lite-server, a very light weight web server. You can install it with two steps:
- Install NPM tool:https://www.npmjs.com/get-npm
- Install lite-server: from OS’s terminal command line: npm install -g lite-server
Then from OS’s terminal command line:
- cd c:\web (this is important as the relative path is now hard-coded in index.json)
- lite-server
Congratulation!Now you can open SAP Analytics Cloud to create an Analytic Application, and you can directly add your own custom widget, the same as in my demo.
Connect to S/4HANA Cloud via SAP API Business Hub
The second custom widget connects to S/4HANA Cloud via SAP API Business Hub to create a purchase item.
As S/4HANA Cloud requires handling of CORS and authentication, we need a backend server like Node.js to do the communications. The S/4HANA Cloud example consists of two parts:
- The custom widget: provides widget UI for SAP Analytics Cloud application developer
- The Node.js: does CORS, authentication, and talks to S/4HANA Cloud
Try it by yourself
- Setup communication scenario in S/4HANA Cloud. We need the username and password configured here in subsequent API calls.
- Create the custom widget. It delegates the call to Node.js
var ajaxPromisify = (url, type, data, headers) => { return new Promise((resolve, reject) => { $.ajax({ url, type, data, contentType: 'application/json', headers, // xhrFields: { // withCredentials: true // }, crossDomain: true, success: function (response, status, xhr) { resolve({ response, status, xhr }) }, error: function (response, status, xhr) { const err = new Error('xhr error') err.status = xhr.status reject(err) } }) }) } const SERVICE_END_POINT = 'http://localhost:3500/sap/opu/odata/sap/API_PURCHASEORDER_PROCESS_SRV'; (function () { const template = document.createElement('template') template.innerHTML = ` <style> </style> <div id="root" style="width: 100%; height: 100%;"> </div> ` class MainWebComponent extends HTMLElement { // ------------------ // Scripting methods // ------------------ async post (path, jsonString) { const { response } = await ajaxPromisify(`${SERVICE_END_POINT}${path}`, 'POST', jsonString) return response.statusCode } } customElements.define('com-sap-sample-s4api-purchaseorder', MainWebComponent) })()
- Create the Node.js. As the code snippet is long, I only copy part of them here. For S/4Hana Cloud integration, please make sure you don’t miss first fetching “’x-csrf-token” then use this token in the subsequent calls by adding { ‘x-csrf-token’: ‘fetch’ } to the header.
const got = require('got') const { CookieJar } = require('tough-cookie') const cookieJar = new CookieJar() const config = require('./config') const BASE_OPTIONS = { cookieJar, username: config.s4api.username, password: config.s4api.password } let token const init = async () => { const response = await got.get(`https://${config.s4api.domain}/sap/opu/odata/sap/API_PURCHASEORDER_PROCESS_SRV`, { ...BASE_OPTIONS, headers: { 'x-csrf-token': 'fetch' } }) token = response.headers['x-csrf-token'] } const post = async (req) => { try { const response = await got.post(`https://${config.s4api.domain}${req.originalUrl}`, { ...BASE_OPTIONS, headers: { 'x-csrf-token': token }, json: req.body }) return response.statusCode } catch (error) { return error.response.statusCode } } module.exports = { init, post }
- Upload the custom widget’s json file to SAP Analytics Cloud.
- Start the web server and Node.js
- Go to SAP Analytics Cloud to create an analytic application. Add your own custom widget, and send request to S/4HANA Cloud like I did in my demo recording.
Frequently asked questions
- What are the user scenarios of using custom widgets to extend SAP Analytics Cloud’s integration capability?
Using custom widgets to extend SAP Analytics Cloud’s integration capability, you will have the possibility for many closed-loop scenarios like:
- Pull data from external systems to SAP Analytics Cloud
- Write data back to external systems
- Trigger actions from SAP Analytics Cloud such as approve, create, update, delete, etc.
- Send notification from SAP Analytics Cloud to external systems
- Does it support non-SAP systems?
Yes. It is based on HTTP request. Any open system that accepts HTTP request can be integrated with SAP Analytics Cloud using this solution. For instance, if you have exposed REST API for customer’s OA and BPM systems, then these systems will be able to integrate with SAP Analytics Cloud.
- What kinds of HTTP requests are supported?
No restrictions are set. The common get, post, patch are all supported.
- What’s SAP API Business Hub?
SAP API Business Hub provides a standard way to easily build Apps, Integrations and Extensions based on SAP products. Supported products include SAP S/4HANA Cloud, SAP S/4HANA, SAP SuccessFactors, SAP Fieldglass, SAP Concur, SAP Ariba, SAP Cloud Platform, etc. More details: https://api.sap.com/
- When accessing the external systems, does the Same-origin policy (https://en.wikipedia.org/wiki/Same-origin_policy)apply as well?
Yes, the Same-origin policy applies in this case as well.
Some public data sources, like the data source in our example, in its response, the server sends back header with Access-Control-Allow-Origin: *, which means that the resource can be accessed by any origin. Nothing special we need to handle in this case.
In most business systems, this needs to be addressed. Many third-party packages are available, for instance, CORS Node.js package. https://www.npmjs.com/package/cors
- Any recommended API testing tool?
The Postman is an excellent one. It is better to run the API successfully in Postman, then wrap it as a custom widget. https://www.postman.com
- Can I schedule the application to run repeatedly? For instance, I would like SAP Analytics Cloud to monitor the data, then based on my configuration, triggering the status update to external systems?
Yes. You can schedule the application to run at the backend with the scheduling feature in SAP Analytics Cloud.
Summary
By following this integration example, I hope you can quickly build up the closed-loop scenarios.
For questions, please visit your community topic page about SAP Analytics Cloud or post your question here.
Great article Yang, thanks for the information. I understand how we can display the information with this method but How can I import this information into a Model? I would like to store the data in SAC so I can use it for a Predictive model
Hi Carlos,
You can write the data back to a planning model.
thanks,
Jason
Hi Jason,
Great article. But is there any way I can upload transaction data in the planning model using the custom widget?
Thanks in advance.
Hi,
There are two APIs on the planning model will help - create members and setUserInput. You can download the Analytic Designer handbook where there are some code sample. https://saphanajourney.com/sap-analytics-cloud/analytics-designer/
Refer to sections (may be updated in newer version of the handbook):
6.10 Set User Input for Planning Data
7.9 Members on the Fly
It works when you have a small set of data, when the data volume is big, this may not be the best way.
thanks,
Jason