Routing / Paths and conditions

Routing

Paths and conditions

Condition groups, operators, ownership rules and every field you can route on.

Every path in a router has a rule. When a lead arrives, Cauliflower checks the rules from top to bottom and runs the steps of the first path whose rule passes. This page covers how rules are built, every operator, ownership rules and every field you can route on.

Click a path node on the canvas to edit its rule. Under Rule type you choose between Without ownership, which matches on conditions alone, and CRM ownership, which also requires the lead to already have an owner.

Conditions and groups

A condition compares one field with a value, for example Employees greater or equal 1000. Conditions live in groups:

  • Inside a group, the group's match setting decides whether all conditions must pass or any one of them is enough.
  • When a path has more than one group, Groups match decides whether all groups must pass or any one of them.

Groups let you express "A and (B or C)". For an enterprise path that targets large companies in North America, either by headcount or by revenue:

GroupMatchConditions
Group 1allCountry is any of US, CA
Group 2anyEmployees greater or equal 1000, Annual revenue (USD) greater or equal 100m

With Groups match set to all, the path passes for a US company with 1,500 employees, or with 200 employees and 150 million in revenue, but not for a German company of any size.

A path with no conditions matches every lead ("No conditions: every lead matches this path"), and so does an empty group. A path can have up to 20 groups with up to 50 conditions each.

In the API, the same rule looks like this:

JSON
{
  "type": "conditions",
  "match": "all",
  "groups": [
    { "id": "g1", "match": "all", "conditions": [
      { "id": "c1", "field": "country", "operator": "in", "value": "US, CA" }
    ] },
    { "id": "g2", "match": "any", "conditions": [
      { "id": "c2", "field": "enrichment.employees", "operator": "gte", "value": 1000 },
      { "id": "c3", "field": "enrichment.revenue", "operator": "gte", "value": "100m" }
    ] }
  ]
}

Operators

OperatorAPI namePasses when
isequalsThe value equals the field. Numbers compare as numbers. For list fields, any item equals the value.
is notnot_equalsThe opposite of is.
containscontainsThe field is not empty and contains the text.
does not containnot_containsThe field doesn't contain the text. Empty fields pass.
starts withstarts_withThe field is not empty and starts with the text.
ends withends_withThe field is not empty and ends with the text, for example .edu.
is any ofinThe field equals one of the listed values.
is none ofnot_inThe field equals none of the listed values. Empty fields pass.
greater thangtBoth sides are numbers and the field is larger.
greater or equalgteBoth sides are numbers and the field is larger or equal.
less thanltBoth sides are numbers and the field is smaller.
less or equallteBoth sides are numbers and the field is smaller or equal.
is emptyis_emptyThe field is missing, blank or an empty list.
is not emptyis_not_emptyThe field has a value.
is trueis_trueThe field is true, yes, y, 1, on, checked or a non-zero number.
is falseis_falseThe field is anything else, including missing.
matches regexmatchesThe field matches a regular expression (case-insensitive).

The builder offers the operators that fit the field: yes/no fields get is true, is false, is empty and is not empty, and number fields get the comparisons. Fields you type by hand get every operator.

How values are compared

  • Text comparisons ignore case and surrounding spaces, so Acme is acme.
  • Lists for is any of and is none of are separated by commas or new lines: US, CA, MX.
  • Numbers tolerate formatting. Commas, spaces, currency signs and a trailing + are ignored, k, m and b multiply by a thousand, a million and a billion, and ranges compare by their lower bound. So 10k is 10,000, $5M is 5,000,000, 1000+ is 1,000 and the form answer 51-200 counts as 51.
  • Number comparisons never pass when either side isn't a number. A lead with no employee count fails both "greater or equal 1000" and "less than 1000", so add a path or catch-all for unknown sizes.
  • List fields such as enrichment.technologies pass is and is any of when any item matches, and contains checks the items joined into one text.
  • Regular expressions must be shorter than 500 characters. An invalid pattern never matches. For example, ^(ceo|cto|cfo|founder) on the job title.

Ownership rules

Set Rule type to CRM ownership to match leads whose account already has an owner. Choose where the owner comes from:

OptionOwner checked
Owner in the CRM or a previous Cauliflower ownerThe CRM record owner, then the lead's owner in Cauliflower
Owner in the CRMcrm.owner_email only
Previous Cauliflower ownerlead.owner_email only

The CRM owner is read from the record you choose under Integrations (by default, the company's owner; in Attio, the attribute you pick). Conditions on an ownership path are optional and must pass as well. For example, you can match only owned accounts that are on an enterprise plan.

An ownership rule only checks that an owner email exists. Pair it with a Display calendar or Assign to step that targets the Record owner, which looks the owner up among your members and falls back to a team or person when they aren't one. See Path steps. In the preview, ownership paths show the owner that was found, or "not found".

Fields you can route on

The field picker groups fields into Form fields, Lead, Lead history, CRM and Enrichment. To use a field that isn't listed, type its key and choose Use field.

Lead fields

FieldLabelValue
emailEmailThe lead's email, lowercased
first_name, last_name, nameFirst name, Last name, Full nameSplit from or joined with the full name when only one is sent
companyCompanyFrom the form, or the enriched company name when the form has none
phonePhoneFrom the form
domainEmail domainThe part after the @
is_personal_emailUses a personal emailTrue for Gmail, Outlook, iCloud, Proton and other free providers, plus the domains under Settings → Extra personal email domains
countryCountryFrom a form field named country, country_code or region
utm_source, utm_medium, utm_campaignUTM source, medium, campaignFrom the page URL, the widget or the API. Any other utm_ parameter works too.
page_urlPage URLThe page the form was submitted from

Lead history

FieldLabelValue
lead.is_existingLead seen beforeA lead with this email already exists in the workspace
lead.owner_emailLead owner emailThe email of the lead's current owner in Cauliflower
lead.meetings_countLead meetings bookedConfirmed and completed meetings for this lead

CRM fields

When Match against your CRM is on and a CRM is connected, the lookup adds:

FieldLabelValue
crm.person.existsCRM · person existsThe CRM has a person (contact or lead) with this email
crm.company.existsCRM · company existsThe CRM has a company (account) for the email domain, or linked to the person
crm.owner_emailCRM · owner emailThe record owner's email

Every attribute of the CRM records is available as well, as crm.person. or crm.company. followed by the attribute or property name, for example crm.company.industry or crm.person.job_title. The picker suggests attributes it has seen in this router's recent routing decisions. When the lookup is off, the two exists fields are false.

Enrichment fields

Normalized data from your CRM or Apollo. Lead enrichment explains where each value comes from.

FieldLabelType
enrichment.foundEnrichment foundyes/no
enrichment.sourceEnrichment source (attio / apollo)text
enrichment.titleJob titletext
enrichment.senioritySenioritytext
enrichment.departmentDepartmenttext
enrichment.countryPerson countrytext
enrichment.cityPerson citytext
enrichment.linkedin_urlLinkedIn URLtext
enrichment.company_nameCompany nametext
enrichment.company_domainCompany domaintext
enrichment.industryIndustrytext
enrichment.employeesEmployeesnumber
enrichment.revenueAnnual revenue (USD)number
enrichment.company_countryCompany countrytext
enrichment.founded_yearFounded yearnumber
enrichment.technologiesTechnologieslist

enrichment.state (the person's state or region, from Apollo) is also available if you type it.

Form fields and custom fields

Every field declared on the router's trigger appears under Form fields, with its options when it's a select. Anything else the form, the widget or the API sends can be routed on by typing its key. Keys ignore case, and spaces and dashes count as underscores, so Company Size and company_size are the same field.

Rules for common cases

PathRule
Personal emailUses a personal email is true
StudentsEmail ends with .edu
EnterpriseEmployees greater or equal 1000
Existing customersCRM ownership, owner in the CRM
Paid searchUTM source is any of google, bing and UTM medium is cpc
Returning leadsLead seen before is true and Lead meetings booked greater than 0

Use the live preview to check each path: it lists every condition with the value it expected and the value it found.