How to Build an AI Content Generator for Marketing Emails
Generate marketing email copy at scale using AI with your brand voice.
What This Integration Does
This Spojit workflow turns a short campaign brief (product, audience, goal) into a complete marketing email: subject line, preheader, body HTML, and CTA, written in your brand voice. It pulls brand guidelines and prior-campaign context from a Knowledge collection so the generated copy isn't written in a vacuum, then routes the draft through a human approval step before pushing the final copy to Klaviyo or Resend for sending.
It's typically invoked through a Webhook trigger (a marketer fills in a form that posts a brief) but can also run on a Schedule trigger for recurring sends like weekly newsletters. The brief flows through generation, validation, and approval; on approval the email send fires, and each run is recorded in execution history so you can re-run a brief without re-sending.
Prerequisites
- A persistent Knowledge collection seeded with your brand guidelines, voice samples, and a few high-performing past emails (created in the Knowledge section of the sidebar).
- A klaviyo or resend connection for sending.
- A slack connection for the approval handoff (optional but recommended).
- At least one approval slot ready (a User, Role, or Team) for the Human node.
Step 1: Trigger with the Campaign Brief
Drop a Trigger node set to Webhook (so a form or internal tool can post a brief) or Manual for one-offs. The payload should carry at least:
{
"product": "Pro plan",
"audience": "trial users 7+ days in",
"goal": "drive upgrade",
"tone": "friendly, slightly urgent",
"segmentId": "klaviyo_segment_abc123"
}
Step 2: Pull Brand and Performance Context
Add a Knowledge node in Query mode. Point its Collection at your persistent brand collection and set the Prompt to something like "brand voice, banned phrases, CTA style for {{ trigger.body.audience }}". Bind the result to an Output Variable so later steps can read it. In parallel, add a Connector node on klaviyo / list-campaigns to gather recent campaigns; pass the open and click rates into the generation step so the copy can lean into what worked.
Step 3: Generate the Email with a Response Schema
Add a Connector node in Agent mode. Write a prompt that gives the agent the brief, the brand context from Step 2, and the recent-campaign stats, and ask it to draft the email. Turn on the Response Schema to force structured JSON output:
{
"type": "object",
"properties": {
"subjectLine": { "type": "string", "maxLength": 60 },
"preheader": { "type": "string", "maxLength": 100 },
"bodyHtml": { "type": "string" },
"ctaText": { "type": "string", "maxLength": 30 },
"ctaUrl": { "type": "string" },
"altSubjects": { "type": "array", "items": { "type": "string" }, "minItems": 2, "maxItems": 4 }
},
"required": ["subjectLine", "preheader", "bodyHtml", "ctaText", "ctaUrl"]
}
The altSubjects array gives you ready-made A/B variants.
Step 4: Render and Lint the HTML
Add a Transform node to inject your standard header and footer around bodyHtml. Then run a quick check with regex / test to flag risky patterns (raw http:// links, missing alt attributes on images, empty <a> hrefs). Use a Condition node to route flagged output back to the generation step with a corrective note rather than letting it reach a human.
Step 5: Human Approval
Add a Human node that surfaces the full preview (subject line, preheader, rendered HTML, CTA URL) in its Message. Add a marketer to an Approval slot (a User, Role, or Team); the run pauses until the slot is satisfied. The approver acts in the Approvals inbox and the outcome is either Approved (the run continues) or Rejected (the run halts). In parallel, post a notification via slack / send-message to the marketing channel so the team sees a draft is waiting.
Step 6: Send via Klaviyo or Resend
Because a rejected approval halts the run, the send steps simply follow the Human node: they only execute when the approval is granted. Wire one of these connector paths after it:
- Klaviyo path: push the segment via klaviyo /
add-profiles-to-list, or record a campaign signal withcreate-event, then run your Klaviyo campaign send. - Resend path: call resend /
send-batch-emailswith the recipient list and rendered HTML.
To keep a record of rejected drafts for prompt tuning, log them earlier in the run (before approval) with a mongodb / insert-documents call, since downstream "on reject" branching is not available once a run halts.
Tips
- Seed the Knowledge base properly. Three or four exemplar emails do more for voice consistency than any amount of prompt engineering.
- Give the model the brief, not the prompt. Marketers shouldn't have to write prompts. A short structured form is enough.
- Cap subject length in the schema. Long subject lines get truncated on mobile. The
maxLengthin the JSON schema makes the model self-enforce.
Common Pitfalls
- Generic copy. Without brand context the model produces fine-but-bland writing. The Knowledge node is the difference between "AI copy" and "your copy".
- Banned phrases leaking through. Add a final regex pass on
bodyHtmlagainst your banned-phrase list and require a human edit if any match. - Mobile rendering. Test on at least one mobile email client before broad send; the model can produce HTML that looks fine on desktop but breaks on Gmail mobile.
- Compliance. Promotional emails need a working unsubscribe link. Make the footer template a hard-coded part of the Transform step, not something the model can edit.
Testing
Run the workflow end-to-end with a 5-person internal test segment first. Check the rendering across three mail clients (Gmail web, Gmail mobile, Outlook), confirm the CTA URL resolves, and verify the Klaviyo or Resend send actually fired. Iterate on the prompt until two consecutive runs produce copy you'd happily send before opening it up to the main marketer.