Control when workflow actions fire as patients move through intake forms — syncing data to an EHR or CRM, or sending messages at exactly the right step.
Use this file to discover all available pages before exploring further.
This doc is for anyone building workflows that react to patient form submissions. When a patient submits a form step, Morf receives that data and needs to know what to do with it. These expressions help you control exactly when those actions fire, so the right data reaches the right destination at the right time. To check out our existing destinations, see our Integrations page.
Use this when you only want an action to fire on a specific step of a multi-step form, not every time the patient submits anything.Start here — match a single step by name:
step_id.orValue("") == "[STEP NAME]"
Match any step that contains a phrase:
step_id.contains("[PHRASE]")
Match any of several steps:
step_id in ["[STEP 1]", "[STEP 2]", "[STEP 3]"]
Examples:
step_id.orValue("") == "Insurance Details"step_id.contains("Child #2")step_id in ["Q4_LET'S START WITH THE BASICS", "Q4B_FREE CALL INFO"]
Step names must match exactly. Copy-paste the step name from your form builder — including capitalization, spaces, and punctuation. If it doesn’t match, the filter won’t fire.
The field name step_id is used throughout this doc and is the standard for Morf forms. Other form tools (like Formsort) may use a different field name — check your event payload if step_id isn’t populated.
Suggested Prompts for Flo AI
Use these sample prompts with Flo to generate a CEL expression that fits your goals.
Only trigger this action when the patient reaches the Insurance Details step.
Use this when you want the workflow to take a different path depending on what the patient answered — for example, sending them down an insurance path vs. a cash pay path.Template:
Use this when you want to make sure an action — like creating a HubSpot contact — only happens once, even if the workflow runs multiple times for the same patient.Only run if a property has NOT been set yet:
Use this when you want to send eligible and ineligible patients down different branches based on their insurance or screener results.Start here — single eligibility check:Patient is eligible:
get_current_property_value("has_diagnosis_report") // Read the diagnosis report property .optMap(diag, diag == "No" // Pass if value is "No" ).orValue(false) // Missing property → fail this check&&get_current_property_value("primary_insurance") // Read the primary insurance object .?payer_name // Safely access the payer name field .optMap(primaryPayer, primaryPayer != "Medicaid" // Pass if payer is not Medicaid ).orValue(false) // Missing insurance or payer → fail this check&&( get_current_property_value("secondary_insurance") // Read the secondary insurance object .?payer_name // Safely access the payer name field .optMap(secondaryPayer, secondaryPayer != "Medicaid" // Pass if payer is not Medicaid ).orValue(true) // No secondary insurance → pass this check)
Suggested Prompts for Flo AI
Use these sample prompts with Flo to generate a CEL expression that fits your goals.
Only continue if the patient's primary insurance is not Medicaid.
Route to the eligible branch if screener_completion_status is 'eligible'.
Handle multilingual or optional fields with fallbacks
Use this when your form has two versions of the same field — like English and Spanish — and you want to use whichever one the patient filled out.Template:
morf_profile_ids.healthie.?id.hasValue() || step_id == "Booking in progress"
Check for the platform ID before creating or updating records. If the patient hasn’t been linked to HubSpot or Intercom yet, the action won’t have the ID it needs and will fail. Add this check in a filter node before any CRM action.
For the complete CEL function reference — including all available operators, string functions, date helpers, and optional chaining syntax — see the CEL Reference.