Back to Blog
3 min read

Power BI Embedded: Analytics in Your Applications

Power BI Embedded integrates interactive reports into your applications. White-label analytics for SaaS products, internal portals, and customer-facing dashboards.

Embedding Scenarios

ScenarioAuthenticationUse Case
App Owns DataService PrincipalSaaS multi-tenant
User Owns DataAzure ADInternal apps

Creating Embedded Capacity

# Create Power BI Embedded capacity
az powerbi embedded-capacity create \
    --name myembedded \
    --resource-group myRG \
    --location eastus \
    --sku-name A1 \
    --administrators admin@company.com

App Owns Data Setup

Register Azure AD Application

# Register app
az ad app create \
    --display-name "PowerBI-Embed-App" \
    --sign-in-audience AzureADMyOrg

# Create service principal
az ad sp create --id <app-id>

# Add to Power BI Admin (Azure Portal)

Authenticate and Get Token

public async Task<string> GetPowerBIToken()
{
    var app = ConfidentialClientApplicationBuilder
        .Create(_config["AzureAd:ClientId"])
        .WithClientSecret(_config["AzureAd:ClientSecret"])
        .WithAuthority($"https://login.microsoftonline.com/{_config["AzureAd:TenantId"]}")
        .Build();

    var scopes = new[] { "https://analysis.windows.net/powerbi/api/.default" };
    var result = await app.AcquireTokenForClient(scopes).ExecuteAsync();

    return result.AccessToken;
}

Get Embed Config

public async Task<EmbedConfig> GetEmbedConfig(Guid workspaceId, Guid reportId)
{
    var token = await GetPowerBIToken();
    var client = new PowerBIClient(new TokenCredentials(token));

    // Get report
    var report = await client.Reports.GetReportInGroupAsync(workspaceId, reportId);

    // Generate embed token
    var generateTokenRequest = new GenerateTokenRequest(
        accessLevel: "View",
        allowSaveAs: false
    );
    var embedToken = await client.Reports.GenerateTokenInGroupAsync(
        workspaceId, reportId, generateTokenRequest);

    return new EmbedConfig
    {
        EmbedUrl = report.EmbedUrl,
        EmbedToken = embedToken.Token,
        ReportId = reportId,
        TokenExpiry = embedToken.Expiration
    };
}

JavaScript Embedding

<div id="reportContainer" style="height: 600px;"></div>

<script src="https://cdn.jsdelivr.net/npm/powerbi-client@2.18.0/dist/powerbi.min.js"></script>
<script>
    async function embedReport() {
        const config = await fetch('/api/embed-config').then(r => r.json());

        const embedConfig = {
            type: 'report',
            id: config.reportId,
            embedUrl: config.embedUrl,
            accessToken: config.embedToken,
            tokenType: pbi.models.TokenType.Embed,
            settings: {
                panes: {
                    filters: { visible: false },
                    pageNavigation: { visible: true }
                },
                background: pbi.models.BackgroundType.Transparent
            }
        };

        const reportContainer = document.getElementById('reportContainer');
        const powerbi = new pbi.service.Service(
            pbi.factories.hpmFactory,
            pbi.factories.wpmpFactory,
            pbi.factories.routerFactory
        );

        const report = powerbi.embed(reportContainer, embedConfig);

        report.on('loaded', function() {
            console.log('Report loaded');
        });

        report.on('error', function(event) {
            console.error('Error:', event.detail);
        });
    }

    embedReport();
</script>

Row-Level Security

// Generate token with RLS
var generateTokenRequest = new GenerateTokenRequest(
    accessLevel: "View",
    identities: new List<EffectiveIdentity>
    {
        new EffectiveIdentity(
            username: user.Email,
            roles: new List<string> { "SalesRegion" },
            datasets: new List<string> { datasetId.ToString() }
        )
    }
);

Multi-Tenant Architecture

┌────────────────────────────────────────────┐
│           Your SaaS Application            │
└───────────────────┬────────────────────────┘

        ┌───────────┴───────────┐
        │                       │
   ┌────┴────┐            ┌────┴────┐
   │Tenant A │            │Tenant B │
   │Workspace│            │Workspace│
   │Reports  │            │Reports  │
   │Dataset  │            │Dataset  │
   └─────────┘            └─────────┘

Capacity SKUs

SKUvCoresRAMCost/hr
A113 GB~$1.00
A225 GB~$2.00
A3410 GB~$4.00
A4825 GB~$8.00

Power BI Embedded: branded analytics at scale.

Michael John Peña

Michael John Peña

Senior Data Engineer based in Sydney. Writing about data, cloud, and technology.