Marketing campaign builder skill
Draft and run Mailchimp email campaigns with AI-generated content, subject line A/B testing, and optimal send timing.
by hewi333·MIT license·★ 122 Stars on the repo·GitHub ↗
npx degit hewi333/Mom-n-Pop-Skills/skills/marketing-campaign-builder#main ~/.claude/skills/marketing-campaign-builderChecked ·commit main
Inside this skill
SKILL.md · the author's own words# Marketing Campaign Builder ## Overview Most small businesses have a Mailchimp list they never use. They sent a few campaigns years ago, got busy, and stopped. This skill fixes that by making campaign creation **fast and owner-gated**: 1. Owner texts a campaign idea in Telegram 2. Agent drafts the email content + 2-3 subject line options 3. Owner picks a subject line (or suggests their own) 4. Agent creates an A/B test campaign in Mailchimp 5. Agent sends a test email to the owner 6. Owner approves → agent schedules the send at optimal time **The owner never writes HTML, never logs into Mailchimp, never touches a template editor.** They just describe what they want and approve the draft.
Word-for-word excerpt, not a result. Read the full SKILL.md ↓
Files of Marketing campaign builder
Show the full text378 lines
Marketing Campaign Builder
Overview
Most small businesses have a Mailchimp list they never use. They sent a few campaigns years ago, got busy, and stopped. This skill fixes that by making campaign creation fast and owner-gated:
- Owner texts a campaign idea in Telegram
- Agent drafts the email content + 2-3 subject line options
- Owner picks a subject line (or suggests their own)
- Agent creates an A/B test campaign in Mailchimp
- Agent sends a test email to the owner
- Owner approves → agent schedules the send at optimal time
The owner never writes HTML, never logs into Mailchimp, never touches a template editor. They just describe what they want and approve the draft.
When to Use
- "Send a summer special to all partners"
- "We haven't emailed the list in 3 months — draft a re-engagement campaign"
- "Send a seasonal reminder to all contacts in our service area"
- "Create a campaign about our new website estimator tool"
- "Send a holiday thank you to all customers"
Prerequisites
mailchimp-integrationskill installed + API key wired- MAILCHIMP_AUDIENCE_ID set in environment
- Owner available in Telegram to approve drafts
The Flow
Step 1: Owner Describes the Campaign
Owner sends a message in Telegram:
"Send a summer special to all partners — mention our partner pricing and that we do free estimates."
Agent extracts:
- Audience segment: "partners" (or "all contacts" if not specified)
- Topic: summer special
- Key points to include: partner pricing, free estimates
- Tone: matches the business (confident, professional, not salesy)
Step 2: Agent Drafts Content + Subject Lines
Agent generates:
- 2-3 subject line options (short, punchy, under 50 chars for mobile)
- Preview text (the snippet recipients see next to subject)
- Email body in HTML, matching the business brand voice
- Plain text version (for accessibility + spam filters)
Example output to owner in Telegram:
📧 Campaign Draft — Summer Partner Special
Subject line options:
A) "Summer Listings? Don't Let Odors Kill the Sale"
B) "Free Estimates for Your Summer Listings"
C) "Partner Special: Summer Service Discount"
Preview text: "[BUSINESS_NAME] — professional service for your
listings. Free estimates, partner pricing."
Body: [shows first few lines or summary]
Which subject line do you prefer? (A, B, or C — or type your own)
Step 3: Owner Picks Subject Line
Owner replies: "A" or "B" or "C" or types their own:
"Make it 'Protect Your Summer Listings from Odors'"
Agent updates the draft with the chosen subject line.
Step 4: Agent Creates Campaign in Mailchimp
Regular (single variant) Campaign
source ~/.hermes/.env
# Create campaign
CAMPAIGN=$(curl -s -X POST "https://$MAILCHIMP_SERVER_PREFIX.api.mailchimp.com/3.0/campaigns" \
--user "anystring:$MAILCHIMP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "regular",
"recipients": {
"list_id": "'"$MAILCHIMP_AUDIENCE_ID"'",
"segment_opts": {
"saved_segment_id": SEGMENT_ID
}
},
"settings": {
"subject_line": "Summer Listings? Don'"'"'t Let Odors Kill the Sale",
"preview_text": "[BUSINESS_NAME] — professional service for your listings.",
"title": "Summer Partner Special - June 2026",
"from_name": "[BUSINESS_NAME]",
"reply_to": "[email protected]",
"to_name": "*|FNAME|*"
},
"tracking": {
"opens": true,
"html_clicks": true
}
}')
CAMPAIGN_ID=$(echo "$CAMPAIGN" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
A/B Test (Variate) Campaign
# Create A/B test campaign testing two subject lines
CAMPAIGN=$(curl -s -X POST "https://$MAILCHIMP_SERVER_PREFIX.api.mailchimp.com/3.0/campaigns" \
--user "anystring:$MAILCHIMP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "variate",
"recipients": {
"list_id": "'"$MAILCHIMP_AUDIENCE_ID"'"
},
"variate_settings": {
"winning_combination": "opens",
"wait_time": 6,
"test_size": 50,
"test_segments": [
{"segment_text": "Subject A"},
{"segment_text": "Subject B"}
],
"subject_lines": [
"Summer Listings? Don'"'"'t Let Odors Kill the Sale",
"Protect Your Summer Listings from Odors"
]
},
"settings": {
"title": "Summer Partner Special A/B - June 2026",
"from_name": "[BUSINESS_NAME]",
"reply_to": "[email protected]",
"to_name": "*|FNAME|*"
}
}')
Step 5: Set Campaign Content
curl -s -X PUT "https://$MAILCHIMP_SERVER_PREFIX.api.mailchimp.com/3.0/campaigns/$CAMPAIGN_ID/content" \
--user "anystring:$MAILCHIMP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<html><body>...campaign HTML...</body></html>",
"plain_text": " plain text version..."
}'
Step 6: Send Test to Owner
curl -s -X POST "https://$MAILCHIMP_SERVER_PREFIX.api.mailchimp.com/3.0/campaigns/$CAMPAIGN_ID/actions/test" \
--user "anystring:$MAILCHIMP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"test_emails": ["[email protected]"],
"send_type": "html"
}'
Agent tells owner: "Test email sent — check your inbox. Reply 'send' to send to the full list, or tell me what to change."
Step 7: Owner Approves → Send or Schedule
Send immediately:
curl -s -X POST "https://$MAILCHIMP_SERVER_PREFIX.api.mailchimp.com/3.0/campaigns/$CAMPAIGN_ID/actions/send" \
--user "anystring:$MAILCHIMP_API_KEY"
Schedule for optimal time:
# Schedule for Tuesday 10am ET (best open rate for B2B per industry data)
curl -s -X PATCH "https://$MAILCHIMP_SERVER_PREFIX.api.mailchimp.com/3.0/campaigns/$CAMPAIGN_ID" \
--user "anystring:$MAILCHIMP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"schedule": {
"schedule_time": "2026-07-07T14:00:00+00:00"
}
}'
Email Content Guidelines
Brand Voice
- Confident, not salesy — "This works. Here's why." not "BUY NOW!!!"
- Professional but warm — like a trusted local business, not a corporation
- Short paragraphs — 2-3 sentences max, lots of white space
- One clear CTA — "Get a Free Estimate" or "Call [PHONE]"
- Mobile-first — 60%+ of recipients read on phones
Email Structure Template
<html>
<body style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px;">
<!-- Header with logo -->
<img src="LOGO_URL" alt="[BUSINESS_NAME]" style="max-width: 200px; margin-bottom: 20px;">
<!-- Headline -->
<h1 style="color: #0C71C3; font-size: 24px;">HEADLINE HERE</h1>
<!-- Body copy -->
<p style="font-size: 16px; line-height: 1.6; color: #1A1A1A;">
BODY COPY HERE — 2-3 short paragraphs
</p>
<!-- CTA button -->
<a href="CTA_URL" style="display: inline-block; background: #0C71C3; color: white;
padding: 12px 30px; text-decoration: none; border-radius: 5px; font-size: 16px;
margin: 20px 0;">Get Your Free Estimate</a>
<!-- Footer -->
<hr style="border: none; border-top: 1px solid #ddd; margin: 30px 0;">
<p style="font-size: 12px; color: #888;">
[BUSINESS_NAME] | [SERVICE_DESCRIPTION] | [PHONE]<br>
Serving [SERVICE_AREA]<br>
<a href="*|UNSUB|*">Unsubscribe</a> | <a href="*|UPDATE_PROFILE|*">Update Preferences</a>
</p>
</body>
</html>
Subject Line Best Practices
- Under 50 characters (mobile cuts off longer)
- Create curiosity or urgency without being clickbait
- Personalization with |FNAME| works but don't overuse
- Test questions vs statements vs benefits
- Examples that work:
- "Summer Listings? Don't Let Odors Kill the Sale"
- "|FNAME|, Free Estimates for Your Spring Listings"
- "Seasonal Prep: Is Your Property Protected?"
- "The Guarantee Real Estate Agents Trust"
A/B Testing Strategy
What to Test (in priority order)
- Subject lines — biggest impact on open rates
- Send time — Tuesday/Wednesday 10am-12pm ET typically wins for B2B
- From name — "[OWNER_NAME] @ [BUSINESS_NAME]" vs "[BUSINESS_NAME]" vs a campaign name
- Preview text — the snippet next to subject in inbox
- CTA — "Get Free Estimate" vs "See Pricing" vs "Call Now"
Mailchimp A/B Test Setup
- Test size: 50% (send to 50% of list, 25% each variant, winner goes to remaining 50%)
- Winning condition: opens (for subject line tests), clicks (for content tests)
- Wait time: 6 hours (enough for a meaningful pattern, not so long it delays)
- Don't over-test — 2 variants is plenty for a small business list
Campaign Timing Recommendations
| Day | Time (ET) | Why |
|---|---|---|
| Tuesday | 10:00am | Best overall open rate for B2B |
| Wednesday | 10:00am | Second best, avoids Monday noise |
| Thursday | 2:00pm | Good for consumer-focused campaigns |
| Avoid | Monday/Friday | Buried in weekend cleanup or pre-weekend rush |
| Avoid | Weekends | B2B recipients don't check |
Segmentation Strategy
Before Sending, Agent Checks Available Segments
# List existing segments
curl -s --user "anystring:$MAILCHIMP_API_KEY" \
"https://$MAILCHIMP_SERVER_PREFIX.api.mailchimp.com/3.0/lists/$MAILCHIMP_AUDIENCE_ID/segments"
If No Segments Exist, Agent Creates Them
Useful default segments for small businesses:
- Active subscribers — opened an email in the last 90 days
- Partners/Referrers — tagged "partner" (if tags exist)
- By region — merge field REGION = specific region
- Engaged — clicked a link in the last 60 days
- Cold — no opens in 180 days (re-engagement target)
Campaign Report (Post-Send)
After a campaign sends (wait 48 hours), agent can pull the report:
curl -s --user "anystring:$MAILCHIMP_API_KEY" \
"https://$MAILCHIMP_SERVER_PREFIX.api.mailchimp.com/3.0/reports/$CAMPAIGN_ID" | python3 -m json.tool
Agent summarizes for owner in Telegram:
📊 Campaign Report — "Summer Partner Special"
Sent to: 1,500 contacts
Opens: 542 (30%) — above industry avg (21%)
Clicks: 28 (1.5%)
Unsubscribes: 3
Best segment: Standard Region (42% open rate)
Agent Integration Patterns
Pattern 1: Seasonal Campaign
Owner: "Send a seasonal campaign to all contacts" Agent: Drafts content about seasonal prep + prevention → subject lines → owner picks → test send → owner approves → scheduled for Tuesday 10am
Pattern 2: Partner Re-engagement
Agent detects (via CRM) that 12 partners haven't sent a lead in 6 months. Agent: Drafts a "We miss you" campaign targeted to cold partner segment → owner approves → send → track who re-engages → update CRM
Pattern 3: Post-Job Review Request
Job completes. Agent: Drafts a campaign asking the customer for a Google review with a direct link → owner approves → send to that one customer (not a bulk send)
Pattern 4: Content from CRM Data
Agent: "You booked 8 jobs from Standard Region partners this quarter — want me to draft a 'Standard Region Partner Thank You' campaign?" Owner: "Yes" → agent drafts.
Common Pitfalls
- Don't send without a test. Always send a test to the owner first. One wrong link or typo to 1,800 people can't be undone.
- Don't forget the unsubscribe footer. CAN-SPAM requires it. Mailchimp
adds it automatically with
*|UNSUB|*merge tag. - Don't use too many images. Many email clients block images by default. Text should carry the message; images are enhancement.
- Don't send on Friday afternoon. Opens tank. Schedule for Tuesday-Wednesday.
- Don't A/B test everything at once. Test one variable per campaign. Subject lines first. Then timing. Then content.
- Merge tags need exact match.
*|FNAME|*works only if the merge field tag is exactly FNAME. Check merge fields before using. - From name consistency. Don't change from "[BUSINESS_NAME]" to "[OWNER_NAME]" across campaigns — it hurts recognition. Pick one and stick to it.
Verification Checklist
- Can create a regular campaign via API
- Can create a variate (A/B test) campaign via API
- Can set campaign content (HTML + plain text)
- Can send a test email to owner
- Can send or schedule a campaign
- Can pull campaign report (opens, clicks, unsubscribes)
- Can create segments by tag/region/engagement
- Owner approval workflow tested end-to-end
One-Shot Recipes
"Quick campaign: seasonal reminder"
# Owner says: "Send a seasonal prevention tip to all contacts for summer"
# Agent drafts 3 short tips + CTA → creates campaign → test → owner approves → send
"Re-engagement: cold contacts"
# Agent identifies contacts with no opens in 180 days
# Creates segment "Cold - 180 days"
# Drafts "We miss you" campaign with special offer
# Owner approves → send → track re-engagement → update CRM
"Monthly newsletter from CRM data"
# Agent pulls: new leads, jobs booked, revenue this month
# Drafts "[BUSINESS_NAME] Monthly" newsletter with stats + customer spotlight
# Owner approves → send → track engagement
# Schedule as monthly cron job
| 1 | |
| 2 | name marketing-campaign-builder |
| 3 | description "Draft and run Mailchimp email campaigns with AI-generated content, subject line A/B testing, and optimal send timing. Agent drafts the email + subject variants, owner approves in Telegram, agent creates the campaign in Mailchimp. Turns a dormant contact list into an active marketing channel." |
| 4 | version "1.0.0" |
| 5 | author Hermes Agent |
| 6 | license MIT |
| 7 | metadata |
| 8 | hermes |
| 9 | tags [mailchimp, marketing, ab-testing, campaigns, email, small-business] |
| 10 | related_skills [mailchimp-integration, crm-lite, lead-to-payment] |
| 11 | |
| 12 | |
| 13 | # Marketing Campaign Builder |
| 14 | |
| 15 | ## Overview |
| 16 | Most small businesses have a Mailchimp list they never use. They sent a few |
| 17 | campaigns years ago, got busy, and stopped. This skill fixes that by making |
| 18 | campaign creation **fast and owner-gated**: |
| 19 | |
| 20 | Owner texts a campaign idea in Telegram |
| 21 | Agent drafts the email content + 2-3 subject line options |
| 22 | Owner picks a subject line (or suggests their own) |
| 23 | Agent creates an A/B test campaign in Mailchimp |
| 24 | Agent sends a test email to the owner |
| 25 | Owner approves → agent schedules the send at optimal time |
| 26 | |
| 27 | **The owner never writes HTML, never logs into Mailchimp, never touches a |
| 28 | template editor.** They just describe what they want and approve the draft. |
| 29 | |
| 30 | ## When to Use |
| 31 | "Send a summer special to all partners" |
| 32 | "We haven't emailed the list in 3 months — draft a re-engagement campaign" |
| 33 | "Send a seasonal reminder to all contacts in our service area" |
| 34 | "Create a campaign about our new website estimator tool" |
| 35 | "Send a holiday thank you to all customers" |
| 36 | |
| 37 | ## Prerequisites |
| 38 | `mailchimp-integration` skill installed + API key wired |
| 39 | MAILCHIMP_AUDIENCE_ID set in environment |
| 40 | Owner available in Telegram to approve drafts |
| 41 | |
| 42 | ## The Flow |
| 43 | |
| 44 | ### Step 1: Owner Describes the Campaign |
| 45 | Owner sends a message in Telegram: |
| 46 | > "Send a summer special to all partners — mention our partner pricing |
| 47 | > and that we do free estimates." |
| 48 | |
| 49 | Agent extracts: |
| 50 | **Audience segment:** "partners" (or "all contacts" if not specified) |
| 51 | **Topic:** summer special |
| 52 | **Key points to include:** partner pricing, free estimates |
| 53 | **Tone:** matches the business (confident, professional, not salesy) |
| 54 | |
| 55 | ### Step 2: Agent Drafts Content + Subject Lines |
| 56 | Agent generates: |
| 57 | **2-3 subject line options** (short, punchy, under 50 chars for mobile) |
| 58 | **Preview text** (the snippet recipients see next to subject) |
| 59 | **Email body** in HTML, matching the business brand voice |
| 60 | **Plain text version** (for accessibility + spam filters) |
| 61 | |
| 62 | Example output to owner in Telegram: |
| 63 | |
| 64 | 📧 Campaign Draft — Summer Partner Special |
| 65 | |
| 66 | Subject line options: |
| 67 | A) "Summer Listings? Don't Let Odors Kill the Sale" |
| 68 | B) "Free Estimates for Your Summer Listings" |
| 69 | C) "Partner Special: Summer Service Discount" |
| 70 | |
| 71 | Preview text: "[BUSINESS_NAME] — professional service for your |
| 72 | listings. Free estimates, partner pricing." |
| 73 | |
| 74 | Body: [shows first few lines or summary] |
| 75 | |
| 76 | Which subject line do you prefer? (A, B, or C — or type your own) |
| 77 | |
| 78 | |
| 79 | ### Step 3: Owner Picks Subject Line |
| 80 | Owner replies: "A" or "B" or "C" or types their own: |
| 81 | > "Make it 'Protect Your Summer Listings from Odors'" |
| 82 | |
| 83 | Agent updates the draft with the chosen subject line. |
| 84 | |
| 85 | ### Step 4: Agent Creates Campaign in Mailchimp |
| 86 | |
| 87 | #### Regular (single variant) Campaign |
| 88 | |
| 89 | source ~/.hermes/.env |
| 90 | |
| 91 | # Create campaign |
| 92 | CAMPAIGN=$(curl -s -X POST "https://$MAILCHIMP_SERVER_PREFIX.api.mailchimp.com/3.0/campaigns" \ |
| 93 | --user "anystring:$MAILCHIMP_API_KEY" \ |
| 94 | -H "Content-Type: application/json" \ |
| 95 | -d '{ |
| 96 | "type": "regular", |
| 97 | "recipients": { |
| 98 | "list_id": "'"$MAILCHIMP_AUDIENCE_ID"'", |
| 99 | "segment_opts": { |
| 100 | "saved_segment_id": SEGMENT_ID |
| 101 | } |
| 102 | }, |
| 103 | "settings": { |
| 104 | "subject_line": "Summer Listings? Don'"'"'t Let Odors Kill the Sale", |
| 105 | "preview_text": "[BUSINESS_NAME] — professional service for your listings.", |
| 106 | "title": "Summer Partner Special - June 2026", |
| 107 | "from_name": "[BUSINESS_NAME]", |
| 108 | "reply_to": "[email protected]", |
| 109 | "to_name": "*|FNAME|*" |
| 110 | }, |
| 111 | "tracking": { |
| 112 | "opens": true, |
| 113 | "html_clicks": true |
| 114 | } |
| 115 | }') |
| 116 | |
| 117 | CAMPAIGN_ID=$(echo "$CAMPAIGN" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])") |
| 118 | |
| 119 | |
| 120 | #### A/B Test (Variate) Campaign |
| 121 | |
| 122 | # Create A/B test campaign testing two subject lines |
| 123 | CAMPAIGN=$(curl -s -X POST "https://$MAILCHIMP_SERVER_PREFIX.api.mailchimp.com/3.0/campaigns" \ |
| 124 | --user "anystring:$MAILCHIMP_API_KEY" \ |
| 125 | -H "Content-Type: application/json" \ |
| 126 | -d '{ |
| 127 | "type": "variate", |
| 128 | "recipients": { |
| 129 | "list_id": "'"$MAILCHIMP_AUDIENCE_ID"'" |
| 130 | }, |
| 131 | "variate_settings": { |
| 132 | "winning_combination": "opens", |
| 133 | "wait_time": 6, |
| 134 | "test_size": 50, |
| 135 | "test_segments": [ |
| 136 | {"segment_text": "Subject A"}, |
| 137 | {"segment_text": "Subject B"} |
| 138 | ], |
| 139 | "subject_lines": [ |
| 140 | "Summer Listings? Don'"'"'t Let Odors Kill the Sale", |
| 141 | "Protect Your Summer Listings from Odors" |
| 142 | ] |
| 143 | }, |
| 144 | "settings": { |
| 145 | "title": "Summer Partner Special A/B - June 2026", |
| 146 | "from_name": "[BUSINESS_NAME]", |
| 147 | "reply_to": "[email protected]", |
| 148 | "to_name": "*|FNAME|*" |
| 149 | } |
| 150 | }') |
| 151 | |
| 152 | |
| 153 | ### Step 5: Set Campaign Content |
| 154 | |
| 155 | curl -s -X PUT "https://$MAILCHIMP_SERVER_PREFIX.api.mailchimp.com/3.0/campaigns/$CAMPAIGN_ID/content" \ |
| 156 | --user "anystring:$MAILCHIMP_API_KEY" \ |
| 157 | -H "Content-Type: application/json" \ |
| 158 | -d '{ |
| 159 | "html": "<html><body>...campaign HTML...</body></html>", |
| 160 | "plain_text": " plain text version..." |
| 161 | }' |
| 162 | |
| 163 | |
| 164 | ### Step 6: Send Test to Owner |
| 165 | |
| 166 | curl -s -X POST "https://$MAILCHIMP_SERVER_PREFIX.api.mailchimp.com/3.0/campaigns/$CAMPAIGN_ID/actions/test" \ |
| 167 | --user "anystring:$MAILCHIMP_API_KEY" \ |
| 168 | -H "Content-Type: application/json" \ |
| 169 | -d '{ |
| 170 | "test_emails": ["[email protected]"], |
| 171 | "send_type": "html" |
| 172 | }' |
| 173 | |
| 174 | |
| 175 | Agent tells owner: "Test email sent — check your inbox. Reply 'send' to send |
| 176 | to the full list, or tell me what to change." |
| 177 | |
| 178 | ### Step 7: Owner Approves → Send or Schedule |
| 179 | |
| 180 | **Send immediately:** |
| 181 | |
| 182 | curl -s -X POST "https://$MAILCHIMP_SERVER_PREFIX.api.mailchimp.com/3.0/campaigns/$CAMPAIGN_ID/actions/send" \ |
| 183 | --user "anystring:$MAILCHIMP_API_KEY" |
| 184 | |
| 185 | |
| 186 | **Schedule for optimal time:** |
| 187 | |
| 188 | # Schedule for Tuesday 10am ET (best open rate for B2B per industry data) |
| 189 | curl -s -X PATCH "https://$MAILCHIMP_SERVER_PREFIX.api.mailchimp.com/3.0/campaigns/$CAMPAIGN_ID" \ |
| 190 | --user "anystring:$MAILCHIMP_API_KEY" \ |
| 191 | -H "Content-Type: application/json" \ |
| 192 | -d '{ |
| 193 | "schedule": { |
| 194 | "schedule_time": "2026-07-07T14:00:00+00:00" |
| 195 | } |
| 196 | }' |
| 197 | |
| 198 | |
| 199 | ## Email Content Guidelines |
| 200 | |
| 201 | ### Brand Voice |
| 202 | **Confident, not salesy** — "This works. Here's why." not "BUY NOW!!!" |
| 203 | **Professional but warm** — like a trusted local business, not a corporation |
| 204 | **Short paragraphs** — 2-3 sentences max, lots of white space |
| 205 | **One clear CTA** — "Get a Free Estimate" or "Call [PHONE]" |
| 206 | **Mobile-first** — 60%+ of recipients read on phones |
| 207 | |
| 208 | ### Email Structure Template |
| 209 | |
| 210 | <html> |
| 211 | <body style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px;"> |
| 212 | |
| 213 | <!-- Header with logo --> |
| 214 | <img src="LOGO_URL" alt="[BUSINESS_NAME]" style="max-width: 200px; margin-bottom: 20px;"> |
| 215 | |
| 216 | <!-- Headline --> |
| 217 | <h1 style="color: #0C71C3; font-size: 24px;">HEADLINE HERE</h1> |
| 218 | |
| 219 | <!-- Body copy --> |
| 220 | <p style="font-size: 16px; line-height: 1.6; color: #1A1A1A;"> |
| 221 | BODY COPY HERE — 2-3 short paragraphs |
| 222 | </p> |
| 223 | |
| 224 | <!-- CTA button --> |
| 225 | <a href="CTA_URL" style="display: inline-block; background: #0C71C3; color: white; |
| 226 | padding: 12px 30px; text-decoration: none; border-radius: 5px; font-size: 16px; |
| 227 | margin: 20px 0;">Get Your Free Estimate</a> |
| 228 | |
| 229 | <!-- Footer --> |
| 230 | <hr style="border: none; border-top: 1px solid #ddd; margin: 30px 0;"> |
| 231 | <p style="font-size: 12px; color: #888;"> |
| 232 | [BUSINESS_NAME] | [SERVICE_DESCRIPTION] | [PHONE]<br> |
| 233 | Serving [SERVICE_AREA]<br> |
| 234 | <a href="*|UNSUB|*">Unsubscribe</a> | <a href="*|UPDATE_PROFILE|*">Update Preferences</a> |
| 235 | </p> |
| 236 | |
| 237 | </body> |
| 238 | </html> |
| 239 | |
| 240 | |
| 241 | ### Subject Line Best Practices |
| 242 | Under 50 characters (mobile cuts off longer) |
| 243 | Create curiosity or urgency without being clickbait |
| 244 | Personalization with *|FNAME|* works but don't overuse |
| 245 | Test questions vs statements vs benefits |
| 246 | Examples that work: |
| 247 | "Summer Listings? Don't Let Odors Kill the Sale" |
| 248 | "*|FNAME|*, Free Estimates for Your Spring Listings" |
| 249 | "Seasonal Prep: Is Your Property Protected?" |
| 250 | "The Guarantee Real Estate Agents Trust" |
| 251 | |
| 252 | ## A/B Testing Strategy |
| 253 | |
| 254 | ### What to Test (in priority order) |
| 255 | **Subject lines** — biggest impact on open rates |
| 256 | **Send time** — Tuesday/Wednesday 10am-12pm ET typically wins for B2B |
| 257 | **From name** — "[OWNER_NAME] @ [BUSINESS_NAME]" vs "[BUSINESS_NAME]" vs a campaign name |
| 258 | **Preview text** — the snippet next to subject in inbox |
| 259 | **CTA** — "Get Free Estimate" vs "See Pricing" vs "Call Now" |
| 260 | |
| 261 | ### Mailchimp A/B Test Setup |
| 262 | Test size: 50% (send to 50% of list, 25% each variant, winner goes to remaining 50%) |
| 263 | Winning condition: opens (for subject line tests), clicks (for content tests) |
| 264 | Wait time: 6 hours (enough for a meaningful pattern, not so long it delays) |
| 265 | Don't over-test — 2 variants is plenty for a small business list |
| 266 | |
| 267 | ### Campaign Timing Recommendations |
| 268 | | Day | Time (ET) | Why | |
| 269 | |-----|-----------|-----| |
| 270 | | Tuesday | 10:00am | Best overall open rate for B2B | |
| 271 | | Wednesday | 10:00am | Second best, avoids Monday noise | |
| 272 | | Thursday | 2:00pm | Good for consumer-focused campaigns | |
| 273 | | Avoid | Monday/Friday | Buried in weekend cleanup or pre-weekend rush | |
| 274 | | Avoid | Weekends | B2B recipients don't check | |
| 275 | |
| 276 | ## Segmentation Strategy |
| 277 | |
| 278 | ### Before Sending, Agent Checks Available Segments |
| 279 | |
| 280 | # List existing segments |
| 281 | curl -s --user "anystring:$MAILCHIMP_API_KEY" \ |
| 282 | "https://$MAILCHIMP_SERVER_PREFIX.api.mailchimp.com/3.0/lists/$MAILCHIMP_AUDIENCE_ID/segments" |
| 283 | |
| 284 | |
| 285 | ### If No Segments Exist, Agent Creates Them |
| 286 | Useful default segments for small businesses: |
| 287 | **Active subscribers** — opened an email in the last 90 days |
| 288 | **Partners/Referrers** — tagged "partner" (if tags exist) |
| 289 | **By region** — merge field REGION = specific region |
| 290 | **Engaged** — clicked a link in the last 60 days |
| 291 | **Cold** — no opens in 180 days (re-engagement target) |
| 292 | |
| 293 | ## Campaign Report (Post-Send) |
| 294 | After a campaign sends (wait 48 hours), agent can pull the report: |
| 295 | |
| 296 | curl -s --user "anystring:$MAILCHIMP_API_KEY" \ |
| 297 | "https://$MAILCHIMP_SERVER_PREFIX.api.mailchimp.com/3.0/reports/$CAMPAIGN_ID" | python3 -m json.tool |
| 298 | |
| 299 | |
| 300 | Agent summarizes for owner in Telegram: |
| 301 | |
| 302 | 📊 Campaign Report — "Summer Partner Special" |
| 303 | Sent to: 1,500 contacts |
| 304 | Opens: 542 (30%) — above industry avg (21%) |
| 305 | Clicks: 28 (1.5%) |
| 306 | Unsubscribes: 3 |
| 307 | Best segment: Standard Region (42% open rate) |
| 308 | |
| 309 | |
| 310 | ## Agent Integration Patterns |
| 311 | |
| 312 | ### Pattern 1: Seasonal Campaign |
| 313 | Owner: "Send a seasonal campaign to all contacts" |
| 314 | Agent: Drafts content about seasonal prep + prevention → subject lines → |
| 315 | owner picks → test send → owner approves → scheduled for Tuesday 10am |
| 316 | |
| 317 | ### Pattern 2: Partner Re-engagement |
| 318 | Agent detects (via CRM) that 12 partners haven't sent a lead in 6 months. |
| 319 | Agent: Drafts a "We miss you" campaign targeted to cold partner segment → |
| 320 | owner approves → send → track who re-engages → update CRM |
| 321 | |
| 322 | ### Pattern 3: Post-Job Review Request |
| 323 | Job completes. Agent: Drafts a campaign asking the customer for a Google review |
| 324 | with a direct link → owner approves → send to that one customer (not a bulk send) |
| 325 | |
| 326 | ### Pattern 4: Content from CRM Data |
| 327 | Agent: "You booked 8 jobs from Standard Region partners this quarter — want me to |
| 328 | draft a 'Standard Region Partner Thank You' campaign?" Owner: "Yes" → agent drafts. |
| 329 | |
| 330 | ## Common Pitfalls |
| 331 | |
| 332 | **Don't send without a test.** Always send a test to the owner first. |
| 333 | One wrong link or typo to 1,800 people can't be undone. |
| 334 | **Don't forget the unsubscribe footer.** CAN-SPAM requires it. Mailchimp |
| 335 | adds it automatically with `*|UNSUB|*` merge tag. |
| 336 | **Don't use too many images.** Many email clients block images by default. |
| 337 | Text should carry the message; images are enhancement. |
| 338 | **Don't send on Friday afternoon.** Opens tank. Schedule for Tuesday-Wednesday. |
| 339 | **Don't A/B test everything at once.** Test one variable per campaign. |
| 340 | Subject lines first. Then timing. Then content. |
| 341 | **Merge tags need exact match.** `*|FNAME|*` works only if the merge field |
| 342 | tag is exactly FNAME. Check merge fields before using. |
| 343 | **From name consistency.** Don't change from "[BUSINESS_NAME]" to "[OWNER_NAME]" |
| 344 | across campaigns — it hurts recognition. Pick one and stick to it. |
| 345 | |
| 346 | ## Verification Checklist |
| 347 | [ ] Can create a regular campaign via API |
| 348 | [ ] Can create a variate (A/B test) campaign via API |
| 349 | [ ] Can set campaign content (HTML + plain text) |
| 350 | [ ] Can send a test email to owner |
| 351 | [ ] Can send or schedule a campaign |
| 352 | [ ] Can pull campaign report (opens, clicks, unsubscribes) |
| 353 | [ ] Can create segments by tag/region/engagement |
| 354 | [ ] Owner approval workflow tested end-to-end |
| 355 | |
| 356 | ## One-Shot Recipes |
| 357 | |
| 358 | ### "Quick campaign: seasonal reminder" |
| 359 | |
| 360 | # Owner says: "Send a seasonal prevention tip to all contacts for summer" |
| 361 | # Agent drafts 3 short tips + CTA → creates campaign → test → owner approves → send |
| 362 | |
| 363 | |
| 364 | ### "Re-engagement: cold contacts" |
| 365 | |
| 366 | # Agent identifies contacts with no opens in 180 days |
| 367 | # Creates segment "Cold - 180 days" |
| 368 | # Drafts "We miss you" campaign with special offer |
| 369 | # Owner approves → send → track re-engagement → update CRM |
| 370 | |
| 371 | |
| 372 | ### "Monthly newsletter from CRM data" |
| 373 | |
| 374 | # Agent pulls: new leads, jobs booked, revenue this month |
| 375 | # Drafts "[BUSINESS_NAME] Monthly" newsletter with stats + customer spotlight |
| 376 | # Owner approves → send → track engagement |
| 377 | # Schedule as monthly cron job |
| 378 |
Discussion
Browse more free Claude skills.