Skip to main content
This guide walks you through adding GBGBridge to your web project, configuring it, and loading your first web-based identity journey inside an iframe.

Requirements

Installation

GBGBridge is published as two npm packages — the core library and a React wrapper. Install one or both:
Availability: these packages will publish to public npm via GGO-13991. The SDK source lives in the reference build under packages/ until the public package is available — clone the repo and link the packages into your app with npm link (or your package manager’s equivalent).
Both packages are ES modules and ship TypeScript declarations. No build configuration beyond standard bundler defaults is required.

Minimal Integration (React)

The steps below take you from an empty screen to a running journey: track the iframe element, declare the capabilities you support, register handlers, and render the provider.

1. Add the Imports

2. Track the Iframe Element

BridgeHostProvider needs the actual HTMLIFrameElement, not a ref. Hold it in component state and pass setIframe as the iframe’s ref callback:
This pattern is required, not stylistic. useRef is not reactive, so the provider’s host-creation effect would not fire when the iframe mounts.

3. Declare the Capabilities You Support

Pass a capabilities map to the provider. Each entry tells the embedded journey “the host can fulfil this”:
This is the declaration half of the two-step pattern. Capability IDs are listed in CAPABILITY_IDS — use the constants to avoid string typos.

4. Register Handlers

Register a handler for each capability action. useBridgeCapability registers on mount and unregisters on unmount; the action ID is the verb (e.g. "camera.document.capture"), not the capability ID ("camera.document"):
The handler receives the inbound BridgeMessage and a BridgeResponder. Call exactly one terminal method on the responder — success, error, cancelled, or unsupported — to send the response. acknowledge() is optional and may be called before the terminal response for long-running operations.

5. Render the Provider and Iframe

Put it all together:

6. Run Your App

Start your dev server. The journey loads inside the iframe. When it sends a capability.query request, GBGBridge automatically responds with the capabilities map you declared, including permissionState if set. When the journey invokes camera.document.capture, your handler runs and the responder returns the result.

Alternative: Framework-agnostic (Vanilla JS / Vue / Angular / Svelte)

If you’re not using React, use the core @gbg/go-bridge-web package directly. The API is identical to what the React wrapper exposes — the wrapper is a thin React adapter, not a separate runtime.
The same BridgeHost class powers the React wrapper internally — BridgeHostProvider instantiates it and handles detach() on unmount automatically. With direct usage, you own the lifecycle: call host.detach() when the iframe is no longer in use.

What Happens Under the Hood

When you mount BridgeHostProvider (or call new BridgeHost(...)):
  1. Iframe attached — The provider holds off until iframe is non-null. Once attached, it instantiates the underlying BridgeHost and snapshots the allowedOrigins, hostVersion, and capabilities props. Only an iframe change triggers a rebuild — remount the provider to apply runtime config changes.
  2. Message listener installed — A single window message listener is attached. Every inbound event is filtered: event.source must equal iframe.contentWindow, and event.origin must normalize to a value in allowedOrigins. Events that fail either check are silently dropped.
  3. Envelope validation — Surviving events are validated against the wire protocol: required fields (version, correlationId, type, timestamp, payload.action) must be present and well-typed. Malformed envelopes are silently dropped — they never reach handlers or the delegate.
  4. Capability query auto-registration — A built-in CapabilityQueryHandler is registered for the capability.query action. The handler reads the effective capability map (your capabilities prop merged with any registerCustomCapability(...) calls) and responds automatically. You do not register this yourself.

Required Page Configuration

GBGBridge runs entirely in your page; there is no global config. However, the iframe and your hosting page need a few things wired up so the browser delegates the right permissions and the SDK can reach the journey origin.

Content Security Policy

If your page sets a CSP, allow the journey origin in frame-src:
If the journey URL might come from multiple origins (staging vs prod), list each one explicitly. Avoid frame-src * in production.

Iframe allow Attribute

For capabilities that require browser permissions (camera, microphone, location), set the iframe allow attribute so the parent grants those permissions to the iframe context:
This is required even when you’re handling capture in the host page — the journey may still call getUserMedia for preview frames or fallback flows.

Origin Allowlist Format

Pass exact origin strings to allowedOrigins. Format: <scheme>://<host> with no trailing slash, no path, no port if it’s the scheme default.
The SDK normalizes inbound origins before comparing, so case differences in the host are tolerated, but non-default ports and paths must match exactly. Empty allowedOrigins arrays throw at construction time — there is no implicit “allow all”.

HTTPS in Production

Browsers block mixed content: an https:// parent page loading an http:// iframe will fail silently in most modern browsers. Always serve the journey over HTTPS in production. Local development on http://localhost works in both directions because browsers treat localhost as secure.

Common Integration Pitfalls

A handful of issues catch most teams when first wiring up the bridge — usually around the two-step declare-then-register pattern, the iframe-as-state pattern, and origin allowlist formatting.

Capability query returns the wrong shape

If the embedded journey calls bridge.hasCapability("camera.document") and gets false even though you’ve registered a handler, you forgot to pass capabilities to the provider. useBridgeCapability only registers the handler — it does not declare the capability. Both calls are required. See Concepts → Declaring vs. Registering.

Provider never builds the host

If host is null forever, you’re probably using useRef instead of useState for the iframe. Refs are not reactive, so the provider’s useEffect watching iframe never sees a change. Use const [iframe, setIframe] = useState<HTMLIFrameElement | null>(null) and pass setIframe as the iframe’s ref callback.

Messages dropped silently

The transport layer drops inbound messages on three independent checks: event.source not matching iframe.contentWindow, origin not in allowedOrigins, and envelope validation failure. None of these surface to the delegate or lastError — they’re filtered defensively. Common causes:
  • Trailing slashes or paths in allowedOrigins entries (must be exact origin strings).
  • Inbound port differs from declared origin (e.g. :443 vs default).
  • Journey URL pointing at a redirect — iframe.contentWindow ends up on a different origin than the declared src.
  • Web journey sending a non-conforming envelope (missing correlationId, malformed payload.action, etc.).
To debug, attach a delegate.onMessage callback — it fires after validation, so absence indicates pre-validation drop. If you need to inspect rejected events, you’ll need to temporarily attach your own window.addEventListener("message", ...) outside the SDK.

Action vs capability ID confusion

The protocol uses two related strings:
  • Capability ID (camera.document) — appears in the capabilities prop and capability.query responses.
  • Action ID (camera.document.capture) — appears in useBridgeCapability(...), registerHandler(...), and inbound request payload.action.
Register handlers for action IDs, declare support for capability IDs. They’re related but distinct strings.

Runtime config changes don’t apply

BridgeHostProvider snapshots allowedOrigins, hostVersion, and capabilities when the underlying BridgeHost is built (i.e., when iframe transitions from null to non-null). Subsequent prop changes do not rebuild the host. To apply runtime changes — adding a new allowed origin, updating capabilities — unmount and remount the provider (key={...} change is the easiest way), or call host.registerCustomCapability(...) directly for dynamic capability additions.

Outbound messages dropped before iframe.src is set

HostIframeChannel resolves targetOrigin from iframe.src at send time. If iframe.src is empty when host.sendEvent(...) or host.respond(...) fires, the channel cannot resolve a target and silently drops the outbound with a console.warn. In vanilla JS, set iframe.src before the first outbound send. In React, this is automatic — the iframe renders with its src attribute already set.

Next Steps

  • Concepts — Understand the architecture, message protocol, and design rationale.
  • Embedding — Patterns for React, framework-agnostic, and SSR-aware integrations.
  • Capability Handling — Declaring, registering, and dynamic capability negotiation.
  • Security — CSP, origin allowlist, transport safety, and token-exchange patterns.
  • API Reference — Detailed reference for every public symbol.