These docs are a work in progress and may not be fully up to date. Some pages may contain internal notes for our team.
Skip to Content
EmbeddingPreview mode

Preview mode

The Live Preview rail in the Finder Builder embeds the same widget that runs on your website, but in preview mode — a special state where the widget reads your unsaved changes from the dashboard instead of the published version on the CDN, and where analytics are suppressed so your edit-time interactions don’t pollute your metrics.

This page explains what preview mode is, when it triggers, and the small set of edge cases where you might encounter it as an integrator.

What preview mode does

When the widget enters preview mode, three things change versus normal operation:

  1. Payload comes from the parent frame — the widget reads finder design + locations from a JavaScript variable the dashboard sets, not from the CDN.
  2. Analytics are suppressed — no POST /analytics events are sent. Edit-time interactions don’t affect your reported metrics.
  3. Authorized URLs are bypassed — preview mode runs inside the dashboard, which doesn’t need to be on your finder’s authorized origins list.

The first one is what makes Live Preview feel instant: when you change a color in the builder, the widget re-reads the payload from the parent frame and re-renders, with no CDN round-trip.

When preview mode triggers

Preview mode is opt-in via globals on window, set by the page hosting the widget. The dashboard sets these globals when it embeds the widget in Live Preview; nothing else does.

The contract is three globals:

GlobalPurpose
window.__LF_PREVIEW_MODEA boolean. When true, preview-mode behavior activates.
window.__LF_PREVIEW_SESSIONA session id. Used to correlate preview-mode interactions for the parent frame.
window.__LF_PREVIEW_PAYLOADThe full design + locations payload, replacing what the widget would have fetched from the CDN.

The widget checks for these on init. If they’re set, it enters preview mode. If they’re not (the typical case for any embed on a real website), it runs normally.

🔒 Internal only: The __LF_PREVIEW_* globals form a private contract between the dashboard and the widget. They are intentionally undocumented as a public API — third-party embedders should not use them, and the names are subject to change without notice. Customer-facing docs describe their existence (this page) only because it’s useful to know the dashboard’s preview is “the real widget” and not a separate render path.

Why this matters to integrators

In normal use, you don’t need to do anything related to preview mode. Your production embed never enters it because nothing on your host page sets the __LF_PREVIEW_* globals.

The two situations where this is worth knowing:

Situation 1 — Your dashboard interactions don’t show up in analytics

This is by design. Live Preview is a preview mode embed; preview mode suppresses analytics. If you click around in the Finder Builder testing your finder, you won’t see those interactions in the Analytics view.

To test analytics for real, embed on a real (or local-dev) page outside the dashboard.

Situation 2 — Live Preview shows changes the host page doesn’t

Live Preview reads your unsaved + just-saved state via the parent-frame payload. Your host page reads from the CDN, which has a 5-minute cache. This means Live Preview is several minutes ahead of what your visitors see.

That’s the design — Live Preview is the iteration loop; the CDN is the propagation surface. See Caching for the full explanation.

Edge case: spotting a preview-mode embed on production

Almost impossible, but technically possible: if some other tool on your host page accidentally sets window.__LF_PREVIEW_MODE = true before the widget loads, the widget enters preview mode for that visitor. Symptoms:

  • The widget renders, but with no real data (because the __LF_PREVIEW_PAYLOAD global is empty)
  • No analytics events are recorded for that visitor’s session
  • Console may log a preview-mode notification

If you suspect this is happening, check whether anything on your host page is touching the __LF_* namespace. You can verify in the browser console:

window.__LF_PREVIEW_MODE // should be undefined or false on a real embed window.__LF_PREVIEW_SESSION // should be undefined window.__LF_PREVIEW_PAYLOAD // should be undefined

In production, all three should be undefined.

Why these globals exist (briefly)

The dashboard needs to embed the same widget visitors see, so what visitors see is what the dashboard owner is editing. But the embed in the dashboard has different needs than the one on a host page:

  • It needs to render unsaved changes (no CDN round-trip)
  • It needs to bypass the host-page allowlist (the dashboard isn’t on it)
  • It needs to suppress analytics (so editing doesn’t show up as visits)

Rather than maintain two widget builds (one for production, one for the dashboard), the codebase uses one widget with a small “preview mode” branch. The globals are how the parent frame (the dashboard) tells the embedded widget which mode to run in.

This is one of those decisions where the elegant solution is also the safe one: the same code paths run in production and in preview, just with different inputs.

Edge cases and limitations

  • Preview mode is all-or-nothing. You can’t preview “just the design” while keeping real-time analytics. The mode toggles all three behaviors together.
  • The session id is opaque. It’s used internally to correlate preview interactions; you can’t read it from the dashboard or set it yourself.
  • No deep-link to “preview as visitor would see it.” If you want to verify your finder from the visitor’s perspective without publishing changes, the workflow is: save → wait 5 minutes → load on a real (or local) host page outside the dashboard.

Where to next