Bridgewise Article
Home / Developer Documentation / Widgets Integration / Widget Integration Guide
</>

Developer Documentation

Widget Integration Guide

Learn how to embed your custom financial widget into your application using an iframe.

1 Overview

This guide shows you how to embed your custom financial widget into your application using an iframe. Your widget is accessible via a single URL that handles data fetching, theming, and emits real-time events back to your application.

What you can do:

• Embed the widget using a simple iframe

• Configure language, theme, security identifiers, and user behavior

• Listen to widget events (load, resize, user interactions, errors)

• Handle security selections in your application (when enabled)

• Auto-resize the widget based on content

2 Quick Start

Basic iframe integration with auto-resize:

HTML
<iframe
  id="widget"
  src="https://embeded.bridgewise.com/en-US/TENANT_NAME/WIDGET_NAME?accessToken=YOUR_TOKEN&identifier=IDENTIFIER"
  style="width:100%; border:0; height:400px;"
>
</iframe>

<script>
  window.addEventListener("message", function (event) {
    if (event.origin !== "https://embeded.bridgewise.com") return;

    try {
      const message = JSON.parse(event.data);
      if (message.event && message.data && message.data.height) {
        document.getElementById("widget").style.height =
          message.data.height + "px";
      }
    } catch (e) {
      // Ignore invalid messages
    }
  });
</script>

3 URL Structure

All widgets share the same base URL structure:

https://embeded.bridgewise.com/{language}/{tenant}/{widgetName}?accessToken=...&identifier=...&identifierType=...&mode=...&actionType=...&sessionId=...&userId=...&scoringMethod=...

Path Parameters

NameRequiredFormatDescription
languageNoen-US, he-ILUI language (BCP-47 locale), defaults to en-US
tenantYesYour assigned tenant nameTenant namespace provided to you
widgetNameYesstock-report-page / fund-report-pageWhich widget to render

Query Parameters

NameRequiredDefaultDescription
accessTokenYesBearer token used by widgets for data requests
identifierRecommendede.g. AAPL-Nasdaq, 24937The security/fund identifier for data
identifierTypeConditionalticker_exchange / ISINIdentifier type for stock widgets
modeNolight (default) / darkTheme mode
actionTypeNodefault / external / preventControls click behavior on securities
sessionIdYesSession identifier to correlate analytics
userIdYesUser identifier to correlate analytics
i Authentication Required

To start integrating widgets, you'll need an access token. Please follow the instructions in our Authentication Guide to generate your token.

4 Widget-Specific Properties

The following properties are specific to certain widgets:

ParameterRequiredDefaultDescription
userNameNoThe name of the user for personalized interactions
defaultMessageNoDefault prompt message for widget chat interface

5 Selection Behavior (actionType)

The actionType parameter controls how the widget handles clicks on links and securities.

actionTypeBehavior
defaultSelection will redirect to the report page on BridgeWise platform
externalWidget emits on-security-select-<widgetName> event; host app handles navigation
preventClicks are ignored for navigation; no selection event is emitted

6 Events & postMessage

Widgets send JSON-serialized messages to window.parent via postMessage. Each message has this format:

Message Format
{
  "event": "on-<eventName>-<widgetName>",
  "type": "<eventName>",
  "widget": "<widgetName>",
  "data": { ... }  // event-specific payload
}

Event Types

Status Events

load { height: number }

Widget fully loaded; provides suggested height.

resize { height: number }

Content height changed; use for auto-resize.

success { height: number }

Successful state update (e.g., answer rendered).

error { message, status, data?, height }

Error inside the widget or underlying services.

Interaction Events

click { id: string, ... }

Click events (clipboard, disclaimer, etc.).

hover { id: string, ... }

Hover events (where supported).

link-click { url: string, text?: string }

Emitted when onLinkClick callback is provided.

Selection Events

security-select { id, ticker?, exchange?, type }

Emitted only when actionType=external.

Click Event Payload

When a user clicks an actionable control inside a widget (for example a call-to-action button), the widget emits an on-click message via postMessage. The event suffix, the widget value, and the data.id vary depending on the widget and the specific control that was clicked.

For example, the restricted widget served from https://embedded.bridgewise.com/en-US/client/restricted emits a message like the one below. The data.id value (here deposit_now) is defined per client as part of a specific customization — it is not a fixed Bridgewise value:

Click Event Example
{
  "event": "on-click-restricted",
  "type": "click",
  "widget": "restricted",
  "data": { "id": "deposit_now" }
}
i Handling Click Events

Match on type === "click" and branch on data.id to trigger the corresponding action in your application (e.g., open a deposit flow). Do not assume a fixed widget name or id — both are widget-specific.

Event Handler Example

JavaScript
window.addEventListener("message", function (event) {
  if (event.origin !== "https://embeded.bridgewise.com") return;

  try {
    const message = JSON.parse(event.data);

    // Auto-resize
    if (message.data && message.data.height) {
      document.getElementById("widget").style.height =
        message.data.height + "px";
    }

    // Handle click events (id is widget-specific)
    if (message.type === "click") {
      const { id } = message.data;
      console.log("Clicked:", id);
    }

    // Handle security selection
    if (message.type === "security-select") {
      const { ticker, exchange } = message.data;
      console.log("Security selected:", ticker, exchange);
    }

    // Handle errors
    if (message.type === "error") {
      console.error("Widget error:", message.data);
    }
  } catch (e) {
    // Ignore invalid messages
  }
});

7 Theming and Styling

?

Theming

  • Set mode=dark for dark theme
  • Use width:100% and border:0
  • Rely on resize events for height
?

Localization

  • Set language via path: en-US, he-IL
  • Widget may fall back to defaults
⚠️

Error Handling

  • Invalid tenant/widget shows error screen
  • Listen for error events
?

Security

  • Validate event.origin
  • Use short-lived tokens
  • Never log tokens in plain text

8 iOS Integration (SwiftUI/UIKit)

For iOS apps, embed the widget using WKWebView with proper postMessage handling:

? Swift
struct WidgetView: UIViewRepresentable {
  @Binding var height: CGFloat
  let widgetURL: String

  func makeUIView(context: Context) -> WKWebView {
    let config = WKWebViewConfiguration()
    let controller = WKUserContentController()
    
    // Bridge postMessage -> webkit messageHandler
    let script = """
      window.addEventListener('message', function(e) {
        if (e.origin !== 'https://embeded.bridgewise.com') return;
        webkit.messageHandlers.postMessage.postMessage(e.data);
      }, false);
    """
    controller.addUserScript(WKUserScript(
      source: script,
      injectionTime: .atDocumentStart,
      forMainFrameOnly: false
    ))
    config.userContentController = controller
    
    let webView = WKWebView(frame: .zero, configuration: config)
    webView.load(URLRequest(url: URL(string: widgetURL)!))
    return webView
  }
}

Key Points for iOS

• Use WKWebView with WKUserContentController for postMessage handling

• Inject JavaScript to bridge iframe postMessage to webkit messageHandler

• Handle height changes to dynamically resize the widget

• Validate message origin for security

• Disable WebView scrolling if you want the widget to control its own height

9 Android Integration (WebView)

For Android apps, use WebView with JavaScript interface to handle postMessage events:

? Kotlin
class WidgetWebView @JvmOverloads constructor(
  context: Context,
  attrs: AttributeSet? = null
) : WebView(context, attrs) {

  init {
    setupWebView()
  }

  @SuppressLint("SetJavaScriptEnabled")
  private fun setupWebView() {
    settings.apply {
      javaScriptEnabled = true
      domStorageEnabled = true
    }

    // Add JavaScript interface for postMessage handling
    addJavascriptInterface(PostMessageHandler(), "AndroidInterface")

    webViewClient = object : WebViewClient() {
      override fun onPageFinished(view: WebView?, url: String?) {
        super.onPageFinished(view, url)
        
        // Inject JavaScript to capture iframe postMessage
        val script = """
          window.addEventListener('message', function(event) {
            if (event.origin !== 'https://embeded.bridgewise.com') return;
            AndroidInterface.handlePostMessage(JSON.stringify(event.data));
          }, false);
        """
        evaluateJavascript(script, null)
      }
    }
  }

  inner class PostMessageHandler {
    @JavascriptInterface
    fun handlePostMessage(messageData: String) {
      // Parse and handle messages
    }
  }
}

Key Points for Android

• Enable JavaScript and DOM storage in WebView settings

• Use @JavascriptInterface to create a bridge for postMessage handling

• Inject JavaScript after page load to capture iframe messages

• Convert pixel heights using display density for proper sizing

• Handle events on the main thread using post()

10 Mobile Integration Notes

?

Responsive Design

Widget automatically adapts to mobile viewports.

?

External Navigation

Use actionType=external to keep users in your app.

⚠️

Error Handling

Listen for error events for network/auth issues.

?

Secure Storage

Use iOS-size: 14px;">• Embed the widget using a simple iframe