Skip to content

Events

For the full event list and detail types, see iframe Events.

All events are listened for directly on the iframe object.

js
iframe.addEventListener("eventName", (event) => {
  const { detail } = event;
  const { api, sceneInfo } = detail;
  console.log(api, sceneInfo);
});

Except for the standard iframe load and error events, all other plugin events are CustomEvent objects.

Whenever you need business data, read it from detail.

The exact detail shape depends on the event. See each event definition for specifics.

Event Scope

The main events you should listen for on an iframe are flow events. They describe the overall lifecycle of the content, from initialization and asset download through loading, entering the experience, and changing recognition state.

If you want to listen for runtime object events, such as a model click or a video finishing playback, use api.on() from the Advanced API.

Trigger Conditions

load and error are foundational events that may come from either the browser or the plugin layer.

See also: iframe#error_and_load_event_behavior

Whether the other events are available depends on account permissions and domain authorization.

Detailed conditions

Account typeDomain authorized?Events available?
Free / StarterUnauthorized and cannot purchase authorizationNo
All usersUnauthorized, but host page is accessed via localhost or LAN IPYes
Pro / EnterpriseAuthorization not purchasedNo
Pro / EnterpriseAuthorizedYes

load

Standard browser event indicating that the iframe page itself has finished loading.

This only means Kivicube page code is running. It does not mean scene assets are fully downloaded.

error

Any error that occurs inside the plugin triggers this event.

It also fires when the user denies camera permission or gyroscope permission.

Example detection:

js
iframe.addEventListener("error", (e) => {
    if(e.detail?.isUserDeniedCamera) {
        console.log('The user denied camera permission');
    }

    if (e.detail?.isUserDeniedGyroscope) {
        console.log('The user denied gyroscope permission');
    }
});

detail types:

ts
interface ErrorType {
  message: string;
  isCameraNotFound?: boolean; // Camera not found. The hardware may be missing or broken.
  isUserDeniedCamera?: boolean; // User manually denied camera permission
  isUserDeniedGyroscope?: boolean; // User manually denied gyroscope permission (iOS)
}
interface ResponseServerError {
  message: string;
  code: number;
}
interface ErrorCustomEvent {
  detail: string | ErrorType | ResponseServerError;
}

Common cases include:

  • the scene or collection ID does not exist
  • camera permission was denied
  • motion and orientation permission was denied on iOS
  • asset download failed

incompatibility

Scenes or collections also trigger incompatibility when preflight compatibility checks fail.

Typical cases include:

  • the current browser does not support the required camera capability
  • the current in-app WebView is not suitable for WebAR
  • the current mode is unavailable on this client

The detail structure is not fully fixed, but it often includes marker objects such as unsupportCamera, so it is best treated as a signal to show a compatibility fallback UI.

ready

Triggered when scene or collection data is available and opening begins.

On scene pages, event.detail.sceneInfo contains basic scene information, and event.detail.api is the scene advanced API object.

On collection pages, event.detail.collectionInfo contains basic collection information, and event.detail.api is the collection advanced API object.

detail types:

ts
interface ReadyDetail {
  sceneInfo: SceneInfo | CollectionInfo;
  api: SceneApi | CollectionApi; // See the Advanced API docs for the exact runtime type.
}

interface ReadyCustomEvent {
  detail: ReadyDetail;
}

Type definitions:

SceneInfo

CollectionInfo

js
iframe.addEventListener("ready", (event) => {
  const { detail } = event;
  const { api, sceneInfo, collectionInfo } = detail;
  console.log(api, sceneInfo, collectionInfo);
});

downloadAssetStart

Triggered when scene assets start downloading.

downloadAssetProgress

Triggered when download progress changes. detail ranges from 0.0 to 1.0.

js
iframe.addEventListener('downloadAssetProgress', (event) => {
  console.log(`Download progress: ${(event.detail * 100).toFixed(0)}%`);
});

downloadAssetEnd

Triggered when asset download finishes.

If the Start Now Button is not hidden, the flow usually waits for the user to click that button before entering loadSceneStart.

If you plan to customize the Start Now Button with advanced APIs, this is also a common moment to call getStartButtonRect() / setStartButtonRect().

loadSceneStart

Triggered when assets start being loaded into the scene runtime.

loadSceneEnd

Triggered when scene loading finishes.

As a general rule, this is a safe time to register object events, read object lists, and do runtime object processing.

sceneStart

Triggered when the scene actually starts.

For non-recognition scenes, it usually fires quickly. For Image AR or Basic AR/Gyroscope scenes, it means the experience has entered a usable state, even though recognition state may still continue changing.

tracked

Triggered when a recognition-based scene successfully tracks the target.

Common uses:

  • hide host-layer scan guidance
  • show a custom photo button
  • fire analytics

lostTrack

Triggered when a recognition-based scene loses the tracked target.

openUrl

Triggered when the scene tries to perform an "open webpage" action. detail is usually the target URL.

If you enabled disableOpenUrl, this event still fires, so the host layer can decide whether to:

  • show a second confirmation dialog
  • route through its own navigation system
  • record analytics before navigating

Collection-Only Events

sceneReady

Triggered when the collection switches to a concrete scene and receives that scene's data.

detail.sceneInfo has the same structure as sceneInfo in a scene ready event.

detail.api has the same type as api in a scene ready event.

sceneDestroy

Triggered when the collection is about to destroy the current scene and switch to the next one.

ts
interface SceneDestroyDetail {
  sceneId: string; // ID of the scene being destroyed
}

Event Order Reference

Scene

Usually:

text
load
-> ready
-> downloadAssetStart
-> downloadAssetProgress
-> downloadAssetEnd
-> loadSceneStart
-> loadSceneEnd
-> sceneStart

Collection

Usually:

text
load
-> ready
-> sceneReady
-> downloadAssetStart
-> downloadAssetProgress
-> downloadAssetEnd
-> loadSceneStart
-> loadSceneEnd
-> sceneStart

For most projects, it is a good idea to listen for at least:

js
iframe.addEventListener('ready', onReady);
iframe.addEventListener('downloadAssetProgress', onProgress);
iframe.addEventListener('sceneStart', onSceneStart);
iframe.addEventListener('tracked', onTracked);
iframe.addEventListener('lostTrack', onLostTrack);
iframe.addEventListener('openUrl', onOpenUrl);
iframe.addEventListener('error', onError);
iframe.addEventListener('incompatibility', onIncompatibility);