FormSubmissionCompleted
Fired after a full (non-partial) submission is ingested and persisted — in the sameafterCommit 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—FlexForminstance$event->submission—FlexFormSubmissioninstance$event->context— typedSubmissionContext(source,formId,submissionId, optional safemeta) — never answers or secrets
Basic listener
app/Listeners/SyncSubmissionToCrm.php
AppServiceProvider or an event service provider:
#[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
AppServiceProvider:
$payload->isAborted() downstream; aborted submissions surface the message to the respondent.
Client-side embed events
For marketing sites and SPAs, forward fill lifecycle events to the host page withformEventsForwarding=1 on the embed URL. The parent receives postMessage payloads like FlexForms.FormSubmitted.
Full attribute list and event names: Embed widget API.