Skip to content

Integration

Step 1: Add SDK and Configure Permissions

Add the SDK Dependency:

Option A: Swift Package Manager

  1. File > Add Package Dependencies
  2. Enter the package URL (to be published)

Option B: XCFramework

Download the XCFramework and add it to your project's Frameworks, Libraries, and Embedded Content.

Configure Info.plist:

<key>NSCameraUsageDescription</key>
<string>Camera access is needed to capture your photo for virtual try-on</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Photo library access is needed to select photos for virtual try-on</string>

Step 2: Add Config and Initialize SDK

Create GlanceConfig.swift in Xcode: File > New > File > Swift File

import Foundation
import GlanceChatSDK

struct GlanceConfig {
    // Partner credentials (provided by Glance)
    static let partnerId = "provided-by-glance"
    static let storeHandle = "provided-by-glance"
    static let tenantId = "provided-by-glance"
    static let environment = GlanceChatConfig.Environment.development

    // Firebase Configuration (provided by Glance)
    static let firebaseProjectId = "provided-by-glance"
    static let firebaseApiKey = "provided-by-glance"
    static let firebaseAuthDomain = "provided-by-glance"
    static let firebaseStorageBucket = "provided-by-glance"
    static let firebaseMessagingSenderId = "provided-by-glance"
    static let firebaseAppId = "provided-by-glance"

    // API Endpoints (provided by Glance)
    static let emberEndpoint = "provided-by-glance"
    static let bifrostEndpoint = "provided-by-glance"
    static let embedCdnEndpoint = "provided-by-glance"
    static let glanceAccountEndpoint = "provided-by-glance"
    static let webAuthUrl = "provided-by-glance"
    static let googleSsoClientId = "provided-by-glance"

    // Shopify Configuration (provided by Glance)
    static let shopifyBaseUrl = "provided-by-glance"
    static let defaultCollectionId = "provided-by-glance"

    // Branding (your values)
    static let brandName = "YOUR BRAND NAME"
    static let brandLogoUrl = "https://your-cdn.com/logo.png"
}

Important

Add GlanceConfig.swift to your .gitignore to avoid committing credentials.

Never inline config values

Always keep credentials in GlanceConfig.swift and reference them. Do NOT copy config values directly into your App entry point.

Initialize in your App struct:

import SwiftUI
import GlanceChatSDK

@main
struct YourApp: App {
    init() {
        initializeSDK()
    }

    private func initializeSDK() {
        do {
            let config = try GlanceChatConfig.Builder()
                .firebaseProjectId(GlanceConfig.firebaseProjectId)
                .firebaseApiKey(GlanceConfig.firebaseApiKey)
                .firebaseAuthDomain(GlanceConfig.firebaseAuthDomain)
                .firebaseStorageBucket(GlanceConfig.firebaseStorageBucket)
                .firebaseMessagingSenderId(GlanceConfig.firebaseMessagingSenderId)
                .firebaseAppId(GlanceConfig.firebaseAppId)
                .emberEndpoint(GlanceConfig.emberEndpoint)
                .bifrostEndpoint(GlanceConfig.bifrostEndpoint)
                .embedCdnEndpoint(GlanceConfig.embedCdnEndpoint)
                .environment(GlanceConfig.environment)
                .glanceAccountEndpoint(GlanceConfig.glanceAccountEndpoint)
                .googleSsoClientId(GlanceConfig.googleSsoClientId)
                .storeHandle(GlanceConfig.storeHandle)
                .webAuthUrl(GlanceConfig.webAuthUrl)
                .brandName(GlanceConfig.brandName)
                .brandLogoUrl(GlanceConfig.brandLogoUrl)
                .build()

            GlanceChatSDK.shared.initialize(partnerId: GlanceConfig.partnerId, config: config)
        } catch {
            print("SDK initialization failed: \(error)")
        }
    }

    var body: some Scene {
        WindowGroup {
            ZStack {
                ContentView()

                // SDK overlay — render last so it floats on top
                if GlanceChatSDK.shared.isInitialized {
                    GlanceChatOverlay()
                        .ignoresSafeArea()
                }
            }
            .onOpenURL { url in
                _ = GlanceChatSDK.shared.handleDeepLink(url)
            }
        }
    }
}

Note

The SDK creates its own Firebase instance. It will not conflict with your existing Firebase setup.

Step 3: Set Page Context

Call setPageContext() when users navigate to key screens so the AI can provide relevant responses.

Page Type When to Set Required Metadata
"PLP" Product listing / category page page_identifier, current_url, tenant_id
"PDP" Product detail page page_identifier, product_id, current_url, tenant_id
// Product List View
struct ProductListView: View {
    let collectionId: String

    var body: some View {
        ScrollView { /* content */ }
        .onAppear {
            GlanceChatSDK.shared.setPageContext("PLP", metadata: [
                "page_identifier": collectionId,
                "current_url": "\(GlanceConfig.shopifyBaseUrl)/collections/\(collectionId)",
                "tenant_id": GlanceConfig.tenantId
            ])
        }
    }
}

// Product Detail View
struct ProductDetailView: View {
    let product: Product

    var body: some View {
        ScrollView { /* content */ }
        .onAppear {
            GlanceChatSDK.shared.setPageContext("PDP", metadata: [
                "page_identifier": product.variantId,
                "product_id": product.variantId,
                "current_url": "\(GlanceConfig.shopifyBaseUrl)/products/\(product.handle)",
                "tenant_id": GlanceConfig.tenantId
            ])
        }
    }
}

Step 4: Handle Product Navigation (Optional)

Set up callbacks to handle product clicks from the chat interface:

// In your App init or after SDK initialization
GlanceChatSDK.shared.onProductClick = { product in
    // Navigate to product detail page
    print("Product clicked: \(product.id)")
}

GlanceChatSDK.shared.onDeeplinkClick = { deeplinkUrl in
    if let url = URL(string: deeplinkUrl) {
        UIApplication.shared.open(url)
    }
}

Step 5: Add Try-On Widget (Optional)

Add a "Try On" button to product cards that triggers the virtual try-on experience.

struct TryOnWidget: View {
    let onClick: () -> Void
    @State private var isExpanded = false

    var body: some View {
        HStack(spacing: 0) {
            Image(systemName: "sparkles")
                .font(.system(size: isExpanded ? 14 : 16, weight: .medium))
                .foregroundColor(.white)
            if isExpanded {
                Text("Try On")
                    .font(.system(size: 12, weight: .semibold))
                    .foregroundColor(.white)
                    .padding(.leading, 6)
            }
        }
        .padding(.horizontal, isExpanded ? 12 : 8)
        .padding(.vertical, 6)
        .frame(minWidth: 36, minHeight: 36)
        .background(
            LinearGradient(
                colors: [Color(red: 0.58, green: 0.42, blue: 0.85).opacity(0.85),
                         Color(red: 0.48, green: 0.32, blue: 0.75).opacity(0.85)],
                startPoint: .topLeading, endPoint: .bottomTrailing
            )
        )
        .clipShape(Capsule())
        .shadow(color: Color.purple.opacity(0.3), radius: 4)
        .onTapGesture { onClick() }
        .animation(.spring(response: 0.3), value: isExpanded)
        .onAppear {
            Timer.scheduledTimer(withTimeInterval: 3.0, repeats: true) { _ in
                withAnimation { isExpanded.toggle() }
            }
        }
    }
}

// Trigger try-on from product card
func triggerTryOn(for product: Product) {
    GlanceChatSDK.shared.setPageContext("PDP", metadata: [
        "page_identifier": product.id,
        "product_id": product.variantId,
        "product_name": product.name,
        "product_image": product.imageUrl,
        "product_price": product.price,
        "current_url": "\(GlanceConfig.shopifyBaseUrl)/products/\(product.handle)",
        "tenant_id": GlanceConfig.tenantId,
        "action": "try_on",
        "from_widget": "true"
    ])
}

Step 6: Session Management and Cleanup

// Handle session expiry (401 errors)
GlanceChatSDK.shared.setSessionExpiredCallback {
    print("Session expired")
}

// Programmatic control
GlanceChatSDK.shared.closeChat()
GlanceChatSDK.shared.clearPageContext()

// Clean up when done (e.g., user logs out)
GlanceChatSDK.shared.destroy()