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 labelstatus—draftorpublishedpublishedVersionId— 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 incrementingversionNumber. 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 atype and a config object with type-specific properties (label, placeholder, required, options, etc.).
Block types:
Actions
Theactions object on a version defines what happens after submission — currently used for the success state (redirect URL or success message display).
Widget status lifecycle
- 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.