Signals Docs
Concepts

Surveys & full-page forms

Multi-question popups shown by the tag, and hosted full-page forms shared by link — built from templates in the dashboard.

A survey is an ordered list of questions — NPS, rating, single/multiple choice, short/long text, email, number — with optional welcome and thank-you screens and a per-survey theme. Build one in Dashboard → Surveys from a template (post-purchase NPS, CSAT, exit-intent, email capture, quick poll …), from scratch, or by describing it — the AI generator turns a sentence like "post-purchase NPS for the new skincare line with an open follow-up" into a ready-to-edit draft.

One setting decides how it reaches the visitor:

DeliveryHow it works
Modal / popupInjected on your site by the tag — corner popup (popup_br/popup_bl) or centered modal.
Full pageA hosted page at /f/<siteId>/<key> on the dashboard host — share the link in emails, DMs, QR codes. Nothing is injected.

Custom form domain

Hosted forms can live on your own hostname. In the survey editor's hosted-form card, set a custom form domain (site-wide) and add a DNS-only CNAME:

TypeNameValue
CNAMEformsconnect.pixelfox.app

The TLS certificate issues automatically on the first request (same gate as first-party tracking domains), and every active form becomes https://forms.yourstore.com/<key>.

When a modal survey shows

All of these gates must pass, in order:

  1. Status — only active surveys ship to the tag.
  2. Trigger — one of: a pageview whose URL matches target_url_pattern (substring, or regex with a ~ prefix); a tracked event matching target_event; a trigger rule targeting the survey; or an explicit signals.showSurvey("key") call.
  3. Frequencyonce_visitor (persisted), once_session, or always.
  4. Rolloutrollout_percentage uses a sticky hash of distinct_id:survey_id, so the same visitor stays in or out.
  5. Schedule — optional starts_at / ends_at window. Outside it the survey (and its hosted form) stops shipping even while status is active.
  6. Delaydelay_ms after the trigger fires.

Size: the engage bundle is lazy

Survey and promo rendering lives in a separate signals-engage.min.js bundle. The core tag only calls GET /v1/engage at boot; the bundle is injected only when that returns something active, so sites without surveys or promos load zero extra bytes.

Responses

Answers POST to /v1/surveys/respond keyed by question id. The backend normalizes them per question type, marks the response completed when every required question was answered, and captures the email when an email question validates. Results — NPS score, per-option histograms, CSV export — live at Dashboard → Surveys → Responses. Hosted-form submissions carry metadata.channel = "hosted_form"; widget submissions carry "widget".

SDK API

signals.showSurvey("post-purchase-nps"); // → boolean (found?)
signals.dismissSurvey();
signals.onSurveys((surveys) => { /* active surveys loaded */ });

On this page