Lifecycle Events
The SDK emits lifecycle events during iframe mount/unmount operations and SDK teardown — useful for analytics, debugging, coordinating UI state, and cleanup.
Lifecycle Diagram
Intellirent.init()
│
▼
┌─────────────────┐
│ SDK Active │◄───── ────────────────────────┐
└────────┬────────┘ │
│ │
│ sdk.mount(selector) │
▼ │
┌─────────┐ │
│MOUNTING │ ─── Event emitted │
└────┬────┘ │
│ │
▼ │
┌─────────┐ │
│ MOUNTED │ ─── Event emitted │
└────┬────┘ │
│ │
│ sdk.unmount() │
│ or instance.destroy() │
▼ │
┌───────────┐ │
│UNMOUNTING │ ─── Event emitted │
└─────┬─────┘ │
│ │
▼ │
┌───────────┐ │
│ UNMOUNTED │ ─── Event emitted ───────────────┘
└───────────┘
│ sdk.destroy()
▼
┌───────────┐
│DESTROYING │ ─── Event emitted
└─────┬─────┘
│ (unmounts iframe if mounted)
▼
┌───────────┐
│ DESTROYED │ ─── Event emitted
└───────────┘
│
▼
SDK Inactive (cannot be reused)
Events Reference
| Event | When Emitted | Payload |
|---|---|---|
mounting | Before iframe creation starts | { selector } |
mounted | After iframe is ready and initialized | { selector, instanceId } |
unmounting | Before iframe cleanup starts | { selector, instanceId } |
unmounted | After iframe cleanup is complete | { selector, instanceId } |
destroying | Before SDK teardown starts | { hadMountedIframe } |
destroyed | After SDK is fully torn down | { hadMountedIframe } |
component_loaded | When the component's iframe is about to begin loading (before HTML/CSS starts fetching), emitted right after mounting | { component, sessionId, timestamp } |
component_ready | When component is interactive and ready for use | { component, sessionId, timestamp, loadTimeMs } |
component_error | When a component-level error occurs | { component, sessionId, timestamp, errorCode, errorMessage } |
component_destroyed | When a component is unmounted within the iframe | { component, sessionId, timestamp, durationMs } |
Typed Events
Event names are the string literals in the table above, and LifecycleEventMap
maps each name to the payload its listener receives. In TypeScript, sdk.on()
infers the payload type from the event name, so a listener never needs an explicit
annotation.
type LifecycleEventType =
| "mounting"
| "mounted"
| "unmounting"
| "unmounted"
| "destroying"
| "destroyed"
| "component_loaded"
| "component_ready"
| "component_error"
| "component_destroyed";
interface LifecycleEventMap {
mounting: MountEventPayload;
mounted: MountEventPayload;
unmounting: UnmountEventPayload;
unmounted: UnmountEventPayload;
destroying: DestroyEventPayload;
destroyed: DestroyEventPayload;
component_loaded: ComponentLoadedPayload;
component_ready: ComponentReadyPayload;
component_error: ComponentErrorPayload;
component_destroyed: ComponentDestroyedPayload;
}
type LifecycleEventListener<T extends LifecycleEventType> = (
payload: LifecycleEventMap[T],
) => void;
// payload is inferred as MountEventPayload
sdk.on("mounted", ({ selector, instanceId }) => { /* ... */ });
// payload is inferred as ComponentReadyPayload
sdk.on("component_ready", ({ component, loadTimeMs }) => { /* ... */ });
Basic Usage
Subscribing to Events
const sdk = Intellirent.init({
publishableKey: "pk_test_xxx",
userContext: { userId: "user_123", userType: "END_USER" },
});
// Subscribe using event name string
sdk.on("mounted", ({ selector, instanceId }) => {
console.log(`Iframe mounted at ${selector} with id ${instanceId}`);
});
sdk.on("unmounted", ({ selector, instanceId }) => {
console.log(`Iframe unmounted from ${selector}`);
});
// Mount the form (triggers 'mounting' then 'mounted' events)
await sdk.mount("#application-form");
Unsubscribing from Events
There are two ways to unsubscribe:
// Method 1: Use the returned unsubscribe function
const unsubscribe = sdk.on("mounted", (payload) => {
console.log("Mounted:", payload);
});
// Later, when you want to stop listening:
unsubscribe();
// Method 2: Use sdk.off() with the same listener reference
const listener = (payload) => {
console.log("Mounted:", payload);
};
sdk.on("mounted", listener);
// Later:
sdk.off("mounted", listener);
Common Use Cases
Analytics & Tracking
Track widget usage for analytics:
const sdk = Intellirent.init({
publishableKey: "pk_live_xxx",
userContext: { userId: "user_123", userType: "END_USER" },
});
sdk.on("mounted", ({ selector, instanceId }) => {
analytics.track("widget_mounted", {
selector,
instanceId,
timestamp: Date.now(),
});
});
sdk.on("unmounted", ({ selector, instanceId }) => {
analytics.track("widget_unmounted", {
selector,
instanceId,
timestamp: Date.now(),
});
});
Loading States
Show/hide loading indicators:
const sdk = Intellirent.init({
publishableKey: "pk_live_xxx",
userContext: { userId: "user_123", userType: "END_USER" },
});
sdk.on("mounting", ({ selector }) => {
showLoadingSpinner(selector);
});
sdk.on("mounted", ({ selector }) => {
hideLoadingSpinner(selector);
});
React Integration
Use lifecycle events with React's useEffect. The SDK is loaded via <script> tag in your index.html and available as a global:
import { useEffect, useRef, useState } from "react";
function ApplicationWidget({ publishableKey, userId, userType }) {
const sdkRef = useRef(null);
const [isLoading, setIsLoading] = useState(true);
const [isMounted, setIsMounted] = useState(false);
useEffect(() => {
const sdk = Intellirent.init({
publishableKey,
userContext: { userId, userType },
});
sdkRef.current = sdk;
// Track mounting state
sdk.on("mounting", () => setIsLoading(true));
sdk.on("mounted", () => {
setIsLoading(false);
setIsMounted(true);
});
sdk.on("unmounted", () => setIsMounted(false));
// Mount the widget
sdk.mount("#widget-container");
// Cleanup on unmount
return () => {
sdk.destroy();
};
}, [publishableKey]);
return (
<div>
{isLoading && <LoadingSpinner />}
<div id="widget-container" style={{ opacity: isMounted ? 1 : 0 }} />
</div>
);
}
Cleanup Verification
Ensure proper cleanup in tests or debugging:
const sdk = Intellirent.init({
publishableKey: "pk_test_xxx",
userContext: { userId: "user_123", userType: "END_USER" },
});
let wasUnmounted = false;
sdk.on("unmounted", () => {
wasUnmounted = true;
console.log("Iframe was properly unmounted");
});
sdk.on("destroyed", ({ hadMountedIframe }) => {
console.log(`SDK destroyed. Had mounted iframe: ${hadMountedIframe}`);
if (hadMountedIframe && !wasUnmounted) {
console.warn(
"Cleanup issue - iframe was mounted but unmount event not received",
);
}
});
// Mount the form
await sdk.mount("#application-form");
// Full teardown
sdk.destroy();
// Logs: "Iframe was properly unmounted"
// Logs: "SDK destroyed. Had mounted iframe: true"
SDK Destruction
After calling sdk.destroy(), the SDK instance cannot be reused:
const sdk = Intellirent.init({
publishableKey: "pk_test_xxx",
userContext: { userId: "user_123", userType: "END_USER" },
});
await sdk.mount("#container");
sdk.destroy();
// This will throw an error:
try {
await sdk.mount("#another-container");
} catch (error) {
console.error(error.message);
// "SDK has been destroyed. Create a new instance with Intellirent.init()"
}
// Create a new instance if needed:
const newSdk = Intellirent.init({
publishableKey: "pk_test_xxx",
userContext: { userId: "user_123", userType: "END_USER" },
});
await newSdk.mount("#another-container"); // Works fine
Event Payload Reference
MountEventPayload
interface MountEventPayload {
/** CSS selector where iframe is being mounted */
selector: string;
/** Instance ID (only available in 'mounted' event) */
instanceId?: string;
}
UnmountEventPayload
interface UnmountEventPayload {
/** CSS selector of the unmounted iframe */
selector: string;
/** Instance ID that was unmounted */
instanceId: string;
}
DestroyEventPayload
interface DestroyEventPayload {
/** Whether an iframe was mounted when destroy was called */
hadMountedIframe: boolean;
}
ComponentLoadedPayload
interface ComponentLoadedPayload {
component: string; // Component type (e.g., 'consumer_screening')
sessionId: string; // Per-mount correlation ID (sess_<12 hex chars>); not IframeInstance.id/instanceId
timestamp: string; // ISO 8601 timestamp
}
ComponentReadyPayload
interface ComponentReadyPayload {
component: string; // Component type (e.g., 'consumer_screening')
sessionId: string; // Per-mount correlation ID (sess_<12 hex chars>); not IframeInstance.id/instanceId
timestamp: string; // ISO 8601 timestamp
loadTimeMs: number; // Time from component_loaded (iframe load starting) to component_ready in ms — includes iframe creation, not just HTML/CSS fetch time
}
ComponentErrorPayload
interface ComponentErrorPayload {
component: string; // Component type (e.g., 'consumer_screening')
sessionId: string; // Per-mount correlation ID (sess_<12 hex chars>); not IframeInstance.id/instanceId
timestamp: string; // ISO 8601 timestamp
errorCode: string; // Error code
errorMessage: string; // Human-readable error message
}
ComponentDestroyedPayload
interface ComponentDestroyedPayload {
component: string; // Component type (e.g., 'consumer_screening')
sessionId: string; // Per-mount correlation ID (sess_<12 hex chars>); not IframeInstance.id/instanceId
timestamp: string; // ISO 8601 timestamp
durationMs: number; // Total time the component was alive in ms
}
Best Practices
-
Always clean up: Call
sdk.destroy()when your application/component unmounts to prevent memory leaks. -
Use unsubscribe functions: Store and call unsubscribe functions if you need to remove listeners before SDK destruction.
-
Handle errors in listeners: The SDK catches errors thrown in event listeners to prevent breaking functionality, but you should still handle errors appropriately.
-
Unmount before remounting: Call
sdk.unmount()before mounting to a different container. -
Reinitialize after destroy: Once destroyed, an SDK instance cannot be reused. Call
Intellirent.init()again if needed.
Next Steps
- Getting Started — Installation and setup
- Screening Pre-fill — Pre-populate form fields with known data