Skip to main content
Flex Forms dispatches Laravel events at clear lifecycle points. Use events + listeners (or queued listeners) for server-side reactions — not Eloquent observers on submission models.

FormSubmissionCompleted

Fired after a full (non-partial) submission is ingested and persisted — in the same afterCommit callback that queues FinalizeSubmissionSideEffectsJob. Partial saves dispatch FormSubmissionPartialSaved instead. Ordering (important): the event runs before outbound integrations and Studio post-submit actions. Those run asynchronously in the finalize job. Do not assume CRM delivery rows exist when your listener runs. If you need “after integrations,” listen for IntegrationDispatchSucceeded / PostSubmitActionSucceeded, or queue work that polls delivery status. The event carries:
  • $event->form — FlexForm instance
  • $event->submission — FlexFormSubmission instance
  • $event->context — typed SubmissionContext (source, formId, submissionId, optional safe meta) — never answers or secrets

Basic listener

app/Listeners/SyncSubmissionToCrm.php
Register in AppServiceProvider or an event service provider:
Or use Laravel’s attribute discovery (#[ListensTo(FormSubmissionCompleted::class)]) if your app uses it.

Queued listener

Offload slow work (CRM API, enrichment) to the queue:
Integrations, mail, and Insights side effects already use queues in production. Your listeners should assume a queue worker is running.

Other server events

Use these when you need observability beyond a single FormSubmissionCompleted hook.
Submission events are not ShouldBroadcast by default. Real-time admin dashboards are out of scope for this package — broadcast from your own listener if you need WebSockets.

Submission pipeline middleware

Pipeline middleware is registered once (config + push()). Duplicate class names are ignored so Octane/long-lived workers do not stack the same middleware repeatedly. For logic that must run before answers are saved (validation, enrichment, blocking spam), implement SubmissionMiddleware instead of listening after the fact.
app/FlexForms/BlockDisposableEmails.php
Register in config:
Or push at runtime from AppServiceProvider:
Check $payload->isAborted() downstream; aborted submissions surface the message to the respondent.
Do not attach Eloquent observers to FlexFormSubmission for ingest side effects. The ingestor owns persistence order; observers race integrations and encryption. Use events or pipeline middleware instead.

Client-side embed events

For marketing sites and SPAs, forward fill lifecycle events to the host page with formEventsForwarding=1 on the embed URL. The parent receives postMessage payloads like FlexForms.FormSubmitted. Full attribute list and event names: Embed widget API.
Last modified on September 7, 2026