Widget

Overview

LoaderCoreView Host Your App Loader Loader (DOM access) Host->Loader load loader.js Loader->Host traffic event Core Core iframe Orchestration logic Loader->Core secure iframe View View iframe UI runtime Loader->View spawn srcdoc view Core->Loader commands View->Loader events

Our widget runtime is intentionally split into three parts so you can run it with confidence:

  • Loader: the only script that touches your DOM. It creates the Core iframe, manages Views, and lets you observe every message before it moves.
  • Core: a sandboxed iframe hosted on our CDN that handles targeting, orchestration, and view lifecycle decisions.
  • View: a sandboxed iframe built from inline srcdoc markup that renders what your customers see.

Key guarantees for your team

  • Your DOM stays yours. Only the Loader script can touch it, and the loader is short enough for a quick audit or even self-hosting.
  • Every message is visible. We raise a cancelable getuserfeedback:traffic event containing { direction, from, to, payload } so you can log, adjust, or veto any payload.
  • No surprise network traffic. Loader/View do not call fetch; only the Core iframe performs network requests. Views are inlined, and any asset fetches come from your own page, not hidden calls inside the widget.
  • Origin-pin by default. Core will only run from https://cdn.getuserfeedback.com; unexpected origins are blocked before a handshake completes.

How messages stay secure

  • Signed envelope. Every message starts with the getuserfeedback: prefix and includes version, session, role, and typed payload details. This prevents unrelated postMessage traffic from entering the channel.
  • Challenge/response handshake. Loader and Core exchange one-time challenges. Any mismatch shuts the session down immediately.
  • Ready gate. Messages from your host app queue until the handshake finishes. Nothing reaches Core early, even if you call APIs during page boot.

Isolation by design

  • Dedicated iframes. Core and View run in their own iframes with sandbox policies; neither can reach out and mutate your page directly.
  • View bootstrapping. Loader injects a short bootstrap script and a viewId into the srcdoc payload so that each View is uniquely tracked.
  • Minimal Loader code. Because Loader has the sensitive job of touching the DOM, it remains slim and well reviewed.

Network and content controls

  • Strict Content Security Policy. Core ships with locked-down frame-src and nonce-based script-src directives, keeping executable content predictable.
  • Sandboxed iframes. We enable only the flags necessary for surveys to run (allow-scripts, allow-same-origin when needed). Everything else stays disabled.
  • Inline-first rendering. View markup runs from inline HTML; when larger experiences are required we may use Blob URLs, still without additional cross-origin fetches.
  • Host CSP-friendly Loader. The Loader only injects iframes; it does not perform network calls. Your host-page CSP can avoid granting connect-src for the widget and instead focus on script-src (loader.js) and frame-src/child-src (core iframe). The Core iframe still enforces its own CSP; host CSP does not override it.

Transparency tools for you

  • Hook into window.addEventListener('getuserfeedback:traffic', handler) to review or veto traffic in real time.
  • Use the observable events to feed your existing monitoring or governance pipelines.
  • Self-host the Loader if your policies require serving all scripts from your own domain.

Threat mitigations at a glance

ThreatWhat We Do
Unauthorized iframe sourceEnforce strict origin pinning and handshake validation.
Cross-frame DOM accessGive DOM privileges only to the Loader; keep Core/View sandboxed.
Protocol spoofingRequire the getuserfeedback: envelope with session and role metadata.
Hidden behaviourSurface every message via getuserfeedback:traffic before it is forwarded.
Replay or out-of-order trafficSequence messages through guarded state machines before delivery.
Inline script attacksApply tight CSP and avoid dynamic eval in Loader or Core.

Looking ahead

  • CSP reporting endpoints will give you deeper visibility into blocked resources.
  • Subresource Integrity (SRI) is under evaluation for teams that prefer CDN hosting without self-hosting.
  • Additional automated tests continue to stress malformed envelopes, replays, and network loss patterns.

Working with the SDK

  • createClient returns a client and fetches the widget by default (set disableAutoLoad: true to opt out).
  • The SDK enqueues init on load; the loader forwards it to core and the instance is ready once registration settles.
  • Use client.open(flowId), client.prefetch(flowId), and client.prerender(flowId) for flow lifecycle control.
  • For per-flow control, client.flow(flowId) exposes open, close, and subscribeFlowState.
  • The global API mirrors this model (window.__getuserfeedback.open(flowId), prerender(flowId), close()), with loader handling secure routing.
  • Consent defaults to granted (all scopes).
  • When a snapshot exists, analytics and app events require analytics.measurement to be granted.

Grow faster with user feedback

In-app user onboarding, surveys, and embedded forms for feedback-fueled product growth