SDK Events
The Spotlight SDK emits events at key points in the content lifecycle. Subscribe to events using Spotlight.on(event, handler) to integrate Spotlight with your analytics pipeline, trigger application logic, or synchronise UI state.
Subscribing to Events
const unsubscribe = Spotlight.on('tour:complete', (data) => {
console.log('Tour completed:', data);
});
// Remove the listener when no longer needed
unsubscribe();You can register multiple handlers for the same event. Handlers are called in registration order.
Tour Events
tour:start
Fired when a tour begins displaying to the user (first step is rendered).
Payload:
| Field | Type | Description |
|---|---|---|
tourId | string | The tour's unique identifier |
tourName | string | The tour's display name |
version | number | The published version number |
totalSteps | number | Total number of steps in the tour (excluding skipped steps) |
trigger | string | The trigger type that caused the tour to start (page_load, manual, event, etc.) |
Example:
Spotlight.on('tour:start', (data) => {
analytics.track('Onboarding Tour Started', {
tourId: data.tourId,
tourName: data.tourName,
version: data.version,
totalSteps: data.totalSteps,
});
});tour:complete
Fired when a user reaches the final step of a tour and either clicks "Finish" or the tour auto-completes.
Payload:
| Field | Type | Description |
|---|---|---|
tourId | string | The tour's unique identifier |
tourName | string | The tour's display name |
version | number | The published version number |
stepsCompleted | number | Number of steps the user viewed |
totalSteps | number | Total number of steps in the tour |
durationMs | number | Time in milliseconds from tour start to completion |
stepsSkipped | number | Number of steps skipped due to missing target elements |
Example:
Spotlight.on('tour:complete', (data) => {
analytics.track('Onboarding Tour Completed', {
tourId: data.tourId,
duration: data.durationMs,
completionRate: data.stepsCompleted / data.totalSteps,
});
});tour:dismiss
Fired when a user explicitly dismisses a tour before completing it (clicks the close button, presses Escape, or clicks outside the tour).
Payload:
| Field | Type | Description |
|---|---|---|
tourId | string | The tour's unique identifier |
tourName | string | The tour's display name |
version | number | The published version number |
dismissedAtStep | number | The step index (0-based) where the user dismissed |
stepsCompleted | number | Number of steps viewed before dismissal |
totalSteps | number | Total number of steps in the tour |
durationMs | number | Time from tour start to dismissal |
Example:
Spotlight.on('tour:dismiss', (data) => {
analytics.track('Onboarding Tour Dismissed', {
tourId: data.tourId,
dismissedAtStep: data.dismissedAtStep,
totalSteps: data.totalSteps,
completionPct: Math.round((data.stepsCompleted / data.totalSteps) * 100),
});
});Step Events
step:view
Fired each time a tour step is displayed to the user.
Payload:
| Field | Type | Description |
|---|---|---|
tourId | string | The parent tour's identifier |
tourName | string | The parent tour's display name |
stepId | string | The step's unique identifier |
stepIndex | number | The step's position in the tour (0-based) |
totalSteps | number | Total number of steps |
stepTitle | string | The step's title text |
selector | string | The CSS selector used to target the element |
targetFound | boolean | Whether the target element was found |
waitMethod | string | How the element was found: 'immediate', 'mutation_observer', 'polling', or 'timeout' |
waitDurationMs | number | Time spent waiting for the target element |
Example:
Spotlight.on('step:view', (data) => {
// Update a custom progress indicator in your app
updateProgressBar(data.stepIndex + 1, data.totalSteps);
// Track step-level analytics
analytics.track('Tour Step Viewed', {
tourId: data.tourId,
stepId: data.stepId,
stepIndex: data.stepIndex,
});
});Custom Events
Fire your own events via Spotlight.track(eventName, data).
event:<name>
Fired for every Spotlight.track(name, data) call. Content with trigger.type === "event" and matching event_name fires on this channel. Host code can also subscribe directly:
Spotlight.on('event:purchase_complete', (data) => {
console.log('Tracked purchase:', data);
});
Spotlight.track('purchase_complete', { plan: 'pro', amount: 19 });event:tracked
Catch-all observer for every track() call, useful for analytics adapters that want to forward every event to a downstream pipeline.
Payload:
| Field | Type | Description |
|---|---|---|
eventName | string | The name passed to Spotlight.track() |
data | object | The payload passed to Spotlight.track() (empty object if none) |
Spotlight.on('event:tracked', ({ eventName, data }) => {
analytics.track(`spotlight:${eventName}`, data);
});Content Events
Content events fire for all non-tour content types: spotlights, tooltips, hotspots, modals, banners, and checklists.
content:view
Fired when a content item is displayed to the user.
Payload:
| Field | Type | Description |
|---|---|---|
contentId | string | The content item's unique identifier |
contentType | string | The content type: 'spotlight', 'tooltip', 'hotspot', 'modal', 'banner', or 'checklist' |
contentName | string | The content item's display name |
trigger | string | The trigger type that caused the content to appear |
url | string | The page URL where the content was shown |
source | string | 'programmatic' when fired by Spotlight.show(); omitted otherwise. |
Example:
Spotlight.on('content:view', (data) => {
analytics.track('Spotlight Content Viewed', {
contentId: data.contentId,
type: data.contentType,
trigger: data.trigger,
page: data.url,
});
});content:dismiss
Fired when a content item is dismissed by the user (close button, click outside, or programmatic dismissal).
Payload:
| Field | Type | Description |
|---|---|---|
contentId | string | The content item's unique identifier |
contentType | string | The content type |
contentName | string | The content item's display name |
durationMs | number | Time the content was visible before dismissal |
interacted | boolean | Whether the user interacted with the content (clicked a CTA, checked a checklist item, etc.) |
Example:
Spotlight.on('content:dismiss', (data) => {
analytics.track('Spotlight Content Dismissed', {
contentId: data.contentId,
type: data.contentType,
duration: data.durationMs,
hadInteraction: data.interacted,
});
});Checklist Events
checklist:item_complete
Fired when a user completes (checks off) a checklist item.
Payload:
| Field | Type | Description |
|---|---|---|
contentId | string | The parent checklist's identifier |
itemId | string | The completed item's identifier |
itemTitle | string | The completed item's title text |
completedItems | number | Total items now completed |
totalItems | number | Total items in the checklist |
checklist:complete
Fired when all items in a checklist have been completed.
Payload:
| Field | Type | Description |
|---|---|---|
contentId | string | The checklist's identifier |
contentName | string | The checklist's display name |
totalItems | number | Total items in the checklist |
durationMs | number | Time from first item completion to last |
Integration Examples
Send All Events to Your Analytics Pipeline
const events = [
'tour:start',
'tour:complete',
'tour:dismiss',
'step:view',
'content:view',
'content:dismiss',
'checklist:item_complete',
'checklist:complete',
];
events.forEach((event) => {
Spotlight.on(event, (data) => {
analytics.track(`Spotlight ${event}`, data);
});
});Trigger Application Logic on Tour Completion
Spotlight.on('tour:complete', (data) => {
if (data.tourId === 'onboarding-tour') {
// Mark onboarding as complete in your app
api.updateUser({ onboardingComplete: true });
showConfetti();
}
});Sync Dark Mode with Tour Start
Spotlight.on('tour:start', () => {
// Ensure Spotlight theme matches current app theme
const isDark = document.documentElement.classList.contains('dark');
Spotlight.setTheme(isDark ? 'dark' : 'light');
});Event Summary
| Event | Fires When |
|---|---|
tour:start | Tour begins displaying |
tour:complete | User finishes the last step |
tour:dismiss | User closes a tour before completing |
step:view | A tour step is displayed |
content:view | Any non-tour content is displayed |
content:dismiss | Any non-tour content is dismissed |
checklist:item_complete | A checklist item is checked off |
checklist:complete | All checklist items are completed |