Skip to content

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

js
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:

FieldTypeDescription
tourIdstringThe tour's unique identifier
tourNamestringThe tour's display name
versionnumberThe published version number
totalStepsnumberTotal number of steps in the tour (excluding skipped steps)
triggerstringThe trigger type that caused the tour to start (page_load, manual, event, etc.)

Example:

js
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:

FieldTypeDescription
tourIdstringThe tour's unique identifier
tourNamestringThe tour's display name
versionnumberThe published version number
stepsCompletednumberNumber of steps the user viewed
totalStepsnumberTotal number of steps in the tour
durationMsnumberTime in milliseconds from tour start to completion
stepsSkippednumberNumber of steps skipped due to missing target elements

Example:

js
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:

FieldTypeDescription
tourIdstringThe tour's unique identifier
tourNamestringThe tour's display name
versionnumberThe published version number
dismissedAtStepnumberThe step index (0-based) where the user dismissed
stepsCompletednumberNumber of steps viewed before dismissal
totalStepsnumberTotal number of steps in the tour
durationMsnumberTime from tour start to dismissal

Example:

js
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:

FieldTypeDescription
tourIdstringThe parent tour's identifier
tourNamestringThe parent tour's display name
stepIdstringThe step's unique identifier
stepIndexnumberThe step's position in the tour (0-based)
totalStepsnumberTotal number of steps
stepTitlestringThe step's title text
selectorstringThe CSS selector used to target the element
targetFoundbooleanWhether the target element was found
waitMethodstringHow the element was found: 'immediate', 'mutation_observer', 'polling', or 'timeout'
waitDurationMsnumberTime spent waiting for the target element

Example:

js
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:

js
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:

FieldTypeDescription
eventNamestringThe name passed to Spotlight.track()
dataobjectThe payload passed to Spotlight.track() (empty object if none)
js
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:

FieldTypeDescription
contentIdstringThe content item's unique identifier
contentTypestringThe content type: 'spotlight', 'tooltip', 'hotspot', 'modal', 'banner', or 'checklist'
contentNamestringThe content item's display name
triggerstringThe trigger type that caused the content to appear
urlstringThe page URL where the content was shown
sourcestring'programmatic' when fired by Spotlight.show(); omitted otherwise.

Example:

js
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:

FieldTypeDescription
contentIdstringThe content item's unique identifier
contentTypestringThe content type
contentNamestringThe content item's display name
durationMsnumberTime the content was visible before dismissal
interactedbooleanWhether the user interacted with the content (clicked a CTA, checked a checklist item, etc.)

Example:

js
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:

FieldTypeDescription
contentIdstringThe parent checklist's identifier
itemIdstringThe completed item's identifier
itemTitlestringThe completed item's title text
completedItemsnumberTotal items now completed
totalItemsnumberTotal items in the checklist

checklist:complete

Fired when all items in a checklist have been completed.

Payload:

FieldTypeDescription
contentIdstringThe checklist's identifier
contentNamestringThe checklist's display name
totalItemsnumberTotal items in the checklist
durationMsnumberTime from first item completion to last

Integration Examples

Send All Events to Your Analytics Pipeline

js
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

js
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

js
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

EventFires When
tour:startTour begins displaying
tour:completeUser finishes the last step
tour:dismissUser closes a tour before completing
step:viewA tour step is displayed
content:viewAny non-tour content is displayed
content:dismissAny non-tour content is dismissed
checklist:item_completeA checklist item is checked off
checklist:completeAll checklist items are completed

Spotlight