Oracle Developers
Published in

Oracle Developers

How to Embed Oracle Analytics Anywhere!

Introduction

Embedding analytics into portals, websites, and applications can greatly increase productivity, delivering faster time-to-insight as the information required to make decisions can be put where it’s needed. With such a variety of use cases, iFrames can be a powerful tool to ‘sandbox’ the embedded analytics from an embedding host that may use a different technology or incompatible versions of same technology.

I’ve previously written about embedding Oracle Analytics using an iFrame in addition to describing a method for using iFrames with Oracle Visual Builder. This is the link to the Oracle Analytics product documentation that describes using iFrames. It’s also possible to reference a specific canvas using an Analytics workbook URL.

In this blog, I will describe how iFrames can be used to embed Oracle Analytics into any website, application or portal that supports iFrames.

When to use an iFrame

The ‘inline Frame’ or ‘iFrame’ enables the embedding of a document within another HTML document and is defined by the tag <iFrame>. The use of iFrames when embedding Oracle Analytics is most useful when you need to ‘sandbox’ the embedded analytics content from the main page or application you are embedding into. This is particularly useful if you’re using a framework that works in a different way to knockout (e.g React) or if you are in a scenario where different versions of a technology are being used (e.g. Oracle JET).

How to use an iFrame

In this section, I will describe several use cases for using iFrames for embedding analytics, starting with a basic workbook URL reference through to using window messaging and events to pass values into an iFrame that can be then used as the source of filters to embedded analytics content.

Using the iFrame ‘src’ Parameter

This is a straightforward way to embed analytics content into a web page. The iFrame ‘src’ parameter is suitable when you already have the content you wish to embed hosted elsewhere or are able to upload a suitable HTML file (as in the example where I described embedding analytics into Visual Builder). This example defines a specific height / width for the iFrame but it’s also possible to create responsive iFrames.

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8"/>
<title>iFrame Embed </title>
</head>
<body>

<iframe src="<link to OAC Workbook URL" height="1000px" width="1000px"></iframe>
</body></html>

Using the iFrame ‘srcdoc’ parameter

If you have a use case where that may not be possible to reference content that is already hosted somewhere via a URL or you cannot upload the HTML to host in the same location as where you are embedding, then this is where the iFrame ‘srcdoc’ parameter can be used.

I find this one of the most useful methods to create a self-contained analytics embedding reference as you define the HTML to embed using the iFrame inline with the iFrame tag. Here’s an example:

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<meta charset="utf-8"/>
<title> iFrame Embed </title>
</head>
<body>
<div>
<iframe style='width:1000px; height:800px' srcdoc="<!DOCTYPE HTML>
<html dir='ltr'>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
<title>Oracle Analytics Embed Example</title>
<script src='https://<oac-instance>.analytics.ocp.oraclecloud.com/public/dv/v1/embedding/standalone/embedding.js' type='application/javascript'>
</script>
</head>
<body>
<h1>Embedded Analytics</h1>
<div style='border:1px solid black;position: absolute; width: calc(100% - 40px); height: calc(100% - 120px)''>
<oracle-dv project-path='/@Catalog/shared/Embed/Public Live/Dark_Theme_Embed'
active-page='canvas'
active-tab-id='1'>
</oracle-dv>
</div>
<script>
requirejs(['jquery','knockout','ojs/ojcore', 'ojs/ojknockout', 'ojs/ojcomposite', 'obitech-application/application', 'jet-composites/oracle-dv/loader'], function($, ko, application) {
ko.applyBindings();
});
</script>
</body>
</html>" >
</iframe>
</div></body>
</html>

There are some important points to note:

  • You must use the /standalone/ path to embedding.js, even if you’re embedding into a JET application. This option provides the JET libraries of the version used by Oracle Analytics and hence is beneficial when differing versions of JET are in use.
  • The iFrame ‘srcdoc’ parameter contains the inline HTML within double quotes “ ”. This means that if any if the inline HTML requires a double quote then it needs to be ‘escaped’ using &quot; (this is particularly relevant when embedding analytics content using ‘srcdoc’ and passing filters. For example, “Hello” would become &quot;Hello&quot;
  • There is an iFrame property ‘sandbox’ that can restrict content in an iFrame that may be useful for your use case.

Passing values into an iFrame

A common requirement for embedded analytics is to be able to pass values to the embedded canvas to act as a filter. When using iFrames, we need to use the window.PostMessage() method and define an event listener within the iFrame.

Here is some sample code that applies a filter to a column ‘Region’ that I will explain further below..

<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<title> iFrame Embed </title>
</head>
<body>
<h1>Embed Analytics into iFrame and pass filter value</h1>
<button onclick='PassFilterValue()'> Pass a filter value </button>
<hr>
<iframe id='OACiFrameEmbed' style='width:1200px; height:1000px' srcdoc="<!DOCTYPE HTML>
<html dir='ltr'>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
<title>Oracle Analytics Embed Example</title>
<script src='https://<oac-instance>.analytics.ocp.oraclecloud.com/public/dv/v1/embedding/standalone/embedding.js' type='application/javascript'>
</script>
</head>
<body>
<h1>Sales Analytics</h1>
<div style='width:1200px; height:1000px'>
<oracle-dv id='Filter'
project-path='<path to DV workbook>'
active-page='canvas'
active-tab-id='1'
project-options='{&quot;bDisableMobileLayout&quot;:false, &quot;bShowFilterBar&quot;:true}'
filters='{{filters}}'>
</oracle-dv>
</div><script>requirejs(['jquery','knockout','ojs/ojcore', 'ojs/ojknockout', 'ojs/ojcomposite', 'obitech-application/application', 'jet-composites/oracle-dv/loader'],
function($, ko, application) {
function model() {
var self = this;
self.filters = ko.observableArray([{
'sColFormula': 'XSA(\'<user>\'.\'Order Activity\').&quot;Columns&quot;.&quot;Region&quot;',
'sColName': 'Region',
'sOperator': 'in',
'isNumericCol': false,
'isDateCol': false,
'bIsDoubleColumn': false,
'aCodeValues': [],
'aDisplayValues': ['Central','West']
}]);
window.addEventListener('message', (event) => {
if ((typeof event.data === 'string' || event.data instanceof String) && event.origin == 'http://localhost:8080') {
let self = this;
self.filters([{
'sColFormula': 'XSA(\'<user>\'.\'Order Activity\').&quot;Columns&quot;.&quot;Region&quot;',
'sColName': 'Region',
'sOperator': 'in',
'isNumericCol': false,
'isDateCol': false,
'bIsDoubleColumn': false,
'aCodeValues': [],
'aDisplayValues': [event.data]}
]);
}
}, false);
}ko.applyBindings(new model);});</script></body>
</html>">
</iframe>
<script>
function PassFilterValue () {
document.getElementById("OACiFrameEmbed").contentWindow.postMessage('South', 'http://localhost:8080');
}
</script>
</body>
</html>

The starting point for this example is an Analytics canvas with filters applied to Region of Central and West.

when the ‘Pass a filter value’ button is pressed, an event containing a new filter value of South is sent as a message into the iFrame.

Describing this code, there is a HTML button, that when pressed, will call a function that posts the message to the iFrame. Note that the host which is passing the message is included in the message to ensure that the message is ‘safe’. You’ll notice that the same host is referenced in the if() statement in the event listener in the iFrame.

<button onclick='PassFilterValue()'> Pass a filter value </button>
.
.
.<other code>
.
.
<script>
function PassFilterValue () { document.getElementById("OACiFrameEmbed").contentWindow.postMessage('South', 'http://localhost:8080');
}
</script>

The reference to the Oracle Analytics ‘embedding.js’ is the /standalone/ option:

<script src='https://<oac-instance>.analytics.ocp.oraclecloud.com/public/dv/v1/embedding/standalone/embedding.js' type='application/javascript'>
</script>

This is the <oracle-dv> tag and explanation of key points below:

<oracle-dv id='Filter'
project-path='<path to DV workbook>'
active-page='canvas'
active-tab-id='1'
project-options='{&quot;bDisableMobileLayout&quot;:false, &quot;bShowFilterBar&quot;:true}'
filters='{{filters}}'>
</oracle-dv>

Note the use of the &quot; escape for “ ” in the project-options. The filters are set using an observable that is defined in the next section of code described below:

<script>requirejs(['jquery','knockout','ojs/ojcore', 'ojs/ojknockout', 'ojs/ojcomposite', 'obitech-application/application', 'jet-composites/oracle-dv/loader'],
function($, ko, application) {
function model() {
var self = this;
self.filters = ko.observableArray([{
'sColFormula': 'XSA(\'<user>\'.\'Order Activity\').&quot;Columns&quot;.&quot;Region&quot;',
'sColName': 'Region',
'sOperator': 'in',
'isNumericCol': false,
'isDateCol': false,
'bIsDoubleColumn': false,
'aCodeValues': [],
'aDisplayValues': ['Central','West']
}]);
window.addEventListener('message', (event) => {
if ((typeof event.data === 'string' || event.data instanceof String) && event.origin == 'http://localhost:8080') {
let self = this;
self.filters([{
'sColFormula': 'XSA(\'<user>\'.\'Order Activity\').&quot;Columns&quot;.&quot;Region&quot;',
'sColName': 'Region',
'sOperator': 'in',
'isNumericCol': false,
'isDateCol': false,
'bIsDoubleColumn': false,
'aCodeValues': [],
'aDisplayValues': [event.data]}
]);
}
}, false);
}ko.applyBindings(new model);});</script>

In this code, note the definition of the observable array for the filters. This blog describes how to create a filter JSON array for Oracle Analytics. Again, you’ll see that we have to escape any “ ” characters using &quot;.

In the event listener, there is an if( ) that checks the type of event content that is passed into the iFrame. In this case, it’s checking for content of type string but it could also be an array, in that case it would be something like:

if ((Array.isArray(event.data)) && event.origin == 'http://localhost:8080')

Summary

This blog has shown examples of how iFrames can be used to embed Oracle Analytics content in a variety of use cases in addition to how filters can be passed into an iFrame that references embedded analytics.

Want to discuss? Drop into our public Slack channel for more.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Mike Durran

Mike Durran

Analytics Product Manager at Oracle. [All content and opinions are my own]