Skip to content

Integrating the SDK into your application

This guide provides a quick reference for integrating the Cognitive3D Analytics SDK into a visionOS application.

Note: Scene and Dynamic Object (meshes, textures) uploads to the Cognitive3D platform is currently a manual process. Reach out to the team via Intercom or Discord for help setting up your Scenes and Dynamic Objects. Our roadmap includes a GUI tool to make uploading these easy and straightforward.

Using the Cognitive3D Analytics SDK

You hae a choice of how to use the analytics SDK with your application:

  • as a framework as a Swift package
  • as soure code

As a framework

The framework will work on device and in the visionOS simulator.

  • copy the framework and Swift.package file into a subfolder

Add Package

  • add the framework as a local Swift package

Package Added

As source code

You can use the analytics directly in your project as source code.

  • create a workspace

Project Folders Xcode workspace

  • add your visionOS project to the workspace

  • add the analytics project into the workspace

Package Added - add the analytics code as a dependancy in your project

Import the framework

import Cognitive3DAnalytics

Initial setup in your application

Initialize the SDK at app startup

// In your App struct's init method
init() {
    // Initialize the C3D SDK when app starts up
    cognitiveSDKInit()
}

Configure the SDK

The sceneName, sceneId, versionNumber, and versionId for a scene in your application can be found on the Scene page for your Project on the Cognitive3D dashboard. Hover over the information icon next to the Media button.

Scene information on the dashboard

The APPLICATION_API_KEY can be found or reset on the Organization Settings page for your project on the Cognitive3D dashboard.

Important: Never store the APPLICATION_API_KEY in your source code directly, and we strongly recommend not storing it in your source control system, like a git repository. The Application Key is what your application uses to allow the Cognitive3D SDK to communicate with the analytics data pipeline and is unique to your application / project.

TODO: Where do we recommend this value be stored?

Project settings for managing keys

The values for setParticipantId and setParticipantFullName are up to you to set as makes sense for your application. These could be a username and real name, or they could be another form of identification, like an employee number and name.

fileprivate func cognitiveSDKInit() {
    // Prepare scene data for the SDK
    let sceneData = SceneData(
        sceneName: "your-scene-name",
        sceneId: "your-scene-id",
        versionNumber: 1,
        versionId: 1234
    )

    let core = Cognitive3DAnalyticsCore.shared

    // Configure settings
    let settings = CoreSettings()
    settings.defaultSceneName = sceneData.sceneName
    settings.allSceneData = [sceneData]

    // Set logging level
    settings.loggingLevel = .all
    settings.isDebugVerbose = false

    // Set Application API key (from Info.plist or another configuration source)
    let apiKey = Bundle.main.object(forInfoDictionaryKey: "APPLICATION_API_KEY") as? String ?? "default-value"
    settings.apiKey = apiKey

    // Set participant information
    core.setParticipantId("participant-id")
    core.setParticipantFullName("Participant Name")

    // Start synchronous initialization
    Task {
        do {
            try await core.configure(with: settings)
            // Register code related to dynamic objects
            configureDynamicObject(settings)

            // Optional: Configure session behaviour
            core.config?.shouldEndSessionOnBackground = false

            // Set session delegate to handle session events
            core.sessionDelegate = yourSessionDelegate
        } catch {
            print("Failed to configure Cognitive3D Analytics: \(error)")
        }
    }
}

Set Up scene phase handling

// In your app's WindowGroup
WindowGroup {
    ContentView()
        // Add this modifier to enable scene phase handling
        .observeCognitive3DScenePhase()
}

Dynamic Objects setup

Register components and systems

fileprivate func configureDynamicObject(_ settings: CoreSettings) {
    // Register the dynamic component
    DynamicComponent.registerComponent()

    // Register the dynamic object system
    DynamicObjectSystem.registerSystem()
}

Configure Dynamic Objects in a scene

func configureDynamicObjects(rootEntity: Entity) async {
    guard let objManager = Cognitive3DAnalyticsCore.shared.dynamicDataManager else {
        return
    }

    // Find all entities with DynamicComponent
    let dynamicEntities = findEntitiesWithComponent(rootEntity, componentType: DynamicComponent.self)

    // Register each dynamic object with the SDK
    for (entity, comp) in dynamicEntities {
        await objManager.registerDynamicObject(id: comp.dynamicId, name: comp.name, mesh: comp.mesh)
    }
}

Content entity for raycasting

This is required to record gaze with RealityKit entities that have a DynamicComponent.

// In your RealityView setup
if let contentEntity = try? await Entity(named: "YourScene", in: realityKitContentBundle) {
    // ...

    // Provide the entity to the SDK for raycasting and collision detection
    let core = Cognitive3DAnalyticsCore.shared
    core.contentEntity = contentEntity
}

Session Management

Implement session delegates

// Conform to SessionDelegate
class YourAppModel: SessionDelegate {
    // Handle session end events
    nonisolated func sessionDidEnd(sessionId: String, sessionState: SessionState) {
        Task { @MainActor in
            switch sessionState {
            case .endedIdle(timeInterval: let timeInterval):
                // Handle idle timeout

            case .endedBackground:
                // Handle app going to background

            default:
                // Handle other cases
            }
        }
    }
}

// Conform to IdleSessionDelegate
class YourAppModel: IdleSessionDelegate {
    nonisolated func sessionDidEndDueToIdle(sessionId: String, idleDuration: TimeInterval) {
        Task { @MainActor in
            // Handle idle session end
        }
    }
}

Starting and ending sessions

Note: Your application should typically only start and end a session once in it's usage lifecycle. If your app starts and ends sessions during typical usage, i.e. while the Participant is using the app continuously, you will see separate sessions on the dashboard for each start-session/end-session pair, which is undesirable.

// Start a session
Cognitive3DAnalyticsCore.shared.startSession()

// End a session
Cognitive3DAnalyticsCore.shared.endSession()

Creating and sending Custom Events

Custom Events are used to track what happens in your application at a given time and location. These are associated with a session and will appear in that session's timeline on the dashboard.

func createCustomEvent(dynamicId: String) {
    let core = Cognitive3DAnalyticsCore.shared

    // Create an event
    let event = CustomEvent(
        name: "tapEvent",
        properties: [
            "timestamp": Date().timeIntervalSince1970
        ],
        dynamicObjectId: dynamicId,
        core: core
    )

    let success = event.send()
}

Working with ExitPoll surveys

The ExitPoll system can be used to prompt Participants for their opinions or feedback while your application is running. The responses are gathered by the SDK and are visible on the dashboard.

TODO: Link to the ExitPolls section of the dashboard documentation.

// Create an exit poll survey
let exitPollSurvey = ExitPollSurveyViewModel()
exitPollSurvey.loadSurvey(hook: "your-survey-hook")

// Submit survey answers
Task {
    let result = await exitPollSurvey.sendSurveyAnswers()
    switch result {
    case .success:
        print("Survey answers submitted successfully.")
    case .failure(let error):
        print("Failed to submit survey answers: \(error)")
    }
}

Changing Scenes

Scenes are typically separate virtual locations in your application. In a game application you might have a Lobby Scene and a Gameplay Scene. For training applications you might have a Login Scene and one or more training scenario Scenes.

Note: Reminder that uploading scene data (meshes, textures) is a manual process currently. Reach out via Intercom or Discord for help from the Cognitive3D team.

// Set a different scene during runtime
Cognitive3DAnalyticsCore.shared.setSceneById(
    sceneId: "new-scene-id", 
    version: 1, 
    versionId: 1234
)

intercom If you have a question or any feedback about our documentation please use the Intercom button (purple circle) in the lower right corner of any web page or join our Discord.