Skip to content

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:

  1. Call posthog.identify(user_id, props) as soon as your app knows who the user is — typically on login / session boot.
  2. Pass the SAME user_id to Spotlight.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.

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

EventFires when
spotlight.impressionAny piece of content rendered on screen
spotlight.clickNon-CTA click registered on content
spotlight.cta_clickedPrimary CTA (tooltip / modal / banner / hotspot)
spotlight.dismissedUser closed content (X, Escape, backdrop)
spotlight.tour_startedTour opened (welcome page or step 1)
spotlight.tour_step_viewedTour advanced to a new step
spotlight.tour_completedUser reached the finish page
spotlight.tour_skippedUser closed the tour before finishing
spotlight.hotspot_expandedHotspot 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):
    1. spotlight.tour_started with property content_id equals <your_tour_id>
    2. spotlight.tour_step_viewed with property content_id equals <your_tour_id> and step_index equals 1
    3. spotlight.tour_step_viewed with property content_id equals <your_tour_id> and step_index equals 2
    4. (one row per step)
    5. spotlight.tour_completed with property content_id equals <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_id in […your tour ids…]
  • Chart: Bar (cumulative)

4c. CTA click-through by page

Which pages' tooltips / modals actually convert?

  • Type: Trends
  • Events (two series):
    1. spotlight.impression, breakdown by url_path
    2. spotlight.cta_clicked, breakdown by url_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:

  1. Completion funnel (insight 4a).
  2. Impressions per day — Trends on spotlight.impression, filter content_id equals your tour. Tells you whether the tour is even reaching enough people.
  3. Weekly completers vs skippers — two trend series, spotlight.tour_completed and spotlight.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: false in 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.

Last updated:

Spotlight