Using WordPress? Every integration here is also available as a plugin. Browse the plugin store →

Knowledge base WordPress plugins Embedding

Embedding Power BI Reports in WordPress

The [o365_powerbi] shortcode: the attributes it reads, the token it needs before it renders anything, and the error strings it prints when one of those is missing.

Published 12 August 2026

  • power-bi
  • reports
  • dashboards
  • embedding
  • shortcode
  • o365

The Office 365 Power Bi plugin (o365-powerbi, version 4.5) registers one shortcode, [o365_powerbi], which renders a Power BI report or dashboard tile into a page using Microsoft’s powerbi-client library (v2.11.0 is bundled with the plugin).

Everything below is drawn from the plugin’s own source. Where the plugin prints a particular string on failure, that string is quoted exactly — searching this page for the message you are seeing is the fastest way to find the cause.

Before the shortcode will render anything

The shortcode checks three things, in this order, and stops at the first one that fails. They have to be done in the same order.

1. The o365 base plugin must be active. Activation of the Power BI plugin calls is_plugin_active('o365/o365.php'). If the base plugin is not active, activation is aborted and WordPress dies with “This plugin requires o365 base plugin.” If the base plugin’s own o365_base_plugin_is_verify option is 0, activation instead dies with “ERROR: This plugin needs to be configured on the settings page >> General tab, before proceeding.”

2. The licence key must be activated. On successful activation the plugin sets o365_powerbi_verify_auth to false, and the shortcode refuses to do anything while that option is false or empty — it prints:

Error: Please enter the Office 365 Powerbi Plugin activation key.

An admin notice with a link to wp-admin/admin.php?page=o365_license says the same thing. Enter the key on that page against Office 365 Powerbi and press Activate. The key is checked against https://api.wpintegrate.com/check_key_updates.php; on a bad key the field shows “Please enter valid key.” On success the key is stored in o365_powerbi_lcode and o365_powerbi_verify_auth becomes yes.

3. A Power BI access token must exist. Without one, the shortcode prints:

Error: Power BI access token required.

Getting that token is the next section.

Getting the Power BI access token

The plugin reads the Azure application credentials from the base plugin’s o365_settings option — the client_id and client_secret keys — so the app registration is configured on the base plugin’s settings page, not here.

The Power BI plugin adds its own row, Office 365 Power BI Report, to the token manager on wp-admin/admin.php?page=o365_settings. Press Get Access Token there and the browser is sent to:

https://login.microsoftonline.com/common/oauth2/authorize
  ?client_id=<your client id>
  &redirect_uri=<your site>/wp-admin/
  &response_type=code%20id_token
  &scope=openid%20profile
  &response_mode=form_post
  &state=o365_powerbi_state
  &nonce=<generated>
  &resource=https://analysis.windows.net/powerbi/api

Three things in that URL matter when you register the Azure application:

  • The resource is https://analysis.windows.net/powerbi/api — this is the v1.0 endpoint, which asks for a resource rather than a scope list. The only scope requested at the authorize step is openid profile; the Power BI permissions themselves come from the permissions granted to the app registration in Azure.
  • The redirect URI is admin_url('/') — your site’s /wp-admin/ URL, exactly as WordPress generates it. It must be registered on the Azure app or Microsoft will reject the sign-in before the plugin ever sees it. Note that it is /wp-admin/, not a plugin-specific callback.
  • The response mode is form_post, so the authorization code comes back as a POST to /wp-admin/. The plugin picks it up on the init hook, and only when the posted state equals o365_powerbi_state.

The code is then exchanged at https://login.microsoftonline.com/common/oauth2/token and you are redirected back to the settings page with “Successfully get Azure access token” or, if the response contained no access_token, “Error while getting access token”.

The token, its expiry and the refresh token are stored as three WordPress options: o365_power_bi_access_token, o365_power_bi_access_token_expires and o365_power_bi_refresh_token. On every init, if a token exists and expires within the next 300 seconds, the plugin silently exchanges the refresh token for a new one. Once a token exists the button on the settings page becomes Revoke Token.

While no token exists, every admin page carries the notice “Office 365 Power Bi Plugin doesn’t have an access token.” with a link to the token manager.

The shortcode

The plugin’s own settings screen documents the minimum form as:

[o365_powerbi groupid="" reportid="" width="" height="" parameters="&temp1=state&temp2=counutry"]

with Group ID and Report ID listed as the compulsory attributes. groupid is the Power BI workspace ID; omit it and the shortcode prints “Error: Group ID missing from shortcode. Please contact to site administrator.”

Attributes

AttributeDefaultWhat it does
groupidPower BI workspace (group) ID. Required.
reportidReport ID. Used as the embed id, as the bookmark storage key, and in the export URL.
dashboardid + tileidSet both to embed a dashboard tile instead of a report.
width100%Applied as width on the embed iframe.
height300pxApplied as min-height on the embed iframe.
parametersAppended verbatim to the embed URL, e.g. &temp1=state&temp2=country.
filterpanenoyes sets filterPaneEnabled.
navpanenoyes sets navContentPaneEnabled.
fullscreenyesShows the expand/contract buttons in the top bar.
printnoyes shows a print button, which calls the client library’s print().
bookmarknoyes shows the bookmarks panel.
exportnoyes shows the export button. Requires expapiurl as well.
expapiurlBase URL of your export API. The download link is built as <expapiurl>?reportId=…&groupId=….
pagesComma-separated Power BI page names. Each name that matches a real page is appended to the export URL as &pages=<name>. The whole attribute value is also passed straight through as the embed’s pageName, which expects a single page name — so use one value if you are relying on that.
exportpreloaderyes shows a spinner while the export runs.
preloadertextDownloading...Text beside that spinner.
preloaderURL of an image shown as a loading overlay until the report fires its loaded event.
hidesysreportHides report bookmarks whose display name contains this string.
styleRaw CSS injected into the .o365_powerbi_report_container iframe rule.

What the rendered page loads

Rendering the shortcode injects, per instance: jQuery 3.5.1 from ajax.googleapis.com, the Office UI Fabric core stylesheet from cdn.jsdelivr.net, the plugin’s jquery.fullscreen.min.js and powerbi_custom.css, and the bundled powerbi.js. If your site blocks third-party CDNs, the icons in the top bar and the fullscreen behaviour are the parts that break.

Bookmarks

With bookmark="yes" the shortcode renders a collapsible BOOKMARKS panel with two lists: Report bookmarks, read from the report itself through the client library’s bookmarksManager, and Personal bookmarks, which only appear for a logged-in user.

Personal bookmarks are saved through the o365_save_powerbi_user_bookmarks admin-ajax action into user meta under the key powerbi_bookmarks-<reportid>-<blogid> — so they are per user, per report and per site on multisite. The panel’s rename, delete and share actions all go through the same endpoint.

Share builds a link by truncating the current URL at its last / and appending ?bookmarkname=<bookmark name>. On load, the shortcode reads that same bookmarkname query parameter and applies the matching bookmark’s state, so a shared link opens on the shared view.

Troubleshooting

“Error: Please enter the Office 365 Powerbi Plugin activation key.”o365_powerbi_verify_auth is false or empty. Activate the licence key on the o365_license page. Note that deactivating the plugin deletes both o365_powerbi_lcode and o365_powerbi_verify_auth, so a deactivate/reactivate cycle always requires re-entering the key.

“Error: Group ID missing from shortcode.”groupid is absent or empty. This check is on groupid only; a missing reportid does not produce its own message.

“Error: Power BI access token required.”o365_power_bi_access_token is empty. Either you have never fetched a token, or a refresh failed. The refresh path writes nothing when the response contains no access_token and reports nothing to the screen, so a silently expired credential presents as this message appearing one day on a page that worked yesterday. Re-run Get Access Token.

“cURL Error #: …” — the call to https://api.powerbi.com/v1.0/myorg/groups/<groupid>/reports/ failed at the transport level. The message printed is the raw cURL error. Firewalls and outbound-request blocks show up here.

“Something went wrong or API has no results. Please contact to site administrator.” — the same call returned an empty body. In practice this is an authorization failure against the workspace, or a groupid that does not exist.

The wrong report renders. This is the one to know about. For a report embed the plugin lists all reports in the workspace and takes the embed URL of the first one returned, while passing your reportid as the embed’s id. In a workspace with one report the two agree. In a workspace with several they may not, and the symptom is a report that loads but is not the one you asked for. The reliable fix is one workspace per embedded report; there is no attribute that overrides the chosen embed URL.

The export button downloads nothing. The download URL is only built when export and expapiurl are both set. With export="yes" and no expapiurl the button renders with an empty link. Note also that expapiurl points at an export API you host — the plugin builds and links the URL, it does not perform the export.

hidesysreportbyname has no effect. The attribute is parsed but the parsed list is not the array handed to the browser; the array that reaches the bookmark-filtering code is always empty. Only hidesysreport, which filters on a substring of the bookmark’s display name, actually removes anything.

A single personal bookmark does not appear in the list. The personal list is only built when more than one bookmark is stored for that report; with exactly one saved, the panel renders empty until a second is added.

Updates

The plugin checks https://api.wpintegrate.com/plugins_update_api_conn.php for its own updates, so an activated licence also keeps the plugin current through the normal WordPress updates screen. Version 4.5 declares a minimum of WordPress 5.0 and is tested to 5.9.1.

Read next

Back to the knowledge base