Evose
BuildTutorials

Tutorial · Marketing Automation

Build an end-to-end Workflow that cleans leads, generates personalized content, and sends across channels

Turn a raw customer-lead CSV into a batch of personalized emails + SMS, sent automatically. 60 minutes.

What You'll Get

A Workflow scheduled (every workday 09:00):

Read CSV (leads) → Batch (per row) → Clean → Score → Generate email → Send → Write back to CRM

Prerequisites

  • A leads CSV (name / email / industry / last contacted / recent product viewed)
  • An email-sending API (SMTP / SendGrid / Mailchimp)
  • A CRM write-back API (optional)

Step 1 · Connect SMTP (10 minutes)

Org · Credential management — register:

Name: smtp_password
Type: Password
Value: <your SMTP password>

Workspace · ToolsAdd HTTP Plugin:

Name: Email Sender
Method: send
URL:  https://api.sendgrid.com/v3/mail/send
Auth: Bearer {{credential:smtp_password}}
Input schema: {to, subject, html}

Step 2 · Upload CSV as Data Source (5 minutes)

Workspace → Data · Data sourceNew → upload leads.csv.

Step 3 · Build the Workflow (35 minutes)

Workspace → Apps · WorkflowNewLead Marketing Pro.

3.1 Start Node

Inputs (empty, since it's scheduled):

inputs:
  date: string  # default {{start_time}}

3.2 Read CSV

Drag a Code node to read the data source's CSV:

import csv
data = read_data_source('leads.csv')
leads = list(csv.DictReader(data))
return {'leads': leads}

3.3 Batch Node

Drag a Batch node to run the downstream branch per lead:

input_list: {{leads}}
item_var: lead

Sub-flow:

Sub-node 1 · LLM Scoring

prompt: |
  Based on the lead info, score 1–10 (10 = high intent).
  Lead: {{lead}}
  Last contacted: {{lead.last_contacted}}
  Recently viewed: {{lead.viewed_product}}
 
  Output the number only.
output_var: score

Sub-node 2 · Conditional

condition: {{score}} >= 7
true → sub-node 3
false → skip

Sub-node 3 · LLM Generates Email

prompt: |
  You are a B2B salesperson. Write a concise email for the lead. Subject short; body ≤ 200 words.
  Warm, professional, with a concrete next step.
 
  Lead: {{lead}}
  Score: {{score}}/10
  Our product: {{lead.viewed_product}}
 
  Output JSON:
  {"subject": "...", "html": "<html>...</html>"}
output_var: email

Sub-node 4 · Send Email

Tool node Email Sender.send:

to: {{lead.email}}
subject: {{email.subject}}
html: {{email.html}}

Sub-node 5 · Write Back to CRM (optional)

HTTP node writes back to CRM, marking "marketed".

3.4 End Node

outputs:
  total: {{leads.length}}
  sent: <count of successful sends>

Step 4 · Debug (5 minutes)

Trial-run → watch the per-lead execution. Open Trace to verify:

  • Are scores reasonable?
  • Are emails personalized?
  • Are API calls successful?

Step 5 · Configure Scheduling (2 minutes)

Workbench → ScheduleNew:

App: Lead Marketing Pro
Mode: cron
Expression: 0 9 * * MON-FRI    # workdays 09:00
inputs: { date: {{start_time}} }

Step 6 · Post-Launch Monitoring

Workspace → Observability:

MetricTarget
Single-run latency< 10 min (≤ 1000 leads)
Email send success rate> 99%
Score distributionReasonable share of 7+
Tokens per leadEvaluate cost structure

Going Further

I want to…Add
Add SMS channelAfter the conditional, fan out an SMS node in parallel
Different industries, different templatesAdd intent classification by industry to fan out
Track click-throughAdd UTM params in emails; aggregate click logs in another Workflow
Retry failed emailsAdd a retry node (auto-retry not in MVP yet — manual loop required)

Reflections

  • Don't treat the LLM as a hammer — LLM scoring is pricey at million-lead scale; use rules + LLM for fallback
  • Don't blast emails simultaneously — add sleep / rate-limit nodes to protect downstream
  • Don't skip CRM write-back — without tracking, no retro

Next Steps