Outcome. New contacts missing a usable email or phone number are flagged and routed to a cleanup queue instead of sitting incomplete and unnoticed.
Workflow mapEnrollment, branches and actions at a glance
flowchart TD
A[Contact created] --> B{Email and phone present?}
B -->|both missing| C[Flag: Missing contact info + list + task]
B -->|email only| D[Flag: Missing phone + list]
B -->|phone only| E[Flag: Missing email + list]
B -->|both present| F[Flag: Complete]
When to use it / when not to
- Use it when reps or forms let contacts through with only a name and no way to reach them.
- Use it when import processes bypass form validation and create sparse records.
- Do not use it expecting it to block record creation. Workflows react after a record exists; they cannot prevent creation. For hard blocking, use required fields on the form itself.
- Do not use it for consent or subscription required fields. That belongs to marketing-ops scope, not data-quality.
Prerequisites
- Property:
Data quality flag, internal namedata_quality_flag, object contact, field type dropdown select, optionsMissing contact info/Missing phone/Missing email/Complete. Why: gives a single filterable marker independent of list membership. - Static list:
Needs contact info review, type static. Why: the workflow adds records here so a data owner can work a queue instead of hunting through reports. - Confirm which person or team owns cleanup follow-up, so the internal notification and task go to a real owner, not a placeholder.
Enrollment
- Trigger type: event-based.
- Criteria:
Contact was created. No filter groups needed here; the branching happens inside the workflow. - Re-enrollment: off. This is a one-time check at creation. If you also want to catch existing records that later lose their email, add a second, separate workflow rather than reusing this one, see Variants.
- Suppression: none required at creation. Optionally exclude contacts
already carrying lifecycle stage
customerfrom an import, since those typically have another system of record.
Steps
- If/then branch:
Emailis unknown ANDPhone numberis unknown- Set property value:
Data quality flag=Missing contact info - Add to static list:
Needs contact info review - Create task: type "To-do", title "Get contact info - {{contact.firstname}} {{contact.lastname}}", due in 2 business days, assigned to data owner
- Set property value:
- Else if:
Emailis known,Phone numberis unknown- Set property value:
Data quality flag=Missing phone - Add to static list:
Needs contact info review
- Set property value:
- Else if:
Phone numberis known,Emailis unknown- Set property value:
Data quality flag=Missing email - Add to static list:
Needs contact info review
- Set property value:
- Else (both present)
- Set property value:
Data quality flag=Complete
- Set property value:
Known pitfalls
- Workflows cannot stop a record from being created. This is a detect-and-flag pattern, not a hard block. For a hard block, use required fields on the form, or mark the property required on the contact create form (Settings > Objects > Contacts > customize the create form, Starter tier or higher); that setting only gates manual creation in the UI, not imports, API calls or workflow-created records (https://knowledge.hubspot.com/object-settings/set-up-fields-seen-when-manually-creating-records).
- "Email is unknown" and "Phone number is unknown" filters treat blank and unset values the same in most cases, and an empty string sent via the API clears the property, so it also matches "is unknown", which HubSpot defines as records with no value for the property (https://knowledge.hubspot.com/segments/determine-filter-criteria and https://developers.hubspot.com/docs/api-reference/crm-properties-v3/guide).
- Static list membership does not clear automatically once a record is
completed later. Build a small companion workflow (trigger:
Email has been changedORPhone number has been changed, action: remove from list when both become known) if you need the queue to self-clean. - Internal notifications sent to a fixed named user break silently if that person leaves the company. Use a team or a rotating owner instead of a hardcoded name.
Test plan
- Create four test contacts: no email/no phone, email only, phone only, both present.
- Open workflow history (Automation > Workflows > this workflow > History) and confirm all four enrolled.
- Check each record's
Data quality flagvalue matches the expected branch. - Confirm the two incomplete-info records landed in the
Needs contact info reviewlist. - Confirm the fully-missing record generated a task, visible in the assigned owner's task queue and on the record timeline.
Variants
- Company-level version: same structure, object company, trigger
Company was created, check domain and phone number. - Add a delay and reminder task for records still incomplete after 5
days, using a second branch on
Data quality flag is not equal to Complete. - Route to a specific rep instead of a shared queue when the source list (for example "Imported - trade show") implies a known owner.
Build spec
trigger:
type: event-based
event: contact_created
criteria: []
reenrollment: false
suppression_list: null
branches:
- condition: email_unknown AND phone_unknown
actions:
- type: set_property_value
property: data_quality_flag
value: "Missing contact info"
- type: add_to_static_list
list: "Needs contact info review"
- type: create_task
task_type: to_do
title: "Get contact info - {{contact.firstname}} {{contact.lastname}}"
due: +2_business_days
assigned_to: data_owner
- condition: email_known AND phone_unknown
actions:
- type: set_property_value
property: data_quality_flag
value: "Missing phone"
- type: add_to_static_list
list: "Needs contact info review"
- condition: phone_known AND email_unknown
actions:
- type: set_property_value
property: data_quality_flag
value: "Missing email"
- type: add_to_static_list
list: "Needs contact info review"
- condition: else
actions:
- type: set_property_value
property: data_quality_flag
value: "Complete"



