PostHog playbook
This is the copy-pasteable version of "how do I turn Spotlight events into useful product-analytics views in PostHog". Every event name and property below is emitted by the SDK unchanged — build dashboards against them and SDK upgrades won't break your definitions.
1. Wire up forwarding
Two prerequisites on your page:
- The PostHog JS SDK loaded with your project API key (the usual
posthog.init(...)snippet — nothing Spotlight-specific). - In Spotlight: Dashboard → Analytics → PostHog toggled on.
That's it. On the next SDK config refresh (≤ 30s TTL) the Spotlight SDK starts calling window.posthog.capture(name, props) for every event alongside its own backend writeback. No extra network hop from Spotlight — PostHog sees events at the same latency as your own.
Verify it's live
Open DevTools → Network, filter for /e/ (PostHog's event endpoint), trigger a tour, and watch the spotlight.tour_started event fly past. If you see Spotlight events on the Spotlight backend but not in PostHog, your PostHog SDK isn't loaded on that page.
2. Identify your users
PostHog funnels only stitch a journey together when events carry the same distinct_id. Two rules:
- Call
posthog.identify(user_id, props)as soon as your app knows who the user is — typically on login / session boot. - Pass the SAME
user_idtoSpotlight.init({ userId }).
If both use the same id, Spotlight events and your product events sit on one timeline in PostHog. If they diverge, your Spotlight events land on anonymous distinct_ids and funnels miss the later steps.
posthog.identify(currentUser.id, { plan: currentUser.plan });
Spotlight.init({
apiKey: 'sk_live_…',
userId: currentUser.id,
tokens: { plan: currentUser.plan },
});3. Canonical event names
Stable across SDK versions. Dashboards built against these names survive upgrades.
| Event | Fires when |
|---|---|
spotlight.impression | Any piece of content rendered on screen |
spotlight.click | Non-CTA click registered on content |
spotlight.cta_clicked | Primary CTA (tooltip / modal / banner / hotspot) |
spotlight.dismissed | User closed content (X, Escape, backdrop) |
spotlight.tour_started | Tour opened (welcome page or step 1) |
spotlight.tour_step_viewed | Tour advanced to a new step |
spotlight.tour_completed | User reached the finish page |
spotlight.tour_skipped | User closed the tour before finishing |
spotlight.hotspot_expanded | Hotspot card opened |
Every event carries content_id (tour / content identifier) plus event-specific props such as step_index, url_path, target (selector), and elapsed_ms since the previous step.
4. Insights to copy
4a. Tour completion funnel
Goal: "of users who started tour X, what % finished each step?"
- Type: Funnel
- Steps (in order):
spotlight.tour_startedwith propertycontent_idequals<your_tour_id>spotlight.tour_step_viewedwith propertycontent_idequals<your_tour_id>andstep_indexequals1spotlight.tour_step_viewedwith propertycontent_idequals<your_tour_id>andstep_indexequals2- (one row per step)
spotlight.tour_completedwith propertycontent_idequals<your_tour_id>
- Conversion window: 1 day (or one session — use whatever matches the tour's purpose)
- Attribution: First touch
This is the single most useful view. "Step 3 → step 4 drops by 60%" is a concrete signal that step 3's body is too long or step 4's target is too hard to find.
4b. Drop-off by step (trend, not funnel)
Useful when you've got a multi-tour product and want a bird's-eye view of where tours bleed out.
- Type: Trends
- Event:
spotlight.tour_skipped - Breakdown by property:
step_index - Filter:
content_idin[…your tour ids…] - Chart: Bar (cumulative)
4c. CTA click-through by page
Which pages' tooltips / modals actually convert?
- Type: Trends
- Events (two series):
spotlight.impression, breakdown byurl_pathspotlight.cta_clicked, breakdown byurl_path
- Formula:
B / A— click-through rate per URL - Sort descending. Low CTR on a high-traffic URL is the first thing to rewrite.
4d. Tour completers retention
Do users who finish a tour retain better than those who skip?
- Type: Retention
- Target event:
spotlight.tour_completed(cohort) - Returning event: any product event that means "used feature X"
- Comparison cohort:
spotlight.tour_skipped
If the two lines are the same, your tour isn't teaching anything — either the feature is obvious or the tour missed the mark.
5. Dashboard layout
One dashboard per tour, three tiles:
- Completion funnel (insight 4a).
- Impressions per day — Trends on
spotlight.impression, filtercontent_idequals your tour. Tells you whether the tour is even reaching enough people. - Weekly completers vs skippers — two trend series,
spotlight.tour_completedandspotlight.tour_skipped. Ratio over time is your "is this tour getting better or worse".
6. Gotchas
- PostHog feature flags apply to Spotlight events too. If you route
spotlight.*to a session-recording mute, recordings stop. Usually what you want; note it. - Anonymous → identified merging: PostHog merges anon sessions on identify, but only if your product SDK calls identify before Spotlight fires. The SDK's auto-start may emit events before your login round-trip completes; pass
autoStart: falsein Spotlight init if you need a strict order. - GA4 receives the same events, mangled. GA4's event-name rules are stricter (no dots, 40-char cap), so events land as
spotlight_tour_step_viewed. PostHog is unaffected.