The name "ABXR" stands for "Analytics Backbone for XR"—a flexible, open-source foundation for capturing and transmitting spatial, interaction, and performance data in XR. When combined with ArborXR Insights, ABXR transforms from a lightweight instrumentation layer into a full-scale enterprise analytics solution—unlocking powerful dashboards, LMS/BI integrations, and AI-enhanced insights.
The ABXRLib SDK for WebXR is an open-source analytics and data collection library that provides developers with the tools to collect and send XR data to any service of their choice. This library enables scalable event tracking, telemetry, and session-based storage—essential for enterprise and education XR environments.
Quick Start: Most developers can integrate ABXRLib SDK and log their first event in under 15 minutes.
Why Use ABXRLib SDK?
- Open-Source & portable to any backend—no vendor lock-in
- Quick integration—track user interactions in minutes
- Secure & scalable—ready for enterprise use cases
- Pluggable with ArborXR Insights—seamless access to LMS/BI integrations, session replays, AI diagnostics, and more
The ABXRLib SDK provides:
- Event Tracking: Monitor user behaviors, interactions, and system events.
- Spatial & Hardware Telemetry: Capture headset/controller movement and hardware metrics.
- Object & System Info: Track XR objects and environmental state.
- Storage & Session Management: Support resumable training and long-form experiences.
- Logs: Developer and system-level logs available across sessions.
The ABXRLib SDK is designed to work with any backend service that implements the ABXR protocol. Currently supported services include:
When paired with ArborXR Insights, ABXR becomes a full-service platform offering:
- Seamless data pipeline from headset to dashboard
- End-to-end session tracking, analysis, and replay
- AI-driven insights for content quality, learner performance, and device usage
- One-click LMS and BI integrations for scalable deployments
Developers can implement their own backend services by following the ABXR protocol specification. This allows for complete control over data storage, processing, and visualization.
npm install abxrlib-for-webxr
To use the ABXRLib SDK with ArborXR Insights:
- Go to the ArborXR Insights web app and log in.
- Grab these three values from the View Data screen of the specific app you are configuring:
- App ID
- Organization ID
- Authentication Secret
The ABXRLib SDK now provides a simplified initialization API. The appId
is required, while orgId
and authSecret
are optional and can be provided via URL parameters.
⚠️ Security Note: For production builds distributed to third parties, avoid compilingorgId
andauthSecret
directly into your application code. Instead, use URL parameters or environment variables to provide these credentials at runtime. Only compile credentials directly into the build when creating custom applications for specific individual clients.
import { Abxr_init, Abxr } from 'abxrlib-for-webxr';
// RECOMMENDED: Use URL parameters for production builds
// URL: https://yourdomain.com/?abxr_orgid=YOUR_ORG_ID&abxr_auth_secret=YOUR_AUTH_SECRET
Abxr_init('your-app-id');
// DEVELOPMENT ONLY: Direct initialization with all parameters
Abxr_init('your-app-id', 'your-org-id', 'your-auth-secret');
// Now you can use the Abxr class
Abxr.Event('user_action', { action: 'button_click' });
Abxr.LogDebug('Debug message');
You can provide authentication credentials via URL parameters, which take precedence over function parameters:
https://yourdomain.com/?abxr_orgid=YOUR_ORG_ID&abxr_auth_secret=YOUR_AUTH_SECRET
Then initialize with just the App ID:
import { Abxr_init, Abxr } from 'abxrlib-for-webxr';
// URL parameters will be automatically detected
Abxr_init('your-app-id');
// Now you can use the Abxr class
Abxr.Event('user_action', { action: 'button_click' });
You have several options for importing the library:
Option 1: Import both initialization and main class
import { Abxr_init, Abxr } from 'abxrlib-for-webxr';
Option 2: Import everything
import { Abxr_init, Abxr, AbxrLib } from 'abxrlib-for-webxr';
Option 3: Browser global scope (no import needed)
<script src="node_modules/abxrlib-for-webxr/Abxr.js"></script>
<script>
// Abxr_init and Abxr are available globally
Abxr_init('app123', 'org456', 'secret789');
Abxr.Event('user_action', { action: 'button_click' });
</script>
For information on implementing your own backend service or using other compatible services, please refer to the ABXR protocol specification.
// JavaScript Event Method Signatures
static async Event(name: string, meta?: any): Promise<number>
// Example Usage - Basic Event (fire-and-forget)
Abxr.Event('button_pressed');
// Example Usage - Event with Metadata (fire-and-forget)
Abxr.Event('item_collected', {
'item_type': 'coin',
'item_value': '100'
});
// Example Usage - Event with Metadata (fire-and-forget)
Abxr.Event('player_teleported', {
'destination': 'spawn_point',
'method': 'instant'
});
Parameters:
name
(string): The name of the event. Use snake_case for better analytics processing.meta
(object): Optional. Additional key-value pairs describing the event.
Returns: Promise<number>
- Event ID or 0 if not authenticated (typically not awaited).
Logs a named event with optional metadata and spatial context. Timestamps and origin (user
or system
) are automatically appended. Recommended usage is fire-and-forget - no need to await the result.
The ABXRLib SDK supports multiple flexible formats for the meta
parameter in all event and log methods. You can use whatever format is most convenient for your application:
// Simple and intuitive - works with any object (runs in background)
Abxr.Event('user_action', {
action: 'click',
timestamp: new Date().toISOString(),
userId: 12345,
completed: true
});
Abxr.LogInfo('User login', {
username: 'john_doe',
loginMethod: 'oauth',
deviceType: 'mobile'
});
// Perfect for APIs or stored JSON data (runs in background)
Abxr.EventAssessmentStart('Math Quiz', '{"difficulty": "hard", "timeLimit": 300, "attempts": 1}');
Abxr.LogError('API Error', '{"endpoint": "/api/users", "status": 500, "message": "Database timeout"}');
// Great for form data or query parameters (runs in background)
Abxr.Event('form_submit', 'name=John%20Doe&[email protected]&age=25');
Abxr.LogDebug('Search query', 'query=virtual+reality&category=education&page=2');
// Handles complex values with = signs
Abxr.Event('equation_solved', 'formula=x=y+5&result=10&method=substitution');
// For advanced users who need precise control (runs in background)
const meta = new Abxr.AbxrDictStrings();
meta.Add('custom_field', 'value');
meta.Add('timestamp', Date.now().toString());
Abxr.Event('custom_event', meta);
// For simple single-value metadata (runs in background)
Abxr.Event('score_update', 1500); // Number
Abxr.LogInfo('Feature enabled', true); // Boolean
Abxr.Event('user_message', 'Hello World'); // String
// Events and logs work fine without metadata (runs in background)
Abxr.Event('app_started');
Abxr.LogInfo('Application initialized');
The SDK automatically handles conversion and URL decoding:
// URL parameters with encoding
'user=John%20Doe&message=Hello%20World'
// Becomes: { user: "John Doe", message: "Hello World" }
// JSON with nested data
'{"user": {"name": "John", "age": 30}, "scores": [95, 87, 92]}'
// Becomes: { user: "John,30", scores: "95,87,92" }
// Mixed formats work seamlessly (runs in background)
Abxr.EventLevelComplete('Level 1', 85, 'score=85&attempts=3&bonus=true');
Abxr.EventAssessmentStart('Quiz', { startTime: Date.now(), difficulty: 'medium' });
All event and log methods support these flexible metadata formats:
Abxr.Event(name, meta?)
Abxr.EventAssessmentStart/Complete(..., meta?)
Abxr.EventObjectiveStart/Complete(..., meta?)
Abxr.EventInteractionStart/Complete(..., meta?)
Abxr.EventLevelStart/Complete(..., meta?)
Abxr.LogDebug/Info/Warn/Error/Critical(message, meta?)
These analytics event functions are essential for ALL developers They provide standardized tracking for key user interactions and learning outcomes that are crucial for understanding user behavior, measuring engagement, and optimizing XR experiences and power the analytics dashboards and reporting features. They also essential for integrations with Learning Management System (LMS) platforms.
EventAssessmentStart and EventAssessmentComplete are REQUIRED for all ArborXR Insights usage
These three event types work together to provide comprehensive tracking of user progress:
-
Assessment: Tracks overall performance across an entire experience, course, or curriculum. Think of it as the final score or outcome for a complete learning module. When an Assessment completes, it automatically records and closes out the session in supported LMS platforms.
-
Objective: Tracks specific learning goals or sub-tasks within an assessment. These represent individual skills, concepts, or milestones that contribute to the overall assessment score.
-
Interaction: Tracks individual user responses or actions within an objective or assessment. These capture specific user inputs, choices, or behaviors that demonstrate engagement and learning progress.
// Status enumeration for all analytics events (user-friendly values)
Abxr.EventStatus.Pass, Abxr.EventStatus.Fail, Abxr.EventStatus.Complete, Abxr.EventStatus.Incomplete, Abxr.EventStatus.Browsed, Abxr.EventStatus.NotAttempted
Abxr.InteractionType.Null, Abxr.InteractionType.Bool, Abxr.InteractionType.Select, Abxr.InteractionType.Text, Abxr.InteractionType.Rating, Abxr.InteractionType.Number
Abxr.InteractionResult.Correct, Abxr.InteractionResult.Incorrect, Abxr.InteractionResult.Neutral // defaults to Neutral
> **Note:** Enums are also available in the global namespace as `AbxrEventStatus`, `AbxrInteractionType`, `AbxrInteractionResult`, `AbxrLogLevel`, `AbxrStorageScope`, and `AbxrStoragePolicy` for compatibility, but the recommended approach is to use the `Abxr.*` namespace to avoid conflicts.
// JavaScript Method Signatures
static async EventAssessmentStart(assessmentName: string, meta?: any): Promise<number>
static async EventAssessmentComplete(assessmentName: string, score: number | string, eventStatus: EventStatus, meta?: any): Promise<number>
static async EventObjectiveStart(objectiveName: string, meta?: any): Promise<number>
static async EventObjectiveComplete(objectiveName: string, score: number | string, eventStatus: EventStatus, meta?: any): Promise<number>
static async EventInteractionStart(interactionName: string, meta?: any): Promise<number>
static async EventInteractionComplete(interactionName: string, interactionType: InteractionType, result: InteractionResult = "neutral", response: string = "", meta?: any): Promise<number>
// Assessment tracking (overall course/curriculum performance)
Abxr.EventAssessmentStart('final_exam');
Abxr.EventAssessmentComplete('final_exam', 92, Abxr.EventStatus.Pass);
// Objective tracking (specific learning goals)
Abxr.EventObjectiveStart('open_valve');
Abxr.EventObjectiveComplete('open_valve', 100, Abxr.EventStatus.Complete);
// Interaction tracking (individual user responses)
Abxr.EventInteractionStart('select_option_a');
Abxr.EventInteractionComplete('select_option_a', Abxr.InteractionType.Select, Abxr.InteractionResult.Correct, 'true');
// JavaScript Method Signatures
static async EventLevelStart(levelName: string, meta?: any): Promise<number>
static async EventLevelComplete(levelName: string, score: number | string, meta?: any): Promise<number>
static async EventCritical(label: string, meta?: any): Promise<number>
// Level tracking
Abxr.EventLevelStart('level_1');
Abxr.EventLevelComplete('level_1', 85);
// Critical event flagging (for safety training, high-risk errors, etc.)
Abxr.EventCritical('safety_violation');
Parameters for all Event Wrapper Functions:
levelName/assessmentName/objectiveName/interactionName
(string): The identifier for the assessment, objective, interaction, or level.score
(int): The numerical score achieved. While typically between 1-100, any integer is valid. In metadata, you can also set a minScore and maxScore to define the range of scores for this objective.result
(InteractionResult
): The result for the interaction (Correct, Incorrect, Neutral).response
(string): Optional. Additional details about the result. For interactions, this can be a single character or a string. For example: "a", "b", "c" or "correct", "incorrect".interactionType
(InteractionType
): Optional. The type of interaction for this event.meta
(object): Optional. Additional key-value pairs describing the event.
Note: All complete events automatically calculate duration if a corresponding start event was logged.
The ABXRLib SDK includes a built-in timing system that allows you to measure the duration of any event. This is useful for tracking how long users spend on specific activities.
// JavaScript Timed Event Method Signature
Abxr.StartTimedEvent(eventName)
// Example Usage
Abxr.StartTimedEvent("Table puzzle");
// ... user performs puzzle activity for 20 seconds ...
Abxr.Event("Table puzzle"); // Duration automatically included: 20 seconds
// Works with all event methods
Abxr.StartTimedEvent("Assessment");
// ... later ...
Abxr.EventAssessmentComplete("Assessment", 95, Abxr.EventStatus.ePass); // Duration included
// Also works with Mixpanel compatibility methods
Abxr.StartTimedEvent("User Session");
// ... later ...
Abxr.Track("User Session"); // Duration automatically included
Parameters:
eventName
(string): The name of the event to start timing. Must match the event name used later.
Note: The timer automatically adds a duration
field (in seconds) to any subsequent event with the same name. The timer is automatically removed after the first matching event.
Global properties automatically included in all events, logs, and telemetry data:
// JavaScript Method Signatures
Abxr.Register(key, value)
Abxr.RegisterOnce(key, value)
// Set persistent properties (included in all events, logs, and telemetry)
Abxr.Register("user_type", "premium");
Abxr.Register("app_version", "1.2.3");
// Set only if not already set
Abxr.RegisterOnce("user_tier", "free");
// Management
Abxr.Unregister("device_type"); // Remove specific property
Abxr.Reset(); // Clear all super metadata
Perfect for user attributes, app state, and device information that should be included with every event, log entry, and telemetry data point.
The Log Methods provide straightforward logging functionality, similar to syslogs. These functions are available to developers by default, even across enterprise users, allowing for consistent and accessible logging across different deployment scenarios.
// JavaScript Method Signatures
static Log(message: string, level: Abxr.LogLevel = Abxr.LogLevel.eInfo, meta?: any): void
// Example usage
Abxr.Log('Module started'); // Defaults to Abxr.LogLevel.eInfo
Abxr.Log('Module started', Abxr.LogLevel.eInfo);
Abxr.Log('Debug information', Abxr.LogLevel.eDebug);
Use standard or severity-specific logging:
// JavaScript Method Signatures
static LogDebug(message: string, meta?: any): void
static LogInfo(message: string, meta?: any): void
static LogWarn(message: string, meta?: any): void
static LogError(message: string, meta?: any): void
static LogCritical(message: string, meta?: any): void
// Example usage
Abxr.LogError('Critical error in assessment phase');
// With metadata
Abxr.LogDebug('User interaction', {
'action': 'button_click',
'screen': 'main_menu'
});
The Storage API enables developers to store and retrieve learner/player progress, facilitating the creation of long-form training content. When users log in using ArborXR's facility or the developer's in-app solution, these methods allow users to continue their progress on different headsets, ensuring a seamless learning experience across multiple sessions or devices.
// JavaScript Method Signatures
static async StorageSetEntry(name: string, entry: {[key: string]: string}, scope: Abxr.StorageScope, policy: Abxr.StoragePolicy = Abxr.StoragePolicy.keepLatest): Promise<number>
static async StorageSetDefaultEntry(entry: {[key: string]: string}, scope: Abxr.StorageScope, policy: Abxr.StoragePolicy = Abxr.StoragePolicy.keepLatest): Promise<number>
static async StorageGetEntry(name: string, scope: Abxr.StorageScope): Promise<{[key: string]: string}[]>
static async StorageGetDefaultEntry(scope: Abxr.StorageScope): Promise<{[key: string]: string}[]>
static async StorageRemoveEntry(name: string = "state", scope: Abxr.StorageScope = Abxr.StorageScope.user): Promise<number>
static async StorageRemoveDefaultEntry(scope: Abxr.StorageScope = Abxr.StorageScope.user): Promise<number>
static async StorageRemoveMultipleEntries(scope: Abxr.StorageScope = Abxr.StorageScope.user): Promise<number>
// Save progress data
Abxr.StorageSetEntry("state", {"progress": "75%"}, Abxr.StorageScope.user);
Abxr.StorageSetDefaultEntry({"progress": "75%"}, Abxr.StorageScope.user);
// Using StoragePolicy enum explicitly
Abxr.StorageSetEntry("state", {"progress": "75%"}, Abxr.StorageScope.user, Abxr.StoragePolicy.keepLatest);
Abxr.StorageSetEntry("history", {"action": "completed_level_1"}, Abxr.StorageScope.user, Abxr.StoragePolicy.appendHistory);
// Retrieve progress data (returns array of dictionaries, matching Unity's List<Dictionary<string, string>>)
const result = await Abxr.StorageGetEntry("state", Abxr.StorageScope.user);
console.log("Retrieved data:", result); // Array of objects: [{"progress": "75%"}]
const defaultResult = await Abxr.StorageGetDefaultEntry(Abxr.StorageScope.user);
console.log("Retrieved default data:", defaultResult); // Array of objects from "state" key
// Process retrieved data (similar to Unity callback pattern)
if (result && result.length > 0) {
const data = result[0]; // Get the most recent entry
if (data.progress) {
console.log("Progress:", data.progress);
}
}
// Remove storage entries
Abxr.StorageRemoveEntry("state", Abxr.StorageScope.user);
Abxr.StorageRemoveDefaultEntry(Abxr.StorageScope.user);
Abxr.StorageRemoveMultipleEntries(Abxr.StorageScope.user); // Clear all entries (use with caution)
Parameters:
name
(string): The identifier for this storage entry.entry
(object): The key-value pairs to store as{[key: string]: string}
.scope
(StorageScope
): Store/retrieve from 'device' or 'user' storage.policy
(StoragePolicy
): How data should be stored -StoragePolicy.keepLatest
orStoragePolicy.appendHistory
(defaults toStoragePolicy.keepLatest
).
Return Values:
- Set methods: Return
Promise<number>
- Storage entry ID or 0 if not authenticated. - Get methods: Return
Promise<{[key: string]: string}[]>
- Array of dictionaries matching Unity'sList<
Dictionary<string, string>>
format.
The Telemetry Methods provide comprehensive tracking of the XR environment. By default, they capture headset and controller movements, but can be extended to track any custom objects in the virtual space. These functions also allow collection of system-level data such as frame rates or device temperatures. This versatile tracking enables developers to gain deep insights into user interactions and application performance, facilitating optimization and enhancing the overall XR experience.
// JavaScript Method Signatures
static async Telemetry(name: string, data: any): Promise<number>
// Custom telemetry logging (fire-and-forget)
Abxr.Telemetry("headset_position", {
"x": "1.23", "y": "4.56", "z": "7.89"
});
Parameters:
name
(string): The type of telemetry data (e.g., "headset_position", "frame_rate", "battery_level").data
(object): Key-value pairs of telemetry measurements.
Returns: Promise<number>
- Telemetry entry ID or 0 if not authenticated (typically not awaited).
The AI Integration methods provide access to AI services for enhanced user interactions and experiences within XR environments. WebXR uses a Promise-based approach that allows developers to choose between blocking and non-blocking patterns.
// Non-blocking approach - process response when ready
Abxr.AIProxy("How can I help you today?", "gpt-4").then(response => {
if (response) {
console.log("AI Response:", response);
// Process the AI response without blocking
} else {
console.log("AI request failed");
}
});
// Blocking approach - wait for response
const response = await Abxr.AIProxy("What's the weather like?", "gpt-4");
if (response) {
console.log("Weather:", response);
}
// With conversation history for context
const pastMessages = ["Hello", "Hi there! How can I help?"];
const contextualResponse = await Abxr.AIProxy("What did we just discuss?", "gpt-4", pastMessages);
// Error handling with try/catch
try {
const aiAdvice = await Abxr.AIProxy("Give me XR development tips", "gpt-4");
if (aiAdvice) {
displayAdvice(aiAdvice);
}
} catch (error) {
console.error("AI request error:", error);
}
Method Signature:
static AIProxy(prompt: string, llmProvider?: string, pastMessages?: string[]): Promise<string | null>
Parameters:
prompt
(string): The input prompt for the AI systemllmProvider
(string, optional): The LLM provider to use (e.g., "gpt-4", "claude", "default")pastMessages
(string[], optional): Previous conversation messages for context
Returns:
Promise<string | null>
: The AI response string, or null if the request failed
Platform Differences:
- Unity: Uses coroutines with callbacks -
StartCoroutine(Abxr.AIProxy(prompt, provider, callback))
- WebXR: Uses Promise-based approach - developers can choose
await
(blocking) or.then()
(non-blocking)
Deliver questionnaires to users to gather feedback.
// Poll type enumeration
Abxr.PollType.Thumbs, Abxr.PollType.Rating, Abxr.PollType.MultipleChoice
// JavaScript Method Signatures
Abxr.PollUser(prompt, pollType, responses?, callback?)
Abxr.HideExitPoll()
// Poll types: Thumbs, Rating (1-5), MultipleChoice (2-8 options)
Abxr.PollUser("How would you rate this training experience?", Abxr.PollType.Rating);
// Multiple choice poll with custom responses
Abxr.PollUser("What was your favorite part?", Abxr.PollType.MultipleChoice,
["Safety Training", "Equipment Check", "Emergency Procedures"],
(response) => console.log("User selected:", response));
// Hide any currently displayed poll
Abxr.HideExitPoll();
The ABXRLib SDK supports multiple flexible metadata formats. All formats are automatically converted to key-value pairs:
// 1. Native JavaScript Objects (most efficient)
Abxr.Event("user_action", {
"action": "click",
"userId": "12345"
});
// 2. JSON Strings (auto-converts objects)
Abxr.Track("assessment_complete", '{"score": 95, "completed": true}');
// 3. No metadata
Abxr.Event("app_started");
Key Takeaway: All event and log methods support these flexible metadata formats
The ABXRLib SDK automatically enhances your data with additional context and metadata without requiring explicit configuration:
Super metadata are automatically merged into every event, log, and telemetry entry's metadata. Data-specific properties take precedence when keys conflict:
// Set super metadata
Abxr.Register("app_version", "1.2.3");
Abxr.Register("user_type", "premium");
// Every event automatically includes super metadata
Abxr.Event("level_complete", {
"level": "3",
"user_type": "trial" // This overrides the super metadata
});
// Result includes: app_version=1.2.3, user_type=trial, level=3
// Logs and telemetry also automatically include super metadata
Abxr.LogInfo("Player action", { "action": "jump" });
// Result includes: app_version=1.2.3, user_type=premium, action=jump
Abxr.Telemetry("frame_rate", { "fps": "60" });
// Result includes: app_version=1.2.3, user_type=premium, fps=60
When using timed events or event wrappers, duration is automatically calculated and included:
// Manual timed events
Abxr.StartTimedEvent("puzzle_solving");
// ... 30 seconds later ...
Abxr.Event("puzzle_solving"); // Automatically includes {"duration": "30"}
// Event wrapper functions automatically handle duration
Abxr.EventAssessmentStart("final_exam");
// ... 45 seconds later ...
Abxr.EventAssessmentComplete("final_exam", 95, Abxr.EventStatus.ePass); // Automatically includes duration
// Works for all start/complete pairs:
// - EventAssessmentStart/Complete
// - EventObjectiveStart/Complete
// - EventInteractionStart/Complete
// - EventLevelStart/Complete
// Duration defaults to "0" if no corresponding start event was found
// Timer is automatically removed after the first matching event
The Module Target feature enables developers to create single applications with multiple modules, where users can be assigned to specific module(s) and the application can automatically direct users to their assigned module within the application. When combined with Insights LMS integration, each module can be its own assignment, and individual grades and results are tracked for that specific assignment.
The recommended way to handle modules is to subscribe your Module/URL anchor handler to the OnModuleTarget
event, which gives you full control over how to handle each module target. This event works perfectly with existing URL anchor handlers—you can use the same routing logic for both external URL anchors and LMS module targets. The module sequence executes automatically when authentication completes, and will wait for your subscription if needed, so you only need to subscribe to the event:
// Subscribe to module target events
Abxr.OnModuleTarget(handleModuleOrUrlTarget); // handleModuleOrUrlTarget points to your module/URL anchor handler
// Module(s) will be executed automatically when authentication completes!
// Create or use your own module/URL anchor handler along these lines
function handleModuleOrUrlTarget(moduleTarget) {
console.log(`Handling module target: ${moduleTarget}`);
// Your existing URL anchor routing logic works here too
switch (moduleTarget) {
case 'safety-training':
loadScene('SafetyTrainingScene');
break;
case 'equipment-check':
loadScene('EquipmentCheckScene');
break;
default:
console.warn(`Unknown module target: ${moduleTarget}`);
loadScene('MainMenuScene');
break;
}
}
Features:
- Smart Automatic Execution: Module sequence executes automatically when authentication completes, and waits for your subscription if needed
- Event-Driven: Uses the
OnModuleTarget
event for maximum flexibility - Developer Control: You decide how to handle each module target
- URL Anchor Integration: Perfect for connecting to existing URL anchor handlers
- Unified Handling: One method handles both external URL anchors and LMS module targets
- Error Handling: Continues to next module if an event handler throws an exception
- Return Count: Returns the number of successfully executed modules
For more control, you can manually process modules:
// Get the next module target from available modules
const nextTarget = Abxr.GetModuleTarget();
if (nextTarget) {
console.log(`Processing module: ${nextTarget.moduleTarget}`);
enableModuleFeatures(nextTarget.moduleTarget);
navigateToModule(nextTarget.moduleTarget);
} else {
console.log('All modules completed!');
showCompletionScreen();
}
// Check remaining module count
const remaining = Abxr.GetModuleTargetCount();
console.log(`Modules remaining: ${remaining}`);
// Get all available modules
const allModules = Abxr.GetModuleTargetList();
console.log(`Total modules: ${allModules.length}`);
// Reset progress
Abxr.ClearModuleTargets();
// Get current user information
const userData = Abxr.GetUserData();
Web applications support URL-based module targeting (similar to Android deep links):
// URL-based module targeting
// Example URLs:
// https://yourapp.com/#module=safety-training
// https://yourapp.com/#module=equipment-check&user=john.doe
// Get module from URL
const urlModule = Abxr.GetModuleFromUrl();
if (urlModule) {
console.log(`Module from URL: ${urlModule}`);
}
// Set module in URL
Abxr.SetModuleInUrl('safety-training');
// Clear module from URL
Abxr.ClearModuleFromUrl();
// Subscribe to URL changes
Abxr.OnUrlModuleChange((moduleTarget) => {
console.log(`URL module changed to: ${moduleTarget}`);
handleModuleOrUrlTarget(moduleTarget);
});
// Integration with authentication
Abxr.OnAuthCompleted((authData) => {
if (authData.success) {
// Check URL for module target first
const urlModule = Abxr.GetModuleFromUrl();
if (urlModule) {
// Handle URL-based module targeting
handleModuleOrUrlTarget(urlModule);
}
// Note: module targets will execute automatically via OnModuleTarget subscription
}
});
URL Anchor Benefits:
- Bookmarkable URLs: Users can bookmark specific modules
- Direct linking: Share links to specific training modules
- Browser history: Back/forward navigation works naturally
- Deep link compatibility: Similar to Android deep links but web-native
Module progress is automatically persisted across browser sessions and page reloads:
// Module data is automatically retrieved from authentication response
// Module progress is automatically saved when advancing through modules
// When page reloads or browser crashes, module progress is automatically restored
const nextTarget = Abxr.GetModuleTarget(); // Loads progress from storage if needed
Automatic Recovery Features:
- Session Persistence: Module progress survives page refreshes and browser crashes
- Lazy Loading: Progress is automatically loaded from storage when first accessed
- Error Resilience: Failed storage operations are logged but don't crash the application
- Cross-Session Continuity: Users can continue multi-module experiences across browser sessions
- Rich Data Access: Complete module information available from authentication response
Storage Details:
- Module progress is stored in browser's persistent storage (IndexedDB/localStorage)
- Storage key:
"abxr_module_index"
(handled internally) - Automatic cleanup when
ClearModuleTargets()
is called - Uses ABXRLib's storage system for reliability and offline capabilities
- Module data comes directly from authentication response for accuracy
- Use OnModuleTarget Event: Subscribe to
OnModuleTarget
for flexible module handling - Subscribe to OnAuthCompleted: Subscribe before authentication starts
- Connect to URL Anchors: Use
OnModuleTarget
to connect to your existing URL anchor handling - Error Handling: Handle cases where modules don't exist or fail
- Progress Tracking: Use assessment events to track module completion
- Unsubscribe on Cleanup: Always unsubscribe from events to prevent memory leaks
- URL Integration: Use URL anchor system for bookmarkable modules and direct linking
- Unified Routing: One method handles both external URL anchors and LMS module targets
The ABXRLib SDK provides comprehensive authentication completion callbacks that deliver detailed user and module information. This enables rich post-authentication workflows including automatic module navigation and personalized user experiences.
Subscribe to authentication events to receive user information and module targets:
// Basic authentication callback
Abxr.OnAuthCompleted((authData) => {
if (authData.success) {
console.log(`Welcome ${authData.userEmail}!`);
// Handle initial vs reauthentication
if (authData.isReauthentication) {
refreshUserData();
} else {
initializeUserInterface();
}
// Handle modules if available
if (authData.moduleCount > 0) {
const moduleData = Abxr.GetModuleTarget();
if (moduleData) {
navigateToModule(moduleData.moduleTarget);
}
}
}
});
// Callback management
Abxr.RemoveAuthCompletedCallback(authCallback); // Remove specific callback
Abxr.ClearAuthCompletedCallbacks(); // Clear all callbacks
The callback provides an AuthCompletedData
object with comprehensive authentication information:
interface ModuleData {
id: string; // Module unique identifier
name: string; // Module display name
target: string; // Module target identifier
order: number; // Module order/sequence
}
interface AuthCompletedData {
success: boolean; // Whether authentication was successful
token?: string; // Authentication token
secret?: string; // Authentication secret
userData?: any; // Complete user data object from authentication response
userId?: any; // User identifier
userEmail?: string | null; // User email address (extracted from userData.email)
appId?: string; // Application identifier
modules?: ModuleData[]; // List of available modules
moduleCount?: number; // Number of available modules
isReauthentication?: boolean; // Whether this was a reauthentication (vs initial auth)
error?: string; // Error message when success is false
// Method to reconstruct original authentication response
toJsonString?(): string;
}
The recommended way to know when AbxrLib is ready to send data is to use the authentication completion callback:
// Subscribe to authentication completion - the recommended approach
Abxr.OnAuthCompleted((authData) => {
if (authData.success) {
console.log("Authentication successful - AbxrLib is ready!");
StartGameFlow(); }
} else {
console.error("Authentication failed:", authData.error);
StartGameFlow(); }
});
Why OnAuthCompleted is better:
- Event-driven: No need to poll or check status repeatedly
- Immediate notification: Called as soon as authentication completes
- Rich data: Provides user info, modules, and detailed authentication data
- Error handling: Includes specific error information when authentication fails
Note: Abxr.ConnectionActive()
is still available for advanced use cases, but OnAuthCompleted
is the recommended approach for most developers.
After authentication completes, you can access comprehensive learner data and preferences:
// Get learner data and preferences
const learnerData = Abxr.GetLearnerData();
if (learnerData) {
const userName = learnerData.name;
const audioPreference = learnerData.audioPreference;
console.log(`Welcome back, ${userName}!`);
setAudioLevel(audioPreference);
}
// Check connection status before accessing data
if (Abxr.ConnectionActive()) {
customizeExperience(Abxr.GetLearnerData());
}
Returns: Object containing learner data from the authentication response, or null if not authenticated
Available Data (when provided by authentication response):
- User Preferences:
audioPreference
,speedPreference
,textPreference
- User Information:
name
,email
,id
,user_id
- Custom Fields: Any additional data provided in the userData object
Use Cases:
- Personalization: Customize audio levels, playback speed, and text size based on user preferences
- Accessibility: Apply user-specific accessibility settings automatically
- User Experience: Greet users by name and show personalized content
- Analytics: Track usage patterns based on user preferences
- Adaptive Content: Adjust content difficulty or presentation based on user data
The ABXRLib SDK provides comprehensive session management capabilities that allow you to control authentication state and session continuity. These methods are particularly useful for multi-user environments, testing scenarios, and creating seamless user experiences across devices and time.
Start a new session with a fresh session identifier. This method generates a new session ID and performs fresh authentication, making it ideal for starting new training experiences or resetting user context.
// JavaScript Method Signature
await Abxr.StartNewSession();
Trigger manual reauthentication with existing stored parameters. This method is primarily useful for testing authentication flows or recovering from authentication issues.
// JavaScript Method Signature
await Abxr.ReAuthenticate();
Note: All session management methods work asynchronously and will trigger the OnAuthCompleted
callback when authentication completes, allowing you to respond to success or failure states.
For debugging authentication, network issues, or other problems, enable debug logging:
// Check if connection is established with the service
Abxr.ConnectionActive();
// Enable and check debug mode Method Sigantures
Abxr.SetDebugMode(enabled)
Abxr.GetDebugMode()
// Example usage
Abxr.SetDebugMode(true); // Enable debug logging
Abxr.SetDebugMode(false); // Disable debug logging
const isDebugging = Abxr.GetDebugMode();
console.log('Debug mode:', isDebugging);
// Conditional debug setup for development
if (process.env.NODE_ENV === 'development') {
Abxr.SetDebugMode(true);
}
Parameters:
enabled
(boolean): Enable or disable debug mode
Returns: GetDebugMode()
returns boolean indicating current debug state
Debug Mode Benefits:
- Detailed error messages: See exactly what's failing during authentication
- Network request logging: Track API calls and responses
- State information: Monitor internal library state changes
- Performance insights: Identify bottlenecks and timing issues
The ABXRLib SDK provides full compatibility with Mixpanel's JavaScript SDK, making migration simple and straightforward. You can replace your existing Mixpanel tracking calls with minimal code changes while gaining access to ABXR's advanced XR analytics capabilities.
- XR-Native Analytics: Purpose-built for spatial computing and immersive experiences
- Advanced Session Management: Resume training across devices and sessions
- Enterprise Features: LMS integrations, SCORM/xAPI support, and AI-powered insights
- Spatial Tracking: Built-in support for 3D position data and XR interactions
- Open Source: No vendor lock-in, deploy to any backend service
Migration Steps:
- Remove Mixpanel references (
import mixpanel from 'mixpanel-browser';
) - Remove: mixpanel.init('YOUR_PROJECT_TOKEN');
- Configure ABXRLib SDK credentials
- Replace
mixpanel.track
→Abxr.Track
throughout codebase - Replace
mixpanel.register
→Abxr.Register
throughout codebase for super metadata
// Mixpanel → ABXR migration example
// Before: mixpanel.track("Plan Selected", props);
// After: Abxr.Track("Plan Selected", props);
// JavaScript Method Signatures
static async Track(eventName: string, properties?: any): Promise<number>
// Abxr compatibility methods for Mixpanel users
Abxr.Track("user_signup");
Abxr.Track("purchase_completed", { amount: 29.99, currency: "USD" });
// Timed events
Abxr.StartTimedEvent("puzzle_solving");
// ... later ...
Abxr.Track("puzzle_solving"); // Duration automatically included
Feature | Mixpanel | ABXRLib SDK |
---|---|---|
Basic Event Tracking | ✅ | ✅ |
Custom Properties | ✅ | ✅ |
Super Metadata/Properties | ✅ | ✅ (Register/RegisterOnce available) |
Timed Events | ✅ | ✅ (StartTimedEvent available) |
XR-Specific Events | ❌ | ✅ (Assessments, Interactions, Objectives) |
Session Persistence | Limited | ✅ (Cross-device, resumable sessions) |
Enterprise LMS Integration | ❌ | ✅ (SCORM, xAPI, major LMS platforms) |
Real-time Collaboration | ❌ | ✅ (Multi-user session tracking) |
Open Source | ❌ | ✅ |
The ABXRLib SDK provides compatibility with most of the Cognitive3D SDK, allowing you to either migrate from Cognitive3D or use both libraries side-by-side. You can add or migrate to ABXRLib from existing Cognitive3D implementations with minimal code changes while gaining access to ABXR's advanced XR analytics capabilities and LMS integrations.
Note: This compatibility guide covers event tracking only. Spatial analytics features of Cognitive3D are not covered as they have different architectures.
- LMS Integration: Native LMS platform support with SCORM/xAPI compatibility
- Advanced Analytics: Purpose-built dashboards for learning and training outcomes
- Enterprise Features: Session management, cross-device continuity, and AI-powered insights
- Open Source: No vendor lock-in, deploy to any backend service
- Structured Events: Rich event wrappers for assessments, objectives, and interactions
- Side-by-Side Usage: Keep your existing Cognitive3D implementation while adding ABXR features
There are a few options for migration or combind usage
Option 1: Quick Migration If you want to replace Cognitive3D entirely, migration can be as simple as the following steps.
Step 1: Disable import statement
// Before: import { CustomEvent } from 'cognitive3d';
// After: //import { CustomEvent } from 'cognitive3d';
Step 2: Replace "Cognitive3D." with "Abxr." throughout your codebase to use the compatibility methods
// Before (Cognitive3D):
new Cognitive3D.CustomEvent("Pressed Space").Send();
// After (ABXRLib) - Direct replacement:
new Abxr.CustomEvent("Pressed Space").Send();
Option 2: Side-by-Side Usage Keep your existing Cognitive3D implementation and add ABXRLib for enhanced features:
// Your existing Cognitive3D code stays unchanged, and then add the Abxr version right below
new Cognitive3D.CustomEvent("Pressed Space").Send();
new Abxr.CustomEvent("Pressed Space").Send();
// Both libraries work side-by-side seamlessly
Cognitive3D.StartEvent("final_exam");
Abxr.EventAssessmentStart("final_exam"); // Enhanced LMS integration
// Later...
Cognitive3D.EndEvent("final_exam", "pass", 95);
Abxr.EventAssessmentComplete("final_exam", 95, Abxr.EventStatus.ePass); // Structured data
Option 3: Detailed Event Tracking Migration Step 1: Disable import statement
// Before: import { CustomEvent } from 'cognitive3d';
// After: //import { CustomEvent } from 'cognitive3d';
Step 2: Review all your "Cognitive3D." usage to convert and improve the data being sent.
///// CUSTOM EVENTS /////
// Before (Cognitive3D):
new Cognitive3D.CustomEvent("Pressed Space").Send();
// After (ABXRLib) - Direct replacement:
new Abxr.CustomEvent("Pressed Space").Send();
// After (ABXRLib) - Recommended approach:
Abxr.Event("Pressed Space");
///// START/END EVENTS (Assessment Tracking) /////
// Before (Cognitive3D):
Cognitive3D.StartEvent("final_exam");
Cognitive3D.EndEvent("final_exam", "pass", 95);
// After (ABXRLib) - Direct replacement:
Abxr.StartEvent("final_exam");
Abxr.EndEvent("final_exam", "pass", 95);
// After (ABXRLib) - Recommended approach:
Abxr.EventAssessmentStart("final_exam");
Abxr.EventAssessmentComplete("final_exam", 95, Abxr.EventStatus.ePass);
///// SEND EVENT (Objective Tracking) /////
// Before (Cognitive3D):
Cognitive3D.SendEvent("valve_opened", {
result: "success",
score: 100
});
// After (ABXRLib) - Direct replacement:
Abxr.SendEvent("valve_opened", {
result: "success",
score: 100
});
// After (ABXRLib) - Recommended approach:
Abxr.EventObjectiveComplete("valve_opened", 100, Abxr.EventStatus.eComplete);
///// SESSION PROPERTIES /////
// Before (Cognitive3D):
Cognitive3D.SetSessionProperty("user_type", "technician");
// After (ABXRLib) - Direct replacement:
Abxr.SetSessionProperty("user_type", "technician");
// After (ABXRLib) - Recommended approach:
Abxr.Register("user_type", "technician");
///// LOGGING /////
// Before (Cognitive3D):
Cognitive3D.Log("Assessment started");
// After (ABXRLib):
Abxr.Log("Assessment started"); // Defaults to Abxr.LogLevel.eInfo
// Or with specific levels:
Abxr.LogInfo("Assessment started");
Abxr.LogError("Error occurred");
Custom Event Properties:
// Cognitive3D approach:
new Cognitive3D.CustomEvent("button_press")
.SetProperty("button_id", "submit")
.SetProperty("screen", "main_menu")
.Send();
// ABXRLib equivalent:
new Abxr.CustomEvent("button_press")
.SetProperty("button_id", "submit")
.SetProperty("screen", "main_menu")
.Send();
// ABXRLib recommended:
Abxr.Event("button_press", {
button_id: "submit",
screen: "main_menu"
});
Result Conversion Logic:
The ABXRLib compatibility layer automatically converts common Cognitive3D result formats:
// These Cognitive3D result values...
"pass", "success", "complete", "true", "1" → Abxr.EventStatus.ePass
"fail", "error", "false", "0" → Abxr.EventStatus.eFail
"incomplete" → Abxr.EventStatus.eIncomplete
"browse" → Abxr.EventStatus.eBrowsed
// All others → Abxr.EventStatus.eComplete (default)
Feature | Cognitive3D | ABXRLib SDK |
---|---|---|
Spacial Analytics | ✅ | ❌ |
Basic Event Tracking | ✅ | ✅ |
Custom Properties | ✅ | ✅ |
Session Properties | ✅ | ✅ (Enhanced with persistence) |
LMS Integration | ❌ | ✅ (SCORM, xAPI, major platforms) |
Structured Learning Events | ❌ | ✅ (Assessments, Objectives, Interactions) |
Cross-Device Sessions | ❌ | ✅ (Resume training across devices) |
AI-Powered Insights | ❌ | ✅ (Content optimization, learner analysis) |
Open Source | ❌ | ✅ |
The SDK has built in dialogs to support the two-step authentication when the backend requires additional credentials (like a PIN or email). There are multiple approaches to handle this:
NEW: Zero-code authentication with beautiful, XR-optimized dialogs! Perfect for VR/AR developers:
import { Abxr_init } from 'abxrlib-for-webxr';
// Simple initialization - XR dialog appears automatically when needed
Abxr_init('app123', 'org456', 'secret789');
// That's it! The library handles everything:
// - Auto-detects XR environments vs regular browsers
// - Shows beautiful XR-optimized dialogs in VR/AR
// - Includes virtual keyboards for XR environments
// - Falls back to HTML dialogs for regular browsers
// - Handles all auth types (email, PIN, etc.) automatically
const dialogOptions = {
enabled: true,
type: 'xr', // 'html', 'xr', or 'auto' (default)
xrFallback: true, // Fallback to HTML if XR fails
xrStyle: {
colors: {
primary: '#00ffff', // Cyan accent
success: '#00ff88', // Green submit button
background: 'linear-gradient(135deg, #0a0a0a, #1a1a2e)',
keyBg: 'rgba(0, 255, 255, 0.1)', // Virtual keyboard keys
keyText: '#ffffff',
keyActive: '#00ffff'
},
dialog: {
borderRadius: '20px',
border: '3px solid #00ffff',
boxShadow: '0 0 50px rgba(0, 255, 255, 0.5)'
},
overlay: {
background: 'radial-gradient(circle, rgba(0, 255, 255, 0.2) 0%, rgba(0, 0, 0, 0.9) 100%)'
}
}
};
Abxr_init('app123', undefined, undefined, undefined, dialogOptions);
What makes XR dialogs special:
- 🥽 VR/AR Optimized: Beautiful in both desktop browsers and XR headsets
- ⌨️ Virtual Keyboard: Built-in keyboard for XR environments (PIN pad for PINs)
- 🎨 Fully Customizable: Colors, styling, and behavior - match your brand
- 🔄 Auto-Detection: Automatically chooses XR vs HTML dialog based on environment
- 📱 Universal: Works everywhere - desktop, mobile, and XR devices
For developers who want to provide their own authentication UI:
import { Abxr_init, Abxr, AuthMechanismData } from 'abxrlib-for-webxr';
// Define callback to handle authentication requirements
function handleAuthMechanism(authData: AuthMechanismData) {
console.log('Auth required:', authData.type); // e.g., 'email', 'assessmentPin'
console.log('Prompt:', authData.prompt); // e.g., 'Enter your Email'
console.log('Domain:', authData.domain); // e.g., 'acme.com' (for email type)
// Show UI to collect user input
const userInput = prompt(authData.prompt);
// Format and submit authentication data
const formattedAuthData = Abxr.formatAuthDataForSubmission(userInput, authData.type, authData.domain);
Abxr.completeFinalAuth(formattedAuthData).then(success => {
if (success) {
console.log('Authentication complete');
} else {
console.log('Authentication failed');
}
});
}
// Initialize with callback
Abxr_init('app123', undefined,undefined, undefined, undefined, handleAuthMechanism);
Check for additional authentication requirements manually (for advanced use cases):
import { Abxr_init, Abxr } from 'abxrlib-for-webxr';
// Step 1: Initial authentication
Abxr_init('app123', 'org456', 'secret789');
// Step 2: Check if additional authentication is required
if (Abxr.getRequiresFinalAuth()) {
console.log('Additional authentication required');
// Extract structured auth data
const authData = Abxr.extractAuthMechanismData();
if (authData) {
console.log('Auth type:', authData.type); // e.g., 'email', 'assessmentPin'
console.log('Prompt:', authData.prompt); // e.g., 'Enter your Email'
console.log('Domain:', authData.domain); // e.g., 'acme.com'
// Get user input
const userInput = prompt(authData.prompt);
// Format and submit
const formattedData = Abxr.formatAuthDataForSubmission(userInput, authData.type, authData.domain);
const success = await Abxr.completeFinalAuth(formattedData);
if (success) {
console.log('Authentication complete');
}
}
}
The SDK supports various authentication types:
email
: Email-based authentication with domain supportassessmentPin
: PIN-based authentication for assessments- Custom types: As defined by your backend service
Abxr.extractAuthMechanismData()
- Get structured auth requirementsAbxr.formatAuthDataForSubmission(input, type, domain?)
- Format user input for submissionAbxr.getRequiresFinalAuth()
- Check if additional auth is requiredAbxr.completeFinalAuth(authData)
- Submit final authentication credentials
Your Application ID can be found in the Web Dashboard under the application details. For the Authorization Secret, navigate to Settings > Organization Codes on the same dashboard.
Object tracking can be enabled by adding the Track Object component to any GameObject in your scene via the Unity Inspector.
Problem: Library fails to authenticate
- Solution: Verify your App ID, Org ID, and Auth Secret are correct
- Check: Ensure URL parameters
abxr_orgid
andabxr_auth_secret
are properly formatted - Debug: Enable debug mode with
Abxr.SetDebugMode(true)
to see detailed error messages
Problem: Two-step authentication not triggering
- Solution: Check that your callback is properly set before calling
Abxr_init()
- Check: Verify the
authMechanism
data is being returned by the server - Debug: Use
Abxr.extractAuthMechanismData()
to inspect authentication requirements
Problem: CORS errors or network failures
- Solution: The library automatically attempts version fallback for common CORS issues
- Check: Ensure your REST URL is correct and accessible
- Manual Fix: Try adding
/v1/
to your REST URL manually
Problem: Library doesn't work in development vs production
- Solution: Use URL parameters for credentials in production builds
- Check: Avoid hardcoding
orgId
andauthSecret
in distributed applications
Problem: Events not being sent
- Solution: Check connection status with
Abxr.ConnectionActive()
- Debug: Enable debug logging to see why events are being blocked
- Check: Verify your event names use snake_case format for best processing
Problem: Super Metadata not persisting
- Solution: Check that localStorage is available in your browser
- Debug: Use
Abxr.GetSuperMetaData()
to inspect current super metadata - Fix: Ensure you're calling
Abxr.Register()
after authentication completes
Problem: Sessions not resuming properly
- Solution: Check that the session ID is valid and not expired
- Debug: Use session management callbacks to track session state changes
- Check: Verify authentication credentials are still valid for session continuation
Best Practices:
// Always set up callbacks before initialization
Abxr.OnAuthCompleted(function(authData) {
if (authData.success) {
// Initialize your app components here
initializeApp();
} else {
console.error('Authentication failed');
}
});
// Then initialize
Abxr_init('your-app-id');
Getting Help:
- See Debug Mode for detailed logging and troubleshooting
- Check browser console for detailed error messages
- Verify network requests in browser developer tools
- Test authentication flow in isolation before adding complex features