Skip to main content

4 minutes read Level: IntermediateLast Updated: October 2025

Split by Custom Expression

In certain flows, it is necessary to deliver different responses to different contacts based on their previous selections or stored profile attributes, such as location, batch start date, or opt-in status.

The Custom Expression is useful in scenarios where it is necessary to:

  • Branch the flow according to a contact’s attribute values
  • Compare dates or times
  • Perform calculations within the flow (for example, days since registration)
  • Combine multiple variables into a single output

Split by a custom expression` uses a coding syntax to match the response received or profile attribute.

The expression follows a format such as: <%= if (variable_name == "string" or number), do: 1, else: 0 %>


Custom Expressions cheatsheet

1. Get Today's Date (IST​)

<%= Timex.today("Asia/Kolkata") |> Date.to_string() %>

2. Get Today's Date and Time (IST)​

<%= DateTime.now!("Asia/Kolkata") |> DateTime.to_string() %>

3. Adding the Date and Time Stamp

To capture the date and time. Example - start time of a flow and the end time of a flow, following custom expression can be used <%= DateTime.now!("Asia/Kolkata") |> Calendar.strftime("%H:%M:%S") %>

Add a Update Contact node and pass the mentioned expression.

Screenshot 2025-10-08 at 4 23 11 PM

4. Calculating the Time Difference

Use case: To calculate the time taken by a contact to complete the flow. Considering the prerequisite that the start time and end time are captured at the flow level in separate variables, the difference can be calculated using the following expression.

<%= Time.diff(Time.from_iso8601!("@contact.fields.time_end"), Time.from_iso8601!("@contact.fields.time_start"), :second) %>

The above expression calculates the difference between @contact.fields.time_end and @contact.fields.time_start in seconds. And the screenshot below updates this difference to a contact variable @contact.fields.timer using update the contact node.

Screenshot 2025-10-08 at 4 26 00 PM

5. Calculating the Difference Between Two Dates

Use case: Calculating the date difference between the current date and a given date (e.g., batch start date or onboarding date of the contact). Here, @calendar.current_date is used to store the batch start date at the time of onboarding. @calendar.current_date returns the date in the format D/0M/YYYY, where: D = day without a leading zero 0M = month with a leading zero YYYY = full numeric year

For example:

  • 2nd January 2025 → 2/01/2025
  • 11th October 2024 → 11/10/2024

The following expression can be used to calculate the difference in days between the current date and the stored batch start date: <%= "@contact.fields.batch_start_date"|>Timex.parse!("{D}/{0M}/{YYYY}") |> then(&(Timex.diff(Timex.now(), &1, :day))) %>

In the screenshot, this expression calculates the date difference and updates the value to a new flow result: @results.datediff

Screenshot 2025-10-08 at 4 34 44 PM

6. Concatenating Strings or Variables

  • To combine two variables in a contact field.
  • In the given example, @results.Var1 @results.Var2 are joined.
Screenshot 2025-10-08 at 4 36 06 PM
  • Use Case: Suppose @results.grade.category contains the value 2 and @contact.fields.s_acp contains the value 4, then the the value of the @contact.fields.present_grade_acp is updated to value of “Grade 2 ACP 4”, By simply writing Grade @results.grade.category ACP @contact.fields.s_acp to update a contact field called present_grade_acp.
Screenshot 2025-10-08 at 4 38 23 PM
  • Similarly, other example of concatenating the node is the following node which Updates the value of @contact.fields.cumulative_acp
  • By adding a comma and the value contained in @contact.fields.present_grade_acp to the already existing values in @contact.fields.cumulative_acp
  • Suppose the @contact.fields.cumulative_acp is set to 0, and suppose the value of @contact.fields.present_grade_acp contains the value Grade 1 ACP 1, then after the node is encountered, the updated value of @contact.fields.cumulative_acp becomes 0, Grade 2 ACP 1
  • In the next flow, if the @contact.fields.present_grade_acp contains the value Grade 1 ACP 2, then after encountering the same node, the value of @contact.fields.cumulative_acp is updated to 0, Grade 1 ACP 1, Grade 2 ACP 1
  • In this way, a contact variable can be used to store the history of progression/ paths taken by a contact.
Screenshot 2025-10-08 at 4 43 44 PM

7. Converting a string to lowercase.

  • Any input variable can be converted to lowercase by using the following expression: <%= String.downcase(“@results.resultname”) %>
  • In the above expression @results.resultname can be replaced with the string or the flow variable or the contact variable containing the string that needs to be converted to lowercase.
  • In the screenshot given below, two tasks are happening at once The flow variable @results.flow_keyword.input is getting converted to the lowercase The lowercase value of flow variable @results.flow_keyword.input is getting saved to the contact variable keyword

Use case: Same flow can be started using multiple keywords. The keyword entered by a contact is used to determine which partner org, city and school is the contact representing. This data is picked up from a separate google sheet maintained by the NGO. Thus reducing the step by the contact to share details like org, school name, city.

Screenshot 2025-10-08 at 4 47 58 PM

8. Validating Date Format and Range

WhatsApp interface does not enable providing a calendar menu to select and enter dates. In order to accomplish collection of cleaner date format, following custom expression can be used: To capture the date in DD/MM/YYYY format(Validating date input using Split By or Wait for Response)

  • Use split by node or in the wait for response include the validation condition for matches regex and check the following . In the given example split by was used with the following regex:

^(0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[0-2])/(?:202[5-9]|2030)$

How it works:

  • (0[1-9]|[12][0-9]|3[01]) - Ensures the DD value (numbers before the /) is between 01 and 31.

  • (0[1-9]|1[0-2]) - Ensures the MM value does not exceed 12.

  • (?:202[5-9]|2030) - Ensures the YYYY value is between 2025 and 2030.

  • Customisation: You can modify the regex to match other formats, such as MM/DD/YYYY or DD-MM-YYYY, by adjusting the sequence and separators accordingly.

Screenshot 2025-10-08 at 4 57 26 PM

9. Validating Time Format (24 Hour)

Users can use a Split By node or, in a Wait for Response node, include a validation condition with Matches Regex to validate time inputs. In the given example, the regex used is: ([01][0-9]|2[0-3]):([0-5][0-9])$

How it works:

  • ([01][0-9]|2[0-3]) → Ensures the hour value is between 00 and 23.
  • ([0-5][0-9]) → Ensures the minutes value is between 00 and 59.
  • : → The colon acts as the delimiter between hours and minutes.
Screenshot 2025-10-08 at 4 59 57 PM

Advanced Syntax Examples

  1. Syntax to check if contact belongs to a specific collection (collection 1 or collection 2) <%= if "collection 1" in @contact.in_groups, do: 1, else: if "collection 2" in @contact.in_groups, do: 2, else: 3 %>

Add a Split by expression node and the above mentioned expression.

Screenshot 2025-10-08 at 5 02 07 PM
  1. Syntax to check if the contact is registered or not. <%= if "@contact.fields.is_registered" == "1" , do: 1, else: 0 %>

  2. Syntax to check if the contact has opted-in or not. <%= if @contact.optin_status == true, do: 1, else: 2%>

Screenshot 2025-10-08 at 5 03 04 PM
  • Any variable created and saved can be used to make decisions within a Split By custom expression.
  • Writing the correct syntax for a Split By expression requires some coding knowledge. If you have specific requirements or need help crafting the right expression, please reach out to us on Discord. We’ll be happy to share the exact syntax tailored to your needs.

Advanced Feature Webinar

Video Link