Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.go.gbgplc.com/llms.txt

Use this file to discover all available pages before exploring further.

A step-by-step walkthrough from zero to a working GBGBridge integration. Follow this page in order; each step links to the detailed guide if you need more context.

Prerequisites

  • Xcode 15.0+ with Swift 5.9+
  • An iOS project targeting iOS 15.0+
  • Access to the GBGBridge SPM package or XCFramework
  • A journey URL from the GBG Go Core SDK (see Journey URL)

Step 1: Add the SDK

Add GBGBridge via Swift Package Manager:
  1. Navigate to File > Add Package Dependencies…
  2. Enter the GBGBridge package URL.
  3. Select Up to Next Major Version from 1.0.0.
  4. Click Add Package and ensure GBGBridge is linked to your app target.
Alternatively, drag the GBGBridge.xcframework into your project and set it to Embed & Sign.

Step 2: Obtain a journey URL

Your app needs a journey URL to load inside the bridge WebView. This URL is generated server-side using the GBG Go Core SDK β€” your backend calls the Core SDK, receives a session URL, and passes it to the iOS app.
See Journey URL for the full pattern, including URL shape, authentication, and configuration options.

Step 3: Add Info.plist entries

Add usage descriptions for any device capabilities your integration uses:
<!-- Required for document and selfie capture -->
<key>NSCameraUsageDescription</key>
<string>Camera access is required for document capture.</string>

<!-- Optional: if using photo library fallback -->
<key>NSPhotoLibraryUsageDescription</key>
<string>Photo library access is used to select document images.</string>

<!-- Optional: if using NFC -->
<key>NSNFCReaderUsageDescription</key>
<string>NFC is used to read identity document chips.</string>
For NFC, also add the Near Field Communication Tag Reading capability in Signing & Capabilities.

Step 4 β€” Initialize BridgeHost

Create a BridgeHost β€” this is the coordinator that routes messages between the WebView and your native code.
import GBGBridge

@StateObject private var host = BridgeHost(hostVersion: "1.0.0")

Step 5: Set up capture handlers

Attach handlers to the typed capability slots. Setting a handler declares that your app supports that capability β€” no separate configuration step.

Option A: Stub Views (Development / Early Integration)

Use the built-in stub views to prove the bridge works without the SmartCapture SDKs:
host.documentCapture.handler = { [weak host] request in
    guard let host else { return .cancelled(reason: "Host deallocated") }
    return await host.documentCapture.awaitCompletion()
}

host.selfieCapture.handler = { [weak host] request in
    guard let host else { return .cancelled(reason: "Host deallocated") }
    return await host.selfieCapture.awaitCompletion()
}
Then present the stub views when a request arrives:
.fullScreenCover(isPresented: $showDocumentCamera) {
    StubDocumentCameraView(
        onCaptured: { result in
            host.documentCapture.complete(.document(result))
        },
        onCancelled: {
            host.documentCapture.complete(.cancelled(reason: "User dismissed"))
        }
    )
}

.fullScreenCover(isPresented: $showSelfieCamera) {
    StubSelfieCameraView(
        onCaptured: { result in
            host.selfieCapture.complete(.selfie(result))
        },
        onCancelled: {
            host.selfieCapture.complete(.cancelled(reason: "User dismissed"))
        }
    )
}
See Stub Camera Views for details on the stubs and how to swap them for real SDKs.

Option B: SmartCapture SDKs (Production)

Replace the stub views with the GBG SmartCapture document and face camera SDKs. The handler setup is identical β€” only the view presented inside fullScreenCover changes.
See the SmartCapture Integration Guide (coming soon) for the full walkthrough.

Step 6: Set permission state

Report camera permission state so the web journey can check permissions before attempting capture:
let camera = CameraDetector.check()
host.documentCapture.permissionState = camera.permissionState
host.selfieCapture.permissionState = camera.permissionState

Step 7: Display the journey

Use BridgeWebView to load the journey URL. It handles WebView creation, bootstrap script injection, and message handler registration automatically.
struct JourneyView: View {
    @StateObject private var host = BridgeHost(hostVersion: "1.0.0")
    let journeyURL: URL

    var body: some View {
        BridgeWebView(url: journeyURL, host: host)
            .onAppear { setupHandlers() }
            .onChange(of: host.documentCapture.activeRequest?.correlationId) { _ in
                showDocumentCamera = host.documentCapture.activeRequest != nil
            }
            .onChange(of: host.selfieCapture.activeRequest?.correlationId) { _ in
                showSelfieCamera = host.selfieCapture.activeRequest != nil
            }
            // Present camera views as fullScreenCovers (see Step 5)
    }
}
See Embedding Guide for SwiftUI and UIKit integration patterns.

Step 8 β€” Build and Run

  1. Build and run on a physical device (camera capture requires real hardware).
  2. The web journey loads in the WebView.
  3. When the journey reaches a document or selfie step, the bridge sends a capture request.
  4. Your handler runs, the camera view presents, the user captures, and the result flows back to the web journey.

Verify It Works

Check for these signs of a successful integration:
  • The web journey loads and renders correctly in the WebView.
  • capability.query is handled automatically β€” the journey knows which capabilities your app supports.
  • Document capture requests trigger your camera view, and the captured image is returned to the journey.
  • Selfie capture requests trigger your selfie view, and the result is returned.
  • Cancellation flows work β€” dismissing the camera sends a cancelled response.

Common Issues

SymptomLikely CauseFix
Blank WebViewATS blocking HTTP URLUse HTTPS, or add NSAllowsLocalNetworking for local dev
capability.query returns emptyNo handlers setSet handler on at least one typed slot before loading the URL
Camera view never appearsactiveRequest not observedWire up .onChange(of: host.documentCapture.activeRequest)
Capture result not received by journeycomplete() not calledEnsure your camera view calls host.documentCapture.complete() on every exit path
See Troubleshooting for a comprehensive diagnostic guide.

Complete Minimal Example

Putting it all together β€” a minimal SwiftUI app that loads a journey and handles document capture with a stub view:
import GBGBridge
import SwiftUI

struct JourneyView: View {
    @StateObject private var host = BridgeHost(hostVersion: "1.0.0")
    @State private var showDocumentCamera = false
    let journeyURL: URL

    var body: some View {
        BridgeWebView(url: journeyURL, host: host)
            .onAppear {
                let camera = CameraDetector.check()
                host.documentCapture.permissionState = camera.permissionState

                host.documentCapture.handler = { [weak host] request in
                    guard let host else { return .cancelled(reason: "Host deallocated") }
                    return await host.documentCapture.awaitCompletion()
                }
            }
            .onChange(of: host.documentCapture.activeRequest?.correlationId) { _ in
                showDocumentCamera = host.documentCapture.activeRequest != nil
            }
            .fullScreenCover(isPresented: $showDocumentCamera, onDismiss: {
                if host.documentCapture.activeRequest != nil {
                    host.documentCapture.complete(.cancelled(reason: "Dismissed"))
                }
            }) {
                StubDocumentCameraView(
                    onCaptured: { result in
                        host.documentCapture.complete(.document(result))
                    },
                    onCancelled: {
                        host.documentCapture.complete(.cancelled(reason: "User dismissed"))
                    }
                )
            }
    }
}
See Hello Journey for the full annotated example.

What’s Next

Once the basic integration is working:
  • Add selfie capture β€” same pattern as document capture, using host.selfieCapture.
  • Add custom capabilities (NFC, biometrics) β€” see Capability Handling.
  • Replace stub views with SmartCapture SDKs for production-quality capture.
  • Review the Security Guide before shipping to production.