Skip to content

Product tours

Tours are multi-step walkthroughs rendered by the Kilden SDK on your own pages: each step is a card that either points at an element of your page (tooltip + spotlight) or, with no anchor, shows as a centered modal. They are a type of in-app unit, so targeting, scheduling and display rules work the same as banners and surveys — the server decides who sees a tour, the SDK decides where and when.

A tour never breaks your page: a selector that doesn’t match anything simply skips that step, and every listener is cleaned up when the tour ends.

In the panel, go to In-app → New unit → Tour. Each step has:

Field What it does
Text What the step says (plus an optional title and image URL)
Anchor A CSS selector for the element the step points at. Empty = centered modal
Placement Which side of the anchor the card appears on (top, bottom, left, right, or centered)
Advance Next button (default), or advance when the visitor clicks the anchored element itself

Steps advance in order; visitors can go back, and a Skip control is shown unless you disable it. Tours default to a frequency of once: a visitor who finished (or skipped) a tour won’t see it again.

You don’t have to write selectors by hand. Next to each step’s anchor field, Pick on your site opens your page in a new tab with the Kilden picker toolbar active — click the element you want and the selector lands back in the editor.

The picker synthesizes the most stable selector it can find, preferring (in order):

  1. A stable id
  2. A data-* attribute — with data-kilden-tour above all others
  3. Semantic attributes (aria-label, name, role, href)
  4. The element’s visible text
  5. Structural position (nth-child chains)

CSS utility classes (Tailwind and friends) are never used: they change with every restyle. Levels 4 and 5 are marked weak — they work, but they depend on copy or layout that can change.

Picking is author-only: the toolbar activates via a short-lived ticket signed by the panel and verified server-side before it mounts. Visitors never see or download any of it.

The most reliable anchor is one that exists for the tour. Add a data-kilden-tour attribute to the elements you point at:

<button data-kilden-tour="take-a-number">Take a number</button>

The step’s anchor is then [data-kilden-tour="take-a-number"] — immune to restyles, copy changes and DOM reshuffles. When the picker can only find a weak anchor, it suggests the exact attribute to add. If you can edit your markup, do this; it’s one attribute and the anchor never breaks.

When the best available anchor is the element’s visible text, the picker emits Kilden’s :kilden-text("…") extension on top of a CSS base:

button:kilden-text("Take a number")

The SDK resolves the base selector and filters by the element’s own trimmed text. Mind that this breaks the moment the copy changes (including translations) — prefer data-kilden-tour when you can.

Iterating on a live tour used to be painful: one real visit marks it as seen and it never shows again. Preview on my site (under the editor’s live preview) solves this:

  • Your page opens with the tour rendered exactly as edited right now — even unsaved changes.
  • Nothing is marked as seen, no analytics events are recorded, and frequency/URL rules are bypassed: preview means “show me now”.
  • A floating Kilden preview bar offers Replay, so you can watch the tour as many times as you need.
  • The preview starts at the step you were editing, not at step one.
  • What the SDK would have tracked is mirrored to the browser console ([kilden] preview (not tracked): …).

Like the picker, the preview is authorized by a short-lived signed ticket — a visitor can’t trigger it by editing the URL.

If your page changes and a step’s selector stops matching, the tour degrades gracefully: the step waits up to 3 seconds (for late-rendering SPAs), then is skipped. Visitors are never stuck — but the step silently disappears.

The panel watches for this. Each anchored step’s reach is measured ($tour_step_viewed per step), and when a step shows zero reach while the tour keeps starting, the editor flags it with Anchor may be broken — distinguishing “never matched” from “stopped matching recently” (the signature of a deploy that renamed the element). Re-pick the element, or better, give it a data-kilden-tour attribute.

Tours emit $ events you can query like any other data:

Event When
$tour_started The first step rendered
$tour_step_viewed A step rendered ($step_index, $step_id)
$tour_completed The visitor reached the end
$tour_dismissed The visitor skipped out

The unit’s detail page shows a per-step drop-off funnel (unique people per step, keyed by the step’s immutable id).