[100% JS] Embed Power BI Tiles in SharePoint !

EDIT: You can now use the jPBI Framework to achieve this goal
https://jpbi.codeplex.com/

Hi all,

After my session with William Bordes called « Embed Power BI ». In this session we showed how to embed a Power BI tile in a web page, or a SharePoint Page, or whatever can show an iFrame and execute JavaScript.

Find here the Sway (in French) of our session

The code is available here, on MSDN

This is the result we expect :Capture d’écran 2015-11-26 à 12.23.05.png

I’d like to share with you THE CODE !
It’s extremely easy : everything is done with JavaScript.

First things first : to embed a tile from Power BI, you have to know its URL, to put in into the Iframe !

Prerequisites :
1. A Power BI report uploaded on the Power BI Portal
2. Tile(s) pined on a dashboard, on the Power BI Portal
Sound’s like this :
Capture d’écran 2015-11-28 à 12.16.52.png

Let’s code !
3. Get the URL of the tile you want to embed. Please use : apiary.io

You have to authenticate with your O365 account on it, and add an Application on your Azure AD, extremly simple :Capture d’écran 2015-12-06 à 10.20.26.png

Authentication :

Capture d’écran 2015-12-06 à 10.20.49.png

Allow Apiary to connect to Power BI Service

Capture d’écran 2015-12-06 à 10.21.00.png

Back to Apiary, « switch to code » and then, « Call ressource »

Capture d’écran 2015-12-06 à 10.21.16.png

Scroll down to the « Body », and find the JSON ! Get the ID of the dashboard you want.

Capture d’écran 2015-12-06 à 10.21.40.png

List all tiles of the dashboard !

Capture d’écran 2015-12-06 à 10.22.05.png

Get the embed URL of the tile you want to show in SharePoint/Website.

Capture d’écran 2015-12-06 à 10.22.48.png

Let’s go to Visual Studio !
I’m going to show you a SharePoint Online integration, so you have to install Office Dev Tools with your Visual Studio.

New Project and create a Provider Hosted App

Capture d’écran 2015-12-06 à 10.45.52.png

Capture d’écran 2015-12-06 à 10.46.35.png

Get connect, then…

Capture d’écran 2015-12-06 à 10.47.19.png

Note that I choose an MVC app because I must use MVC every time it’s possible for me (to learn it). You can use a web forms app if you want. The JS code I’ll show later won’t be change.

Capture d’écran 2015-12-06 à 11.23.58.png

Capture d’écran 2015-12-06 à 11.24.20.png

 

Now, we are really happy to have an app. But, before going further, we have to create and set an application in your Azure AD (the Azure AD used by your Office 365 Tenant).

So, go to your Azure Portal (if you didn’t dit it already, subscribe on Azure with your Office 365 Admin account, you’ll see your Azure AD after that).

Capture d’écran 2015-12-06 à 11.40.35.png

Capture d’écran 2015-12-06 à 11.41.53.png

Capture d’écran 2015-12-06 à 11.42.01.pngCapture d’écran 2015-12-06 à 11.42.33.png

Back to Visual Studio, you need to get an information there !

Capture d’écran 2015-12-06 à 11.43.10.png

Back to Azure !

Capture d’écran 2015-12-06 à 11.43.34.png

You’re AAD Application has been created. Now clic on « Configure »

Capture d’écran 2015-12-06 à 11.44.04.png

Scroll down and and « Add an application »Capture d’écran 2015-12-06 à 11.44.26.png

Select « Power BI Service »

Capture d’écran 2015-12-06 à 11.44.37.png

Give authorizations ! And Save !

Capture d’écran 2015-12-06 à 11.44.56.png

Scroll up and copy the Client ID of the app. Paste it in a notepad.

Capture d’écran 2015-12-06 à 11.45.35.png

Then, we have to make a few changes in the AAD Application JSON configuration. It’s needed to make it works with our Javascript authentication code. So, go back on the dashboard of your AAD Application.

Download the manifest

Capture d’écran 2015-12-06 à 11.54.11.png

Open it, and set the value of the parameter « oauth2AllowImpliciteFlow » to « true ». Save the file.Capture d’écran 2015-12-06 à 11.55.43.png

Re-upload it in AzureCapture d’écran 2015-12-06 à 11.55.55.pngCapture d’écran 2015-12-06 à 11.56.11.png

 

Nice ! Everything is ready. Now we can code !!! Go back to Visual Studio !

Let’s prepare the app.
Change your HomeController.cs, so it’ll seem like this (don’t forget to remove the [SharePointContextFilter]).

Capture d’écran 2015-12-06 à 14.35.21.png

Comment the code in _ViewStart.cshtml

Capture d’écran 2015-12-06 à 14.01.34.png

 

The code is available here, on MSDN

Now, we add the HTML code to « Index.cshtml »

In this example I will embed three tiles ; so I’ve added three iFrame elements. 

Capture d’écran 2015-12-06 à 15.22.53.png

And the JS code !

Line 13 to 19, you’ll see three call to « UpdateEmbedTile ». The first parameter is the ID of the iFrame you add in the HTML, the second parameter is the « embedUrl » we get with Apiary. You have to set it to your own value.

In the function requestToken(), don’t forget to change the var « clientId » with the client ID of your AAD application (you’ve just copied to the notepad) and, if needed, the redirectUrl, with the SSL Url of your application.

Do not forget to load jQuery :
/Scripts/jquery-1.10.2.min.js

     //https://powerbi.microsoft.com/en-us/documentation/powerbi-developer-integrate-a-power-bi-tile-or-report/

var token = null;  
   
     $(document).ready(function () {  
   
       //Get Token  
       if (urlParameterExtraction.queryStringParameters['access_token'] == null) { requestToken(); }  
       // Extract token from urlParameterExtraction object.  
       token = urlParameterExtraction.queryStringParameters['access_token'];  
   
       //Like par auteurs  
       updateEmbedTile("iFrameEmbedTile1", "https://app.powerbi.com/embed?dashboardId=c822f941-7d5a-4769-abf3-0bfdfe7d202b&tileId=bd39ae2a-5499-44c9-81e7-212e4ddc7e9e", 300, 450);  
       //Nombre total de likes  
       updateEmbedTile("iFrameEmbedTile2", "https://app.powerbi.com/embed?dashboardId=c822f941-7d5a-4769-abf3-0bfdfe7d202b&tileId=98c7349d-0c80-4054-a9db-f556fb99acc1", 300, 250);  
       //Top des likeurs  
       updateEmbedTile("iFrameEmbedTile3", "https://app.powerbi.com/embed?dashboardId=c822f941-7d5a-4769-abf3-0bfdfe7d202b&tileId=8dc31946-6b46-4f60-9316-1a7fcd6a5ead", 250, 800);  
   
     });  
   
   
     //**********************//  
     //***TILE MANAGEMENT***//  
     //********************//  
     function updateEmbedTile(iFrameId, embedTileUrl, h, w) {  
       console.log("updateEmbedTile");  
       // check if the embed url was selected  
       if ("" === embedTileUrl)  
         return;  
   
       // to load a tile do the following:  
       // 1: set the url, include size.  
       // 2: add a onload handler to submit the auth token  
       iframe = document.getElementById(iFrameId);  
       iframe.src = embedTileUrl + "&width=" + w + "&height=" + h;  
       iframe.onload = function () { postActionLoadTile(iFrameId, h, w); }  
     }  
     function postActionLoadTile(iFrameId, h, w) {  
       console.log("postActionLoadTile");  
       // get the access token.  
       accessToken = token;  
   
       // return if no a  
       if ("" === accessToken)  
         return;  
   
   
       // construct the push message structure  
       var m = { action: "loadTile", accessToken: accessToken, height: h, width: w };  
       message = JSON.stringify(m);  
   
       // push the message.  
       iframe = document.getElementById(iFrameId);  
       iframe.contentWindow.postMessage(message, "*");;  
     }  
   
     //************************//  
     //********UTILS**********//  
     //**********************//  
     function requestToken() {  
       // Change clientId and replyUrl to reflect your app's values  
       // found on the Configure tab in the Azure Management Portal.  
       // Also change {your_subdomain} to your subdomain for both endpointUrl and resource.  
       var clientId = 'dd4870e9-992c-4e26-b464-28f66a738930';  
       var replyUrl = 'https://localhost:44300';  
       var resource = "https://analysis.windows.net/powerbi/api";  
       var authServer = 'https://login.windows.net/common/oauth2/authorize?';  
       var responseType = 'token';  
   
       var url = authServer +  
            "response_type=" + encodeURI(responseType) + "&" +  
            "client_id=" + encodeURI(clientId) + "&" +  
            "resource=" + encodeURI(resource) + "&" +  
            "redirect_uri=" + encodeURI(replyUrl);  
   
       window.location = url;  
     }  

 

 var urlParameterExtraction = new (function () {  
       function splitQueryString(queryStringFormattedString) {  
         var split = queryStringFormattedString.split('&');  
   
         // If there are no parameters in URL, do nothing.  
         if (split == "") {  
           return {};  
         }  
   
         var results = {};  
   
         // If there are parameters in URL, extract key/value pairs.   
         for (var i = 0; i < split.length; ++i) {  
           var p = split[i].split('=', 2);  
           if (p.length == 1)  
             results[p[0]] = "";  
           else  
             results[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));  
         }  
   
         return results;  
       }  
   
       // Split the query string (after removing preceding '#').   
       this.queryStringParameters = splitQueryString(window.location.hash.substr(1));  
     })();  

On the SharePoint part of the project, we will add a Client Web Part to embed our page that contains tiles.Capture d’écran 2015-12-06 à 13.41.12.png

 

Capture d’écran 2015-12-06 à 13.41.37.png

Capture d’écran 2015-12-06 à 13.42.12.png

In the Elements.xml of your webpart, change the code with that :

 <?xml version="1.0" encoding="utf-8"?>  
 <Elements xmlns="http://schemas.microsoft.com/sharepoint/">  
  <ClientWebPart Name="Embed Power BI Tiles" Title="Embed Power BI Tiles" Description="Show Embed Power BI Tiles" DefaultWidth="900" DefaultHeight="2000">  
   
   <!-- Content element identifies the location of the page that will render inside the client web part  
      Properties are referenced on the query string using the pattern _propertyName_  
      Example: Src="~appWebUrl/Pages/ClientWebPart1.aspx?Property1=_property1_" -->  
   <Content Type="html" Src="~remoteAppUrl" />  
   
   <!-- Define properties in the Properties element.  
      Remember to put Property Name on the Src attribute of the Content element above. -->  
   <Properties>  
   </Properties>  
   
  </ClientWebPart>  
 </Elements>  
   

You can now press F5 and launch the debug !
Allow the app in your SharePoint.

The first thing you’ll see in your web browser will be a page with your tiles.

Capture d’écran 2015-12-06 à 14.57.28.png

Now, go to your SharePoint, add a page, edit it and add a webpart. Choose the webpart we add in the Add In !Capture d’écran 2015-12-06 à 13.44.51.png

And that’s it !

Capture d’écran 2015-12-06 à 15.00.08.png

 

Before upload it in production environment, don’t forget to change redirection address in your AAD Application AND in your JS code.

Note that I tried the API to embed some reports, but it seems to be a little bit buggy, so I’m in touch with Power BI team to see how we can fix it !

Do not hesitate to ask if you meet any issue !

And again : The code is available here, on MSDN 😉

 

 

29 réflexions sur “[100% JS] Embed Power BI Tiles in SharePoint !

  1. Hi, thank you for writing this article – I am new totally new to app development and managed to follow your instructions, which means they were quite good. 🙂

    When my tiles are loading, they display a « sorry we couldn’t find what you were looking for » message with an owl image for just a second, then the graphs load normally – do you know what causes this? It *does* work, but for some reason it is using this message while the tiles load.

    J’aime

    • Yes I know ! Are you using Firefox ?
      If yes, the cause is :
      1. The page load without token
      2. Iframes are loaded without the token <= IT'S WHEN YOU SEE THE MESSAGE
      3. The page re-load, call Azure AD, get the token
      4. Iframes re-loads, and show tiles (because you have your token)
      I've experimented this experience only with Firefox. A workaround should be : hide the div that contains the iFrames since you don't have a token in the URL, with jQuery/Javascript.

      J’aime

      • Christine dit :

        Yes, Firefox. Thank you! I have since managed to break the whole thing (for some reason the web part is trying to look at the localhost url now and failing to find it…) but I will poke around.

        J’aime

  2. Alex dit :

    Very helpful article. I have followed your instructions, after downloading and making the changes that you specified, but I’m getting the following error, which seems to be on the Power BI side

    SourceMap https://app.powerbi.com/11.0.9169.161/scripts/visuals.min.js.map read failed: One or more errors occurred.SourceMap https://app.powerbi.com/11.0.9169.161/scripts/PowerBIVisualRenderer.min.js.map read failed: One or more errors occurred.The program ‘[4620] iexplore.exe’ has exited with code 0 (0x0).

    Have you ever seen it? Do you know what could be causing it? Thanks,

    Alex

    J’aime

    • Hi !

      It seems to be an error on Microsoft side (remember it’s in beta). I’ve met those kinds of errors with the API for reports, that’s why the code for reports is commented in the code. Here, we are using the API for tiles.

      Maybe you should talk about that to the Power BI dev team on Twitter. They like feedbacks… Or try with another web browser !

      Best regards

      J’aime

      • Christine dit :

        I just saw last week that the dev team is officially working on PBI embeds in SharePoint, so one way or another it’ll probably get fixed 🙂

        J’aime

  3. ken dit :

    Hi sir, i don’t know what i haven’t done wrong.
    I get this report if i write done my credentials. :/
    I’ve tried it with microsoft edge, firefox, IE and chrome.

    cheers Ken

    J’aime

  4. Sasha dit :

    Very good solution here – I always have the problem that the reports are loading very long time and the browser not responding and the site is crashing. Do you know this issue ? The tiles are working fine.

    J’aime

  5. Shwetha dit :

    I followed the post. Now in the end when I deploy the application ,I get following error
    Can you please help me.

    Sign In
    Sorry, but we’re having trouble signing you in.
    We received a bad request.

    Additional technical information:
    Correlation ID: e52f3ccf-0f35-4291-bd48-09c0428249bc
    Timestamp: 2016-08-30 11:44:43Z
    AADSTS70001: Application with identifier ‘fcd56ff3-2dd5-440c-bcb7-6714950fff1a’ was not found in the directory mind123.onmicrosoft.com

    J’aime

  6. Shwetha dit :

    Hi,

    Can you please help. I have followed all the steps mentioned in the blog. Whenm I try browsing it, I get an message saying ‘OOp’s the page you are looking for couldn’t be found’. I tried refreshing the page several times but still the error is same and the browser I am using is Chrome and Microsoft edge

    Any help is really appreciated.

    J’aime

  7. Hi, I am using PowerBI API to get dashboards, tiles and reports. i think Power BI API is not returning responsive html data, all divs are with hard coded height and width. How i can use this in a responsive web site?
    thanks
    Jais

    J’aime

    • Hi Jason, really I don’t know… Maybe try using the Office UI Fabric or some PnP responsive stuff for SharePoint, but I’m really not sure about the result. Another approach would be to use the Power BI app on iOS (if your devices are on it)…

      J’aime

  8. Fantastic blog you have here but I was curious if you knew of any forums that cover the same topics discussed in this article? I’d really like to be a part of online community where I can get comments from other experienced individuals that share the same interest. If you have any suggestions, please let me know. Bless you!|

    J’aime

  9. Jonathan dit :

    Very informative post! Thank you!

    I’m a little stuck in my deployment :

    I’ve tried both your original and the jpbi version but when launching debug i get a message « working on it » then it redirects to a page with my iframes but none of the tiles load.

    I’ve reverified my embed urls from apiary and even tried loading them directly in the browser, but I only get spinning loding symbols that way, no data.

    Any ideas?

    J’aime

Répondre à Marc Hoogendoorn Annuler la réponse.