Skip to main content

Methods

Muta.configure()

Initializes the SDK with your API key.
Muta.configure(apiKey: String)

Parameters

ParameterTypeRequiredDescription
apiKeyStringYesYour Muta API key

Muta.shared.displayPlacement()

Displays a placement in a modal overlay.
// Using SwiftUI Color
func displayPlacement(
    placementId: String,
    backgroundColor: Color = .white,
    presentationType: PresentationType = .slide,
    loadingView: AnyView? = nil,
    injectedScreens: [InjectedScreen] = []
)

// Using hex color string
func displayPlacement(
    placementId: String,
    backgroundHexColor: String,
    presentationType: PresentationType = .slide,
    loadingView: AnyView? = nil,
    injectedScreens: [InjectedScreen] = []
)

Parameters

ParameterTypeRequiredDescription
placementIdStringYesThe ID of the placement to display
backgroundColorColorNoBackground color that matches your first placement screen. Defaults to white.
backgroundHexColorStringNoBackground color as a hex string. Alternative to backgroundColor.
presentationTypePresentationTypeNoAnimation style when showing the placement. Defaults to .slide
loadingViewAnyView?NoA custom SwiftUI view to show while the placement is loading
injectedScreens[InjectedScreen]NoArray of native SwiftUI views to inject into code screens. See Code Screens for details.

Muta.shared.on()

Subscribe to Muta events.
// Subscribe to all events
func on(_ handler: @escaping (MutaEvent) -> Void) -> Subscription

// Subscribe to specific event type
func on<T: MutaEvent>(_ type: T.Type, handler: @escaping (T) -> Void) -> Subscription

Parameters

ParameterTypeRequiredDescription
handler(MutaEvent) -> VoidYesThe closure to be called when any event occurs
typeT.TypeYesThe specific event type to listen for
handler(T) -> VoidYesThe closure to be called when the specific event occurs

Returns

A Subscription object that can be used to unsubscribe from the event.

Types

MutaEvent

Base protocol for all Muta events.
protocol MutaEvent {
    var timestamp: Int { get }
    var placementId: String { get }
    var flowName: String? { get }
}

FlowStartedEvent

struct FlowStartedEvent: MutaEvent {
    let timestamp: Int
    let placementId: String
    let flowName: String?
    let totalScreens: Int
}

ScreenViewedEvent

struct ScreenViewedEvent: MutaEvent {
    let timestamp: Int
    let placementId: String
    let flowName: String?
    let screenIndex: Int
    let totalScreens: Int
    let screenName: String?
}

FlowCompletedEvent

struct FlowCompletedEvent: MutaEvent {
    let timestamp: Int
    let placementId: String
    let flowName: String
    let screenIndex: Int
    let totalScreens: Int
    let screenName: String
    let eventData: [String: Any]?  // Contains variables collected during the flow
}

FlowAbandonedEvent

struct FlowAbandonedEvent: MutaEvent {
    let timestamp: Int
    let placementId: String
    let flowName: String?
    let screenIndex: Int
    let totalScreens: Int
    let lastScreenIndex: Int
    let screenName: String?
}

CodeScreenDisplayedEvent

struct CodeScreenDisplayedEvent {
    let screenId: String
    let screenName: String
    let timestamp: Int
}

CodeScreenActionEvent

struct CodeScreenActionEvent {
    let action: String         // "continue" or "back"
    let screenId: String
    let screenName: String
    let timestamp: Int
}

CustomEvent

struct CustomEvent: MutaEvent {
    let type: String           // Your custom event name
    let timestamp: Int
    let placementId: String
    let flowName: String?
    let screenIndex: Int?
    let eventData: [String: Any]?  // Custom data from the editor
}

Usage Example

// Listen for custom events configured in the Muta editor
let subscription = Muta.shared.on(CustomEvent.self) { event in
    switch event.type {
    case "signup_started":
        // Handle signup button click
        navigateToSignup()
        
    case "plan_selected":
        // Handle plan selection with custom data
        if let planType = event.eventData?["planType"] as? String {
            selectPlan(planType)
        }
        
    case "survey_completed":
        // Handle survey completion
        if let answers = event.eventData?["answers"] as? [String: Any] {
            saveSurveyData(answers)
        }
        
    default:
        break
    }
}

InjectedScreen

struct InjectedScreen {
    let screenName: String                               // Must match name in Muta editor
    let view: (CodeScreenContext) -> AnyView             // Factory function for the view
}

CodeScreenContext

struct CodeScreenContext {
    let onContinue: () -> Void                           // Navigate to configured continue destination
    let onBack: () -> Void                               // Navigate to configured back destination
    let variables: [[String: Any]]                       // Current flow variables
    let screenId: String                                 // Unique screen ID
    let screenIndex: Int                                 // Screen position in flow
}

Usage Example

// Inject a login screen into your flow
Muta.shared.displayPlacement(
    placementId: "onboarding",
    backgroundColor: .black,
    injectedScreens: [
        InjectedScreen(
            screenName: "Login Screen",
            view: { context in
                AnyView(LoginScreen(context: context))
            }
        )
    ]
)

ErrorEvent

enum ErrorEvent {
    case network(message: String, timestamp: Int)
    case placement(message: String, code: String, timestamp: Int, placementId: String)
}

Example Usage

import SwiftUI
import MutaSDK

@main
struct YourApp: App {
    init() {
        Muta.configure(apiKey: "your-api-key")
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

struct ContentView: View {
    var body: some View {
        Button("Show Placement") {
            Muta.shared.displayPlacement(
                placementId: "your-placement-id",
                backgroundColor: .white,
                presentationType: .fade,
                loadingView: AnyView(
                    VStack {
                        ProgressView()
                        Text("Loading...")
                    }
                )
            )
        }
    }
}