Skip to main content

Widget Architecture

Data model

A widget in Financely is composed of three layers:

Widget definition

The top-level record for a widget. It holds:
  • name — human-readable label
  • statusdraft or published
  • publishedVersionId — points to the currently live version (null if draft)
  • organizationId — scoped to an organization

Versions

Every time you click Save in the widget builder, a new version is created with an incrementing versionNumber. The version stores the full widget schema: pages, blocks, actions, and multi-step options. The published version is the one with versionId === publishedVersionId. Only this version is served to embedded widgets and used to process submissions.

Pages

A page is a single step in a multi-step form. A widget must have at least one page. Pages are ordered — the order in the version schema determines the step sequence shown to the user.

Blocks

Blocks live inside pages and define the form’s content and fields. Each block has a type and a config object with type-specific properties (label, placeholder, required, options, etc.). Block types:

Actions

The actions object on a version defines what happens after submission — currently used for the success state (redirect URL or success message display).

Widget status lifecycle

Only published widgets:
  • Render the embed script on external websites
  • Accept and process form submissions
  • Trigger lead creation and webhooks

Submission pipeline

When a visitor submits a widget form, the following happens server-side:
The endpoint always returns HTTP 200, even for rejected submissions (spam, honeypot, duplicate). This prevents abuse detection from being reverse-engineered.

Security model