Embedding a Link with the SDK

CONTENTS

Home

Once you have created an embed link you can add it to your registered external application using an iframe. The SDK includes a standalone javascript file (bipp.js) used by the external application to load the embeddable bipp dashboard.

Embedded Analytics is only supported for bipp Enterprise Edition.

Getting started with the SDK:

Using SDK to load the dashboard

Below is a complete example, how you can embed a link into a webpage


<!DOCTYPE html>
<html>
<body>
   <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
   <script src="https://unpkg.com/bipp"></script>
   <div id='container'></div>
<script>
   const url = "http://zwchaz.localhost:8080/embed/3d5e2483-71b9-42c4-b3fa-ab238eb70a58?id=14d9d31f-18e6-4876-bc2f-b4b047a4b9ff&cid=523a1c9464bc41639b33829bd4ad81e7.zwchaz.localhost&secret=seP9muK6w3CvoQQVpcA!j1S!qFoiQs72kCbu0BgDVwNXOU3l";
   let config = { id : 'container', width: '1200px', height: '900px', style: 'border:none;' }
   let bipp = new Bipp();
   bipp.load(url, config);
</script>
</body>
</html>

This example code creates an iframe object and appends it in the container html element, url is the embed link created previously. Change the width and height of the iframe with config.

Showing/Hiding filter panel

Use config option filter_panel : true/false to show / hide the filter panel.


let config = { id : 'container', width, height, style: 'border:none;', filter_panel : false }
let bipp = new Bipp();
bipp.load(url, config);

Determining the Dashboard Loaded

You can set up a message to verify when the dashboard is fully loaded.


bipp.onmessage = (e) => {
console.log("message from embedded SDK", e.data);
// message from embedded SDK {source: "bippSDK", message: "ready"}

Adding Filters

You can add filters to the embedded dashboard.

bipp.addFilter(<filters>)

where filters is an array of objects and each object represents a filter. A filter object has the following structure:


{
   table,
   column,
   value,
   params: {
      mode
   }
}

table and column are the underlying table name and column name params is an optional field. mode can have following values: IN, BETWEEN, <, >, <=, >= value is a string

If mode is IN or BETWEEN then value is an array of length two, containing two values.

Filter examples:


// single filter
filters = [{
   table: 'trips',
   column: 'payment_type',
   value: 'CSH'
}];

// two filters
filters = [
    {
        table: 'trips',
        column: 'payment_type',
        value: 'CRD'
    },
    {
        table: 'trips',
        column: 'rate_code',
        value: '34'
    }
]

// filter mode = 'IN'
filters = [{
    table: 'trips',
    column: 'payment_type',
    value: ['CSH', 'CRD'],
    params: { mode: 'IN' }
}]

// filter mode = 'BETWEEN'
filters = [{
    table: 'trips',
    column: 'pickup_datetime',
    value: ['2012-07-01', '2012-07-30'],
    params: { mode: 'BETWEEN' }
}]

Removing Filters

To remove filters from the embedded dashboard, pass an array of filter objects. Each filter object requires two fields: table and column.


bipp.removeFilter(<filters>)
// Example
bipp.removeFilter(
    [{
        table: 'trips',
        column: 'pickup_datetime'
    }]
);

Final HTML Example

Here is an example:


<!DOCTYPE html>
<html>
<body>
   <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
   <script src="https://unpkg.com/bipp"></script>

   <div id='container'></div>

    <script>
        const url = "http://zwchaz.localhost:8080/embed/3d5e2483-71b9-42c4-b3fa-ab238eb70a58?id=14d9d31f-18e6-4876-bc2f-b4b047a4b9ff&cid=523a1c9464bc41639b33829bd4ad81e7.zwchaz.localhost&secret=seP9muK6w3CvoQQVpcA!j1S!qFoiQs72kCbu0BgDVwNXOU3l";
        let config = { id : 'container', width: '1200px', height: '900px', style: 'border:none;' }
        let bipp = new Bipp();
        bipp.load(url, config);
    </script>
</body>
</html>

Security

Embed link contains information which is required for login into the bipp server and once login is successful, the server returns an EmbedToken to the iframe. This embed token is used in all further communication between iframe and server. The embed token stores information like white listed domains, dashboard id and filters in encrypted form (AES 256) and can not be read by unauthorized persons.

Each embed link is associated with a website(s). So only websites which are white listed during embed link creation, can use that embed link. Any other website that tries to embed the link will get an authorization error.

Clients who want to write custom logic on server side and want to create embed links dynamically can do so by using bipp rest API, and can choose the dashboard and pass filters, choose domains while creating embed links. More about this is described in the next section.

Advance Usage

Bipp supports two modes of integration of embedded dashboards with your application:

  • Static Embedding, where all users see the same dashboard data.
  • Dynamic Embedding, where the embed links are custom generated as per the business logic. Using this mode, the users of your application sees only the data as defined by the embed link

In case of static embedding, you can directly embed Bipp dashboards in your existing application with the embed links using the code snippet shown in the previous section.

In case of dynamic embedding, you need to host a web application server where the generation of embed link, as per your business logic, is programmatically handled. Bipp provides a REST API endpoint which can be used to generate an embed link. This API requires the API Key of your registered application for authentication.

The REST API is described as below:

POST /app/v1/extapps/YOUR-APP-ID/embed/generate-link

-H 'Accept: application/json'

-H 'Content-Type: application/json'

-H 'X-Org-ID: YOUR-ORG-ID'

-H 'X-API-Key: YOUR-API-KEY'

{
	"id": "DASHBOARD ID",
	"name": "DASHBOARD NAME",
	"domains": [
    	"scheme://host:port"
	],
	"filters": [
    	{
        	"column": "NAME OF DB COLUMN AS PER DATAMODEL",
        	"comparator": "COMPARATOR OPERATOR",
        	"table": "NAME OF DB TABLE AS PER DATAMODEL",
        	"value": "FILTER VALUE",
        	"logical_operator": "AND / OR"
    	}
	]
}

More than one domain can be specified, separated by commas. Also, more than one filters can be specified and chained together through logical operators: AND, OR

Comparator Operators can be one of "=", "<>", "<", ">", "<=", ">=", "BETWEEN", "IN", "LIKE", "NOT IN", "NOT BETWEEN", "STARTS WITH", "ENDS WITH", "IS NULL", "IS NOT NULL", "IS EMPTY", "IS NOT EMPTY"

On Success: 201 Created is returned with a response body similar to:

{
"embed_url": "http://home.localhost:8080/embed/dba7eea2-3d14-48d8-b615-9fe5649e283c?id=ee31e70d-f209-46a6-ba45-06ef4256fcf3&cid=6bdc83fcd28c49e1927d01d415e7b2e2.home.localhost&secret=dyXKLQ2pGujkPah05UZKMYa5tow9YEuGbgL9!HTBDRdkN3pR"
}

On Failure, one of the following HTTP status codes is returned, along with the appropriate error message:

400 BadRequest

401 Unauthorized

402 PaymentRequired

403 Forbidden

500 InternalServerError

In next sections we will show how to do dynamic embedding with example code in different languages.

Node JS Example

Full code example for dynamic embedding using programmatic filtering in node JS. The code below runs a server at port 9191 and serves a Bipp embedded dashboard.


const express = require('express');
const axios = require('axios');

const port = '9191';
const orgID = 'O~zNHknp0hV';
const appID = '28a2274d-2596-44d9-a4d0-607526855397';
const apiKey = 'rdhgstionbr65tt81vlc0lvwy47uroh5cnsum38pyf88wbie';
const bippURL = 'http://localhost:8080';

const content = `<!DOCTYPE html>

<html>
<style>
h1 {text-align: center;}
div {text-align: center;}
</style>
<body style="background-color:powderblue;">
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://unpkg.com/bipp"></script>
<h1>Bipp Dynamic Embedding Demo (Node Server)</h1>
<div id='container'></div>
<script>
const url = '%s';
var w = window.innerWidth;
var h = window.innerHeight;
let config = { id : 'container', width: w, height: h, style: 'border:none;' }
let bipp = new Bipp();
bipp.load(url, config);
</script>
</body>
</html>`;

let app = express();

function embedHandler(req, res) {

const url = `${bippURL}/app/v1/extapps/${appID}/embed/generate-link`;

axios
.post(
url,
{
id: 'D~5UYBGNBjJ',
name: 'Demography',
domains: ['http://localhost:9191'],

       filters: [
         {
           table: "_2020",
           column: "Region",
           comparator: "="
         }
       ]
     },
     {
       headers: {
         'X-API-Key': apiKey,
         'X-Org-ID': orgID,
       },
     }

)
.then(function (response) {
const { embed_url } = response.data;

     const data = content.replace('%s', embed_url);
     res.send(data);

})
.catch(function (error) {
console.log(error);
});
}

app.get('/', (req, res) => {
embedHandler(req, res);
});

app.listen(port, function () {
console.log('Running node server', 'on port ' + port);
});

Golang Code Example

Full code example for dynamic embedding using programmatic filtering in Golang. The code below runs a server at port 9191 and serves a Bipp embedded dashboard.


package main
import (
"fmt"
"log"
"time"
"strings"
"io/ioutil"
"net/http"
"encoding/json"
)
const (
port = ":9191"
orgID = "O~27gKJhx7N"
appID = "ee31e70d-f209-46a6-ba45-06ef4256fcf3"
apiKey = "zg0s72c6x54nxxn97qjxd8ooqzdlmzpc2t4ujzgo8rzl2ik7"
bippURL = "https://app.bipp.io"
)
var content = `<!DOCTYPE html>

<html>
<style>
h1 {text-align: center;}
div {text-align: center;}
</style>
<body style="background-color:powderblue;">
   <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
   <script src="https://unpkg.com/bipp"></script>
   <h1>Bipp Dynamic Embedding Demo (Go Server)</h1>
   <div id='container'></div><script>
   const url = "%s";
   var w = window.innerWidth;
   var h = window.innerHeight;
   let config = { id : 'container', width: w, height: h, style: 'border:none;' }
   let bipp = new Bipp();
   bipp.load(url, config);
   </script>
</body>
</html>
`
func embedHandler(w http.ResponseWriter, r * http.Request) {
   reqURL: = fmt.Sprintf("%s/app/v1/extapps/%s/embed/generate-link", bippURL, appID)

method: = "POST"
payload: = strings.NewReader(`{
"id": "D~ZpO3WhzSG",
"name": "TestDashboard"
"domains": [
"http://localhost:9191"
],
"filters": [
{
"column": "Region",
"comparator": "=",
"table": "\_2020",
"value": "Western Europe",
"logical_operator": "AND"
},
{
"column": "Region",
"comparator": "=",
"table": "\_2020",
"value": "North America and ANZ",
"logical_operator": "OR"
},
{
"column": "Region",
"comparator": "=",
"table": "\_2020",
"value": "Southeast Asia"
}

]}`) client: = & http.Client { Timeout: 30 * time.Second, } req, err: = http.NewRequest(method, reqURL, payload) if err != nil { fmt.Println(err) return } req.Header.Add("Accept", "application/json") req.Header.Add("Content-Type", "application/json") req.Header.Add("X-Org-ID", orgID) req.Header.Add("X-API-Key", apiKey) res, err: = client.Do(req) if err != nil { fmt.Println(err) return } defer res.Body.Close() body, err: = ioutil.ReadAll(res.Body) if err != nil { fmt.Println(err) return } type response struct { EmbedURL string `json:"embed_url"`
}
var data response
err = json.Unmarshal(body, & data)
if err != nil {
fmt.Println(err)
return
}
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprintf(w, content, data.EmbedURL)
}
func main() {
http.HandleFunc("/", embedHandler)
log.Println("HTTP Serving at " + port)
log.Fatal(http.ListenAndServe(port, nil))
}

Python Code Example

Full code example for dynamic embedding using programmatic filtering in Python. The code below runs a server at port 9192 and serves a Bipp embedded dashboard.


#!/usr/bin/env python3
import sys, signal
import requests
import json
from http.server import BaseHTTPRequestHandler, HTTPServer
PORT = 9192
ORGID = "O~27gKJhx7N"
APPID = "ee31e70d-f209-46a6-ba45-06ef4256fcf3"
APIKEY = "zg0s72c6x54nxxn97qjxd8ooqzdlmzpc2t4ujzgo8rzl2ik7"
BIPPURL = "https://app.bipp.io"
content = """<!DOCTYPE html>

<html>
<style>
h1 {text-align: center;}
div {text-align: center;}
</style>
<body style="background-color:powderblue;">
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://unpkg.com/bipp"></script>
<h1>Bipp Dynamic Embedding Demo (Python Server)</h1>
<div id='container'></div>
<script>
const url = '%s';
var w = window.innerWidth;
var h = window.innerHeight;
let config = { id : 'container', width: w, height: h, style: 'border:none;' }
let bipp = new Bipp();
bipp.onmessage = (e) => {
console.log("Bipp Embedded SDK", e.data);
}
bipp.load(url, config);
</script>
</body>
</html>"""
# A custom signal handle to allow us to Ctrl-C out of the process
def signal_handler(signal, frame):
   print( 'Exiting http server (Ctrl+C pressed)')
   try:
       if( server ):
           server.server_close()
   finally:
       sys.exit(0)

def embed_url():
url = "{bipp_url}/app/v1/extapps/{app_id}/embed/generate-link".format(bipp_url=BIPPURL, app_id=APPID)
payload = json.dumps({
"id": "D~L_GYXHDHW",
"name": "My Dashboard",
"domains": ["http://localhost:9192"],
"filters": [
{
"column": "Region",
"comparator": "=",
"table": "_2020",
"value": "Western Europe",
"logical_operator": "AND"
},
{
"column": "Region",
"comparator": "=",
"table": "_2020",
"value": "North America and ANZ",
"logical_operator": "OR"
},
{
"column": "Region",
"comparator": "=",
"table": "_2020",
"value": "Southeast Asia"
}
]
})
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-Org-ID': ORGID,
'x-api-key': APIKEY
}

response = requests.request("POST", url, headers=headers, data=payload)
return json.loads(response.text)['embed_url']# Install the keyboard interrupt handler
signal.signal(signal.SIGINT, signal_handler)

class handler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type','text/html; charset=utf-8')
self.end_headers()
body = content % embed_url()
self.wfile.write(bytes(body, "utf8"))
try:
with HTTPServer(('', PORT), handler) as server:
print("Http Server Serving at port", PORT)
server.serve_forever()
except KeyboardInterrupt:
pass
server.server_close()

Ruby Code Example

Full code example for dynamic embedding using programmatic filtering in Ruby. The code below runs a server at port 9193 and serves a Bipp embedded dashboard.


#!/usr/bin/env ruby

require "uri"
require "json"
require "webrick"
require "net/http"
PORT = 9193
ORGID = "O~27gKJhx7N"
APPID = "ee31e70d-f209-46a6-ba45-06ef4256fcf3"
APIKEY = "zg0s72c6x54nxxn97qjxd8ooqzdlmzpc2t4ujzgo8rzl2ik7"
BIPPURL = "https://app.bipp.io"
content = % Q( < !DOCTYPE html >
<
html >
<
style >
h1 {
text - align: center;
}
div {
text - align: center;
} <
/style> <
body style = "background-color:powderblue;" >
<
script src = "https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js" > < /script> <
script src = "https://unpkg.com/bipp" > < /script> <
h1 > Bipp Dynamic Embedding Demo(Ruby Server) < /h1><div id='container'></div >
<
script >
const url = "%s";
var w = window.innerWidth;
var h = window.innerHeight;
let config = {
id: 'container',
width: w,
height: h,
style: 'border:none;'
}
let bipp = new Bipp(); bipp.onmessage = (e) => {
console.log("Bipp Embedded SDK", e.data);
}
bipp.load(url, config); <
/script> <
/body> <
/html>)
def embed_url() url = URI("%s/app/v1/extapps/%s/embed/generate-link" % [BIPPURL, APPID]) http = Net::HTTP.new(url.host, url.port); request = Net::HTTP::Post.new(url) request["Accept"] = "application/json"
request["Content-Type"] = "application/json"
request["X-Org-ID"] = ORGID request["x-api-key"] = APIKEY request.body = JSON.dump({
"id": "D~MhNWm\_\_RM",
"name": "Western Europe Happiness Index 2020"
"domains": [
"http://localhost:9193"
],
"filters": [{
"column": "Region",
"comparator": "=",
"table": "_2020",
"value": "Western Europe",
"logical_operator": "AND"
}]
}) response = http.request(request) return JSON.parse(response.read_body)['embed_url']
end server = WEBrick::HTTPServer.new(Port: PORT, DocumentRoot: '.') server.mount_proc("/") do |request, response |
response.status = 200 response.content_type = "text/html; charset=utf-8"
response.body = content % [embed_url()] end trap 'INT'
do server.shutdown end
server.start