@cakemail-org/cakemail-cli 1.7.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +12 -0
- package/.env.example +40 -0
- package/.env.test.example +45 -0
- package/CHANGELOG.md +1031 -0
- package/README.md +41 -37
- package/audit-formats.js +128 -0
- package/cakemail.rb +20 -0
- package/dist/client.js +1 -1
- package/dist/client.js.map +1 -1
- package/dist/commands/account.js +1 -1
- package/dist/commands/account.js.map +1 -1
- package/dist/commands/attributes.js +1 -1
- package/dist/commands/attributes.js.map +1 -1
- package/dist/commands/campaigns.js +1 -1
- package/dist/commands/campaigns.js.map +1 -1
- package/dist/commands/contacts.js +1 -1
- package/dist/commands/contacts.js.map +1 -1
- package/dist/commands/emails.js +1 -1
- package/dist/commands/emails.js.map +1 -1
- package/dist/commands/interests.js +1 -1
- package/dist/commands/interests.js.map +1 -1
- package/dist/commands/lists.js +1 -1
- package/dist/commands/lists.js.map +1 -1
- package/dist/commands/logs.js +1 -1
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/reports.js +1 -1
- package/dist/commands/reports.js.map +1 -1
- package/dist/commands/segments.js +1 -1
- package/dist/commands/segments.js.map +1 -1
- package/dist/commands/senders.js +1 -1
- package/dist/commands/senders.js.map +1 -1
- package/dist/commands/suppressed.js +1 -1
- package/dist/commands/suppressed.js.map +1 -1
- package/dist/commands/tags.js +1 -1
- package/dist/commands/tags.js.map +1 -1
- package/dist/commands/templates.js +1 -1
- package/dist/commands/templates.js.map +1 -1
- package/dist/commands/transactional-templates.js +1 -1
- package/dist/commands/transactional-templates.js.map +1 -1
- package/dist/commands/webhooks.js +1 -1
- package/dist/commands/webhooks.js.map +1 -1
- package/dist/utils/config.js +2 -2
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/errors.js +1 -1
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/progress.d.ts.map +1 -1
- package/dist/utils/progress.js +32 -4
- package/dist/utils/progress.js.map +1 -1
- package/dist/utils/spinner.d.ts +17 -0
- package/dist/utils/spinner.d.ts.map +1 -0
- package/dist/utils/spinner.js +43 -0
- package/dist/utils/spinner.js.map +1 -0
- package/docs/DOCUMENTATION-STANDARD.md +1068 -0
- package/docs/README.md +161 -0
- package/docs/developer/ARCHITECTURE.md +516 -0
- package/docs/developer/AUTH.md +204 -0
- package/docs/developer/CONTRIBUTING.md +227 -0
- package/docs/developer/DOCUMENTATION_SUMMARY.md +346 -0
- package/docs/developer/PROJECT_INDEX.md +365 -0
- package/docs/planning/API_COVERAGE.md +1045 -0
- package/docs/planning/BACKLOG.md +1159 -0
- package/docs/planning/PROFILE_SYSTEM_TASKS.md +287 -0
- package/docs/planning/UX_IMPLEMENTATION_PLAN.md +691 -0
- package/docs/planning/archive/RELEASE_CHECKLIST_v1.3.0.md +332 -0
- package/docs/planning/archive/RELEASE_v1.3.0.md +428 -0
- package/docs/planning/archive/cakemail-cli-ux-improvements.md +438 -0
- package/docs/planning/cakemail-profile-system-plan.md +1121 -0
- package/docs/testing/AI_USER_SIMULATION_DESIGN.md +1342 -0
- package/docs/testing/KENOGAMI_BIDIRECTIONAL_FLOW.md +1517 -0
- package/docs/testing/KENOGAMI_TRUTH_RECONCILIATION_SYSTEM.md +1369 -0
- package/docs/user-manual/.obsidian/app.json +1 -0
- package/docs/user-manual/.obsidian/appearance.json +1 -0
- package/docs/user-manual/.obsidian/core-plugins.json +33 -0
- package/docs/user-manual/.obsidian/workspace.json +167 -0
- package/docs/user-manual/01-getting-started/01-installation.md +214 -0
- package/docs/user-manual/01-getting-started/02-quick-start.md +432 -0
- package/docs/user-manual/01-getting-started/03-authentication.md +448 -0
- package/docs/user-manual/01-getting-started/04-configuration.md +430 -0
- package/docs/user-manual/01-getting-started/05-output-formats.md +447 -0
- package/docs/user-manual/02-core-concepts/01-accounts.md +514 -0
- package/docs/user-manual/02-core-concepts/02-profile-system.md +771 -0
- package/docs/user-manual/02-core-concepts/03-smart-defaults.md +485 -0
- package/docs/user-manual/02-core-concepts/04-authentication-methods.md +435 -0
- package/docs/user-manual/02-core-concepts/05-pagination-filtering.md +600 -0
- package/docs/user-manual/02-core-concepts/06-error-handling.md +718 -0
- package/docs/user-manual/02-core-concepts/07-api-coverage.md +483 -0
- package/docs/user-manual/03-email-operations/01-senders.md +490 -0
- package/docs/user-manual/03-email-operations/02-templates.md +444 -0
- package/docs/user-manual/03-email-operations/03-transactional-emails.md +706 -0
- package/docs/user-manual/03-email-operations/04-email-tracking.md +407 -0
- package/docs/user-manual/04-campaign-management/01-campaigns-basics.md +394 -0
- package/docs/user-manual/04-campaign-management/02-campaign-scheduling.md +630 -0
- package/docs/user-manual/04-campaign-management/03-campaign-testing.md +997 -0
- package/docs/user-manual/04-campaign-management/04-campaign-lifecycle.md +709 -0
- package/docs/user-manual/04-campaign-management/05-campaign-links.md +934 -0
- package/docs/user-manual/05-contact-management/01-lists.md +836 -0
- package/docs/user-manual/05-contact-management/02-contacts.md +1035 -0
- package/docs/user-manual/05-contact-management/03-custom-attributes.md +788 -0
- package/docs/user-manual/05-contact-management/04-segments.md +1028 -0
- package/docs/user-manual/05-contact-management/05-contact-import-export.md +1031 -0
- package/docs/user-manual/06-analytics-reporting/01-campaign-analytics.md +867 -0
- package/docs/user-manual/06-analytics-reporting/02-account-reports.md +227 -0
- package/docs/user-manual/07-integrations/01-webhooks-integration.md +259 -0
- package/docs/user-manual/07-integrations/02-automation.md +326 -0
- package/docs/user-manual/08-advanced-usage/01-scripting-patterns.md +672 -0
- package/docs/user-manual/08-advanced-usage/02-bulk-operations.md +932 -0
- package/docs/user-manual/08-advanced-usage/03-ci-cd-integration.md +892 -0
- package/docs/user-manual/08-advanced-usage/04-performance-optimization.md +766 -0
- package/docs/user-manual/09-command-reference/01-config.md +776 -0
- package/docs/user-manual/09-command-reference/02-account.md +652 -0
- package/docs/user-manual/09-command-reference/03-lists.md +958 -0
- package/docs/user-manual/09-command-reference/04-contacts.md +1408 -0
- package/docs/user-manual/09-command-reference/05-attributes.md +617 -0
- package/docs/user-manual/09-command-reference/06-segments.md +894 -0
- package/docs/user-manual/09-command-reference/07-senders.md +803 -0
- package/docs/user-manual/09-command-reference/08-templates.md +818 -0
- package/docs/user-manual/09-command-reference/09-campaigns.md +1250 -0
- package/docs/user-manual/09-command-reference/10-emails.md +807 -0
- package/docs/user-manual/09-command-reference/11-reports.md +1135 -0
- package/docs/user-manual/09-command-reference/12-webhooks.md +773 -0
- package/docs/user-manual/09-command-reference/13-suppressed.md +797 -0
- package/docs/user-manual/09-command-reference/14-interests.md +630 -0
- package/docs/user-manual/09-command-reference/15-tags.md +584 -0
- package/docs/user-manual/09-command-reference/16-logs.md +656 -0
- package/docs/user-manual/09-command-reference/17-transactional-templates.md +850 -0
- package/docs/user-manual/10-troubleshooting/01-common-errors.md +457 -0
- package/docs/user-manual/10-troubleshooting/02-authentication-issues.md +558 -0
- package/docs/user-manual/10-troubleshooting/03-connection-problems.md +634 -0
- package/docs/user-manual/10-troubleshooting/04-debugging.md +725 -0
- package/docs/user-manual/11-appendix/04-faq.md +484 -0
- package/docs/user-manual/11-appendix/05-glossary.md +250 -0
- package/docs/user-manual/README.md +0 -0
- package/package.json +13 -61
- package/src/cli.ts +125 -0
- package/src/client.ts +16 -0
- package/src/commands/account.ts +267 -0
- package/src/commands/accounts.ts +78 -0
- package/src/commands/actions.ts +249 -0
- package/src/commands/attributes.ts +139 -0
- package/src/commands/campaign-blueprints.ts +106 -0
- package/src/commands/campaigns.ts +469 -0
- package/src/commands/config.ts +77 -0
- package/src/commands/contacts.ts +612 -0
- package/src/commands/custom-attributes.ts +127 -0
- package/src/commands/dkims.ts +117 -0
- package/src/commands/domains.ts +82 -0
- package/src/commands/email-apis.ts +569 -0
- package/src/commands/emails.ts +197 -0
- package/src/commands/forms.ts +283 -0
- package/src/commands/interests.ts +155 -0
- package/src/commands/links.ts +38 -0
- package/src/commands/lists.ts +406 -0
- package/src/commands/logos.ts +71 -0
- package/src/commands/logs.ts +386 -0
- package/src/commands/reports.ts +306 -0
- package/src/commands/segments.ts +158 -0
- package/src/commands/senders.ts +204 -0
- package/src/commands/sub-accounts.ts +271 -0
- package/src/commands/suppressed-emails.ts +234 -0
- package/src/commands/suppressed.ts +198 -0
- package/src/commands/system-emails.ts +85 -0
- package/src/commands/tags.ts +146 -0
- package/src/commands/tasks.ts +116 -0
- package/src/commands/templates.ts +189 -0
- package/src/commands/tokens.ts +83 -0
- package/src/commands/transactional-emails.ts +374 -0
- package/src/commands/transactional-templates.ts +385 -0
- package/src/commands/users.ts +506 -0
- package/src/commands/webhooks.ts +172 -0
- package/src/commands/workflow-blueprints.ts +123 -0
- package/src/commands/workflows.ts +265 -0
- package/src/types/profile.ts +93 -0
- package/src/utils/auth.ts +272 -0
- package/src/utils/config-file.ts +96 -0
- package/src/utils/config.ts +134 -0
- package/src/utils/confirm.ts +32 -0
- package/src/utils/defaults.ts +99 -0
- package/src/utils/errors.ts +116 -0
- package/src/utils/interactive.ts +91 -0
- package/src/utils/list-defaults.ts +74 -0
- package/src/utils/output.ts +190 -0
- package/src/utils/progress.ts +320 -0
- package/src/utils/spinner.ts +22 -0
- package/tests/IMPLEMENTATION_STATUS.md +258 -0
- package/tests/PTY_SETUP.md +118 -0
- package/tests/PTY_TESTING_GUIDE.md +507 -0
- package/tests/README.md +244 -0
- package/tests/fixtures/api-responses/campaigns.json +34 -0
- package/tests/fixtures/test-config.json +13 -0
- package/tests/helpers/cli-runner.ts +128 -0
- package/tests/helpers/mock-server.ts +301 -0
- package/tests/helpers/pty-runner.ts +181 -0
- package/tests/integration/campaigns-real-api.test.ts +196 -0
- package/tests/integration/setup-integration.ts +50 -0
- package/tests/pty/campaigns.test.ts +241 -0
- package/tests/setup.ts +34 -0
- package/tsconfig.json +15 -0
- package/vitest.config.ts +28 -0
|
@@ -0,0 +1,836 @@
|
|
|
1
|
+
# Managing Contact Lists
|
|
2
|
+
|
|
3
|
+
Master contact list management for organizing and segmenting your email subscribers.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Contact lists allow you to:
|
|
8
|
+
- Organize subscribers by audience type
|
|
9
|
+
- Separate marketing campaigns
|
|
10
|
+
- Manage different product lines or brands
|
|
11
|
+
- Maintain compliance with consent requirements
|
|
12
|
+
- Control who receives which campaigns
|
|
13
|
+
- Track list-specific metrics
|
|
14
|
+
|
|
15
|
+
Lists are the foundation of contact management in Cakemail - every contact must belong to at least one list.
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
### Create Your First List
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
$ cakemail lists create -n "Newsletter Subscribers" -l "en"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Output:**
|
|
26
|
+
```
|
|
27
|
+
✓ List created successfully
|
|
28
|
+
|
|
29
|
+
ID: 123
|
|
30
|
+
Name: Newsletter Subscribers
|
|
31
|
+
Language: en
|
|
32
|
+
Status: active
|
|
33
|
+
Contacts: 0
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### View All Lists
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
$ cakemail lists list
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Output:**
|
|
43
|
+
```
|
|
44
|
+
┌─────┬────────────────────────┬──────────┬───────────┬─────────────────────┐
|
|
45
|
+
│ ID │ Name │ Language │ Contacts │ Created │
|
|
46
|
+
├─────┼────────────────────────┼──────────┼───────────┼─────────────────────┤
|
|
47
|
+
│ 123 │ Newsletter Subscribers │ en │ 1,247 │ 2024-01-15 10:30:00 │
|
|
48
|
+
│ 124 │ Product Updates │ en │ 856 │ 2024-02-01 14:20:00 │
|
|
49
|
+
│ 125 │ VIP Customers │ en │ 342 │ 2024-03-10 09:00:00 │
|
|
50
|
+
└─────┴────────────────────────┴──────────┴───────────┴─────────────────────┘
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## List Management Basics
|
|
54
|
+
|
|
55
|
+
### Create a List
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
$ cakemail lists create -n "Monthly Newsletter" -l "en"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**With optional description:**
|
|
62
|
+
```bash
|
|
63
|
+
$ cakemail lists create \
|
|
64
|
+
-n "Product Announcements" \
|
|
65
|
+
-l "en" \
|
|
66
|
+
-d "Subscribers interested in product updates"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**French language list:**
|
|
70
|
+
```bash
|
|
71
|
+
$ cakemail lists create -n "Infolettre" -l "fr"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### View List Details
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
$ cakemail lists get 123
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Output:**
|
|
81
|
+
```
|
|
82
|
+
{
|
|
83
|
+
"id": 123,
|
|
84
|
+
"name": "Newsletter Subscribers",
|
|
85
|
+
"language": "en",
|
|
86
|
+
"description": "Monthly newsletter subscribers",
|
|
87
|
+
"status": "active",
|
|
88
|
+
"contacts_count": 1247,
|
|
89
|
+
"active_contacts": 1189,
|
|
90
|
+
"unsubscribed": 45,
|
|
91
|
+
"bounced": 13,
|
|
92
|
+
"created_at": "2024-01-15T10:30:00Z",
|
|
93
|
+
"updated_at": "2024-03-15T14:22:00Z"
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Update List
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Update name
|
|
101
|
+
$ cakemail lists update 123 -n "Weekly Newsletter"
|
|
102
|
+
|
|
103
|
+
# Update description
|
|
104
|
+
$ cakemail lists update 123 -d "Weekly updates for subscribers"
|
|
105
|
+
|
|
106
|
+
# Update both
|
|
107
|
+
$ cakemail lists update 123 \
|
|
108
|
+
-n "Newsletter - Weekly Edition" \
|
|
109
|
+
-d "Our weekly newsletter with industry insights"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Delete List
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
$ cakemail lists delete 123
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Output:**
|
|
119
|
+
```
|
|
120
|
+
⚠ Delete list 123?
|
|
121
|
+
|
|
122
|
+
The following will happen:
|
|
123
|
+
• List and all contacts will be deleted
|
|
124
|
+
• This action cannot be undone
|
|
125
|
+
• Associated campaigns remain but will show "List Deleted"
|
|
126
|
+
|
|
127
|
+
Type 'yes' to confirm: yes
|
|
128
|
+
|
|
129
|
+
✓ List 123 deleted
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Force delete (skip confirmation):**
|
|
133
|
+
```bash
|
|
134
|
+
$ cakemail lists delete 123 --force
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## List Organization Strategies
|
|
138
|
+
|
|
139
|
+
### Strategy 1: By Audience Type
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# Create lists for different audiences
|
|
143
|
+
$ cakemail lists create -n "B2B Subscribers" -l "en"
|
|
144
|
+
$ cakemail lists create -n "B2C Customers" -l "en"
|
|
145
|
+
$ cakemail lists create -n "Partners & Affiliates" -l "en"
|
|
146
|
+
$ cakemail lists create -n "Internal Team" -l "en"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Use cases:**
|
|
150
|
+
- Different content for each audience
|
|
151
|
+
- Separate sender addresses
|
|
152
|
+
- Varied sending frequency
|
|
153
|
+
- Audience-specific compliance needs
|
|
154
|
+
|
|
155
|
+
### Strategy 2: By Product/Brand
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Multi-product company
|
|
159
|
+
$ cakemail lists create -n "Product A Users" -l "en"
|
|
160
|
+
$ cakemail lists create -n "Product B Users" -l "en"
|
|
161
|
+
$ cakemail lists create -n "Product C Users" -l "en"
|
|
162
|
+
|
|
163
|
+
# Multi-brand
|
|
164
|
+
$ cakemail lists create -n "Brand X Subscribers" -l "en"
|
|
165
|
+
$ cakemail lists create -n "Brand Y Subscribers" -l "en"
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**Use cases:**
|
|
169
|
+
- Separate branding per product
|
|
170
|
+
- Product-specific campaigns
|
|
171
|
+
- Cross-sell opportunities
|
|
172
|
+
- Brand-specific metrics
|
|
173
|
+
|
|
174
|
+
### Strategy 3: By Engagement Level
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
# Segment by engagement
|
|
178
|
+
$ cakemail lists create -n "Highly Engaged" -l "en"
|
|
179
|
+
$ cakemail lists create -n "Moderately Engaged" -l "en"
|
|
180
|
+
$ cakemail lists create -n "At Risk - Low Engagement" -l "en"
|
|
181
|
+
$ cakemail lists create -n "Re-engagement Candidates" -l "en"
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Use cases:**
|
|
185
|
+
- Engagement-based sending frequency
|
|
186
|
+
- Re-engagement campaigns
|
|
187
|
+
- VIP/loyalty programs
|
|
188
|
+
- List health maintenance
|
|
189
|
+
|
|
190
|
+
### Strategy 4: By Content Type
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
# Content-based lists
|
|
194
|
+
$ cakemail lists create -n "Blog Subscribers" -l "en"
|
|
195
|
+
$ cakemail lists create -n "Product News" -l "en"
|
|
196
|
+
$ cakemail lists create -n "Event Announcements" -l "en"
|
|
197
|
+
$ cakemail lists create -n "Sales & Promotions" -l "en"
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**Use cases:**
|
|
201
|
+
- Content preference management
|
|
202
|
+
- Targeted content delivery
|
|
203
|
+
- Reduced unsubscribes
|
|
204
|
+
- Better engagement rates
|
|
205
|
+
|
|
206
|
+
### Strategy 5: By Lifecycle Stage
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
# Customer lifecycle
|
|
210
|
+
$ cakemail lists create -n "Leads - Not Converted" -l "en"
|
|
211
|
+
$ cakemail lists create -n "Trial Users" -l "en"
|
|
212
|
+
$ cakemail lists create -n "New Customers (< 30 days)" -l "en"
|
|
213
|
+
$ cakemail lists create -n "Active Customers" -l "en"
|
|
214
|
+
$ cakemail lists create -n "Lapsed Customers" -l "en"
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**Use cases:**
|
|
218
|
+
- Lifecycle-specific messaging
|
|
219
|
+
- Onboarding sequences
|
|
220
|
+
- Retention campaigns
|
|
221
|
+
- Win-back campaigns
|
|
222
|
+
|
|
223
|
+
## List Workflows
|
|
224
|
+
|
|
225
|
+
### Workflow 1: New Business Setup
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
#!/bin/bash
|
|
229
|
+
# setup-lists.sh
|
|
230
|
+
|
|
231
|
+
echo "=== Setting Up Marketing Lists ==="
|
|
232
|
+
echo ""
|
|
233
|
+
|
|
234
|
+
# Main newsletter
|
|
235
|
+
NEWSLETTER=$(cakemail lists create \
|
|
236
|
+
-n "Newsletter Subscribers" \
|
|
237
|
+
-l "en" \
|
|
238
|
+
-d "Our monthly newsletter" \
|
|
239
|
+
-f json | jq -r '.id')
|
|
240
|
+
|
|
241
|
+
echo "✓ Newsletter list created: $NEWSLETTER"
|
|
242
|
+
|
|
243
|
+
# Product updates
|
|
244
|
+
PRODUCT=$(cakemail lists create \
|
|
245
|
+
-n "Product Updates" \
|
|
246
|
+
-l "en" \
|
|
247
|
+
-d "Product announcements and feature releases" \
|
|
248
|
+
-f json | jq -r '.id')
|
|
249
|
+
|
|
250
|
+
echo "✓ Product updates list created: $PRODUCT"
|
|
251
|
+
|
|
252
|
+
# Promotions
|
|
253
|
+
PROMO=$(cakemail lists create \
|
|
254
|
+
-n "Sales & Promotions" \
|
|
255
|
+
-l "en" \
|
|
256
|
+
-d "Special offers and discounts" \
|
|
257
|
+
-f json | jq -r '.id')
|
|
258
|
+
|
|
259
|
+
echo "✓ Promotions list created: $PROMO"
|
|
260
|
+
|
|
261
|
+
echo ""
|
|
262
|
+
echo "=== Setup Complete ===="
|
|
263
|
+
echo ""
|
|
264
|
+
echo "List IDs:"
|
|
265
|
+
echo " Newsletter: $NEWSLETTER"
|
|
266
|
+
echo " Product Updates: $PRODUCT"
|
|
267
|
+
echo " Promotions: $PROMO"
|
|
268
|
+
echo ""
|
|
269
|
+
echo "Next steps:"
|
|
270
|
+
echo " 1. Import contacts: cakemail contacts import $NEWSLETTER --file contacts.csv"
|
|
271
|
+
echo " 2. Create custom attributes: cakemail attributes create $NEWSLETTER -n \"preference\" -t \"text\""
|
|
272
|
+
echo " 3. Create segments: cakemail segments create $NEWSLETTER -n \"Active Users\""
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Workflow 2: Multi-Language Support
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
#!/bin/bash
|
|
279
|
+
# multilang-lists.sh
|
|
280
|
+
|
|
281
|
+
echo "=== Creating Multi-Language Lists ==="
|
|
282
|
+
echo ""
|
|
283
|
+
|
|
284
|
+
# English
|
|
285
|
+
EN=$(cakemail lists create \
|
|
286
|
+
-n "Newsletter - English" \
|
|
287
|
+
-l "en" \
|
|
288
|
+
-d "English language newsletter" \
|
|
289
|
+
-f json | jq -r '.id')
|
|
290
|
+
|
|
291
|
+
echo "✓ English list created: $EN"
|
|
292
|
+
|
|
293
|
+
# French
|
|
294
|
+
FR=$(cakemail lists create \
|
|
295
|
+
-n "Newsletter - Français" \
|
|
296
|
+
-l "fr" \
|
|
297
|
+
-d "Infolettre en français" \
|
|
298
|
+
-f json | jq -r '.id')
|
|
299
|
+
|
|
300
|
+
echo "✓ French list created: $FR"
|
|
301
|
+
|
|
302
|
+
# Spanish
|
|
303
|
+
ES=$(cakemail lists create \
|
|
304
|
+
-n "Newsletter - Español" \
|
|
305
|
+
-l "es" \
|
|
306
|
+
-d "Boletín en español" \
|
|
307
|
+
-f json | jq -r '.id')
|
|
308
|
+
|
|
309
|
+
echo "✓ Spanish list created: $ES"
|
|
310
|
+
|
|
311
|
+
echo ""
|
|
312
|
+
echo "Language-specific lists ready"
|
|
313
|
+
echo " English (en): $EN"
|
|
314
|
+
echo " French (fr): $FR"
|
|
315
|
+
echo " Spanish (es): $ES"
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Workflow 3: List Health Audit
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
#!/bin/bash
|
|
322
|
+
# list-health-audit.sh
|
|
323
|
+
|
|
324
|
+
echo "=== List Health Audit ==="
|
|
325
|
+
echo ""
|
|
326
|
+
|
|
327
|
+
# Get all lists
|
|
328
|
+
LISTS=$(cakemail lists list -f json | jq -r '.data[].id')
|
|
329
|
+
|
|
330
|
+
echo "List ID | Name | Total | Active | Unsub | Bounce | Health"
|
|
331
|
+
echo "--------|------|-------|--------|-------|--------|-------"
|
|
332
|
+
|
|
333
|
+
for LIST_ID in $LISTS; do
|
|
334
|
+
LIST=$(cakemail lists get $LIST_ID -f json)
|
|
335
|
+
|
|
336
|
+
NAME=$(echo "$LIST" | jq -r '.name' | cut -c1-15)
|
|
337
|
+
TOTAL=$(echo "$LIST" | jq -r '.contacts_count')
|
|
338
|
+
ACTIVE=$(echo "$LIST" | jq -r '.active_contacts')
|
|
339
|
+
UNSUB=$(echo "$LIST" | jq -r '.unsubscribed')
|
|
340
|
+
BOUNCE=$(echo "$LIST" | jq -r '.bounced')
|
|
341
|
+
|
|
342
|
+
# Calculate health score
|
|
343
|
+
if [ $TOTAL -gt 0 ]; then
|
|
344
|
+
HEALTH=$(echo "scale=1; $ACTIVE * 100 / $TOTAL" | bc)
|
|
345
|
+
else
|
|
346
|
+
HEALTH="N/A"
|
|
347
|
+
fi
|
|
348
|
+
|
|
349
|
+
printf "%-7s | %-15s | %5d | %6d | %5d | %6d | %s%%\n" \
|
|
350
|
+
"$LIST_ID" "$NAME" "$TOTAL" "$ACTIVE" "$UNSUB" "$BOUNCE" "$HEALTH"
|
|
351
|
+
done
|
|
352
|
+
|
|
353
|
+
echo ""
|
|
354
|
+
echo "Health Score: % of contacts that are active (not unsubscribed or bounced)"
|
|
355
|
+
echo " > 90%: Excellent"
|
|
356
|
+
echo " 80-90%: Good"
|
|
357
|
+
echo " 70-80%: Fair - Consider list cleaning"
|
|
358
|
+
echo " < 70%: Poor - Clean list immediately"
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Workflow 4: List Consolidation
|
|
362
|
+
|
|
363
|
+
```bash
|
|
364
|
+
#!/bin/bash
|
|
365
|
+
# consolidate-lists.sh
|
|
366
|
+
|
|
367
|
+
SOURCE_LIST_1=123
|
|
368
|
+
SOURCE_LIST_2=124
|
|
369
|
+
TARGET_LIST=125
|
|
370
|
+
|
|
371
|
+
echo "=== Consolidating Lists ==="
|
|
372
|
+
echo ""
|
|
373
|
+
echo "Merging lists $SOURCE_LIST_1 and $SOURCE_LIST_2 into $TARGET_LIST"
|
|
374
|
+
echo ""
|
|
375
|
+
|
|
376
|
+
# Export contacts from source lists
|
|
377
|
+
echo "Exporting from list $SOURCE_LIST_1..."
|
|
378
|
+
cakemail contacts export $SOURCE_LIST_1
|
|
379
|
+
EXPORT_1=$(cakemail contacts export-list -f json | jq -r '.data[0].id')
|
|
380
|
+
|
|
381
|
+
echo "Exporting from list $SOURCE_LIST_2..."
|
|
382
|
+
cakemail contacts export $SOURCE_LIST_2
|
|
383
|
+
EXPORT_2=$(cakemail contacts export-list -f json | jq -r '.data[0].id')
|
|
384
|
+
|
|
385
|
+
# Wait for exports
|
|
386
|
+
echo "Waiting for exports to complete..."
|
|
387
|
+
sleep 10
|
|
388
|
+
|
|
389
|
+
# Download exports
|
|
390
|
+
cakemail contacts export-download $EXPORT_1 > list1.csv
|
|
391
|
+
cakemail contacts export-download $EXPORT_2 > list2.csv
|
|
392
|
+
|
|
393
|
+
# Combine and deduplicate
|
|
394
|
+
echo "Combining and deduplicating..."
|
|
395
|
+
cat list1.csv list2.csv | sort -u -t',' -k1,1 > combined.csv
|
|
396
|
+
|
|
397
|
+
# Import to target list
|
|
398
|
+
echo "Importing to target list $TARGET_LIST..."
|
|
399
|
+
cakemail contacts import $TARGET_LIST --file combined.csv
|
|
400
|
+
|
|
401
|
+
echo ""
|
|
402
|
+
echo "✓ Lists consolidated"
|
|
403
|
+
echo ""
|
|
404
|
+
read -p "Delete source lists? (yes/no): " DELETE
|
|
405
|
+
|
|
406
|
+
if [ "$DELETE" == "yes" ]; then
|
|
407
|
+
cakemail lists delete $SOURCE_LIST_1 --force
|
|
408
|
+
cakemail lists delete $SOURCE_LIST_2 --force
|
|
409
|
+
echo "✓ Source lists deleted"
|
|
410
|
+
fi
|
|
411
|
+
|
|
412
|
+
# Cleanup
|
|
413
|
+
rm list1.csv list2.csv combined.csv
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### Workflow 5: List Cleanup
|
|
417
|
+
|
|
418
|
+
```bash
|
|
419
|
+
#!/bin/bash
|
|
420
|
+
# cleanup-list.sh
|
|
421
|
+
|
|
422
|
+
LIST_ID=$1
|
|
423
|
+
|
|
424
|
+
if [ -z "$LIST_ID" ]; then
|
|
425
|
+
echo "Usage: $0 <list-id>"
|
|
426
|
+
exit 1
|
|
427
|
+
fi
|
|
428
|
+
|
|
429
|
+
echo "=== List Cleanup: $LIST_ID ==="
|
|
430
|
+
echo ""
|
|
431
|
+
|
|
432
|
+
# Get list stats
|
|
433
|
+
LIST=$(cakemail lists get $LIST_ID -f json)
|
|
434
|
+
TOTAL=$(echo "$LIST" | jq -r '.contacts_count')
|
|
435
|
+
BOUNCED=$(echo "$LIST" | jq -r '.bounced')
|
|
436
|
+
UNSUB=$(echo "$LIST" | jq -r '.unsubscribed')
|
|
437
|
+
|
|
438
|
+
echo "Current Stats:"
|
|
439
|
+
echo " Total Contacts: $TOTAL"
|
|
440
|
+
echo " Bounced: $BOUNCED"
|
|
441
|
+
echo " Unsubscribed: $UNSUB"
|
|
442
|
+
echo ""
|
|
443
|
+
|
|
444
|
+
# Calculate to remove
|
|
445
|
+
TO_REMOVE=$((BOUNCED + UNSUB))
|
|
446
|
+
echo "Contacts to remove: $TO_REMOVE"
|
|
447
|
+
echo ""
|
|
448
|
+
|
|
449
|
+
read -p "Remove bounced and unsubscribed contacts? (yes/no): " CONFIRM
|
|
450
|
+
|
|
451
|
+
if [ "$CONFIRM" == "yes" ]; then
|
|
452
|
+
echo ""
|
|
453
|
+
echo "Removing bounced contacts..."
|
|
454
|
+
# Export active only, then re-import (effective cleanup)
|
|
455
|
+
cakemail contacts export $LIST_ID --filter "status==subscribed"
|
|
456
|
+
|
|
457
|
+
EXPORT_ID=$(cakemail contacts export-list -f json | jq -r '.data[0].id')
|
|
458
|
+
|
|
459
|
+
echo "Waiting for export..."
|
|
460
|
+
sleep 10
|
|
461
|
+
|
|
462
|
+
# Download clean list
|
|
463
|
+
cakemail contacts export-download $EXPORT_ID > clean.csv
|
|
464
|
+
|
|
465
|
+
# Create new list
|
|
466
|
+
NEW_LIST=$(cakemail lists create \
|
|
467
|
+
-n "$(echo "$LIST" | jq -r '.name') (Cleaned)" \
|
|
468
|
+
-l "$(echo "$LIST" | jq -r '.language')" \
|
|
469
|
+
-f json | jq -r '.id')
|
|
470
|
+
|
|
471
|
+
# Import clean contacts
|
|
472
|
+
echo "Importing clean contacts to new list $NEW_LIST..."
|
|
473
|
+
cakemail contacts import $NEW_LIST --file clean.csv
|
|
474
|
+
|
|
475
|
+
echo ""
|
|
476
|
+
echo "✓ Cleanup complete"
|
|
477
|
+
echo " New list: $NEW_LIST"
|
|
478
|
+
echo " Review new list before deleting old list"
|
|
479
|
+
|
|
480
|
+
rm clean.csv
|
|
481
|
+
else
|
|
482
|
+
echo "Cleanup cancelled"
|
|
483
|
+
fi
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
## List Metrics & Analysis
|
|
487
|
+
|
|
488
|
+
### View List Statistics
|
|
489
|
+
|
|
490
|
+
```bash
|
|
491
|
+
$ cakemail lists get 123 -f json | jq '{
|
|
492
|
+
name: .name,
|
|
493
|
+
total: .contacts_count,
|
|
494
|
+
active: .active_contacts,
|
|
495
|
+
unsubscribed: .unsubscribed,
|
|
496
|
+
bounced: .bounced,
|
|
497
|
+
health: (.active_contacts / .contacts_count * 100 | round)
|
|
498
|
+
}'
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
**Output:**
|
|
502
|
+
```json
|
|
503
|
+
{
|
|
504
|
+
"name": "Newsletter Subscribers",
|
|
505
|
+
"total": 1247,
|
|
506
|
+
"active": 1189,
|
|
507
|
+
"unsubscribed": 45,
|
|
508
|
+
"bounced": 13,
|
|
509
|
+
"health": 95
|
|
510
|
+
}
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
### Compare List Performance
|
|
514
|
+
|
|
515
|
+
```bash
|
|
516
|
+
#!/bin/bash
|
|
517
|
+
# compare-lists.sh
|
|
518
|
+
|
|
519
|
+
echo "=== List Comparison ==="
|
|
520
|
+
echo ""
|
|
521
|
+
|
|
522
|
+
# Get all lists
|
|
523
|
+
cakemail lists list -f json | jq -r '.data[] |
|
|
524
|
+
"List: \(.name)\n ID: \(.id)\n Contacts: \(.contacts_count)\n Active: \(.active_contacts)\n Growth: +\(.contacts_count - .active_contacts) inactive\n"'
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
### Track List Growth
|
|
528
|
+
|
|
529
|
+
```bash
|
|
530
|
+
#!/bin/bash
|
|
531
|
+
# track-growth.sh
|
|
532
|
+
|
|
533
|
+
LIST_ID=$1
|
|
534
|
+
LOG_FILE="list-growth-$LIST_ID.log"
|
|
535
|
+
|
|
536
|
+
# Get current count
|
|
537
|
+
CURRENT=$(cakemail lists get $LIST_ID -f json | jq -r '.contacts_count')
|
|
538
|
+
DATE=$(date +%Y-%m-%d)
|
|
539
|
+
|
|
540
|
+
# Log to file
|
|
541
|
+
echo "$DATE,$CURRENT" >> $LOG_FILE
|
|
542
|
+
|
|
543
|
+
# Show recent growth
|
|
544
|
+
echo "=== List Growth: $LIST_ID ==="
|
|
545
|
+
echo ""
|
|
546
|
+
echo "Date | Count | Change"
|
|
547
|
+
echo "-----------|-------|-------"
|
|
548
|
+
|
|
549
|
+
# Calculate changes
|
|
550
|
+
tail -30 $LOG_FILE | awk -F',' '
|
|
551
|
+
NR > 1 {
|
|
552
|
+
change = $2 - prev
|
|
553
|
+
printf "%s | %5d | %+6d\n", $1, $2, change
|
|
554
|
+
}
|
|
555
|
+
{prev = $2}
|
|
556
|
+
'
|
|
557
|
+
|
|
558
|
+
echo ""
|
|
559
|
+
echo "Run this script daily via cron to track growth"
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
## List Best Practices
|
|
563
|
+
|
|
564
|
+
### 1. Keep Lists Focused
|
|
565
|
+
|
|
566
|
+
```bash
|
|
567
|
+
# Good: Focused lists
|
|
568
|
+
Newsletter Subscribers # General updates
|
|
569
|
+
Product A Users # Specific product
|
|
570
|
+
VIP Customers # High-value segment
|
|
571
|
+
|
|
572
|
+
# Avoid: Catch-all lists
|
|
573
|
+
All Contacts # Too broad
|
|
574
|
+
Everyone # No segmentation
|
|
575
|
+
Main List # Unclear purpose
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
### 2. Name Lists Clearly
|
|
579
|
+
|
|
580
|
+
```bash
|
|
581
|
+
# Good naming
|
|
582
|
+
$ cakemail lists create -n "Newsletter - Weekly Tech Tips" -l "en"
|
|
583
|
+
$ cakemail lists create -n "Product Updates - Enterprise" -l "en"
|
|
584
|
+
$ cakemail lists create -n "Event Invites - NYC Region" -l "en"
|
|
585
|
+
|
|
586
|
+
# Avoid vague names
|
|
587
|
+
$ cakemail lists create -n "List 1" -l "en" # ❌
|
|
588
|
+
$ cakemail lists create -n "Emails" -l "en" # ❌
|
|
589
|
+
$ cakemail lists create -n "Test" -l "en" # ❌
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
### 3. Regular List Maintenance
|
|
593
|
+
|
|
594
|
+
```bash
|
|
595
|
+
#!/bin/bash
|
|
596
|
+
# monthly-maintenance.sh
|
|
597
|
+
|
|
598
|
+
echo "=== Monthly List Maintenance ==="
|
|
599
|
+
echo ""
|
|
600
|
+
|
|
601
|
+
# Get all lists
|
|
602
|
+
LISTS=$(cakemail lists list -f json | jq -r '.data[].id')
|
|
603
|
+
|
|
604
|
+
for LIST_ID in $LISTS; do
|
|
605
|
+
echo "Checking list $LIST_ID..."
|
|
606
|
+
|
|
607
|
+
# Get stats
|
|
608
|
+
LIST=$(cakemail lists get $LIST_ID -f json)
|
|
609
|
+
BOUNCED=$(echo "$LIST" | jq -r '.bounced')
|
|
610
|
+
|
|
611
|
+
# Alert if high bounce rate
|
|
612
|
+
if [ $BOUNCED -gt 100 ]; then
|
|
613
|
+
echo " ⚠️ High bounce count: $BOUNCED"
|
|
614
|
+
echo " Consider list cleanup"
|
|
615
|
+
fi
|
|
616
|
+
done
|
|
617
|
+
|
|
618
|
+
echo ""
|
|
619
|
+
echo "Maintenance check complete"
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
### 4. Document List Purpose
|
|
623
|
+
|
|
624
|
+
```bash
|
|
625
|
+
# Create with descriptive description
|
|
626
|
+
$ cakemail lists create \
|
|
627
|
+
-n "Q1 Webinar Attendees" \
|
|
628
|
+
-l "en" \
|
|
629
|
+
-d "Contacts who attended any Q1 2024 webinar. Used for post-event nurture campaigns and future event invites."
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
### 5. Archive Inactive Lists
|
|
633
|
+
|
|
634
|
+
```bash
|
|
635
|
+
#!/bin/bash
|
|
636
|
+
# archive-inactive-lists.sh
|
|
637
|
+
|
|
638
|
+
echo "=== Archiving Inactive Lists ==="
|
|
639
|
+
echo ""
|
|
640
|
+
|
|
641
|
+
CUTOFF_DATE=$(date -d "90 days ago" +%Y-%m-%d)
|
|
642
|
+
|
|
643
|
+
# Find lists not used recently
|
|
644
|
+
LISTS=$(cakemail lists list -f json | jq -r '.data[].id')
|
|
645
|
+
|
|
646
|
+
for LIST_ID in $LISTS; do
|
|
647
|
+
# Get latest campaign using this list
|
|
648
|
+
LATEST=$(cakemail campaigns list \
|
|
649
|
+
--filter "list_id==$LIST_ID" \
|
|
650
|
+
--sort "-delivered_at" \
|
|
651
|
+
--limit 1 \
|
|
652
|
+
-f json | jq -r '.data[0].delivered_at // "null"')
|
|
653
|
+
|
|
654
|
+
if [ "$LATEST" == "null" ] || [ "$LATEST" < "$CUTOFF_DATE" ]; then
|
|
655
|
+
NAME=$(cakemail lists get $LIST_ID -f json | jq -r '.name')
|
|
656
|
+
echo "⚠️ Inactive list: $NAME (ID: $LIST_ID)"
|
|
657
|
+
echo " Last used: ${LATEST:-Never}"
|
|
658
|
+
|
|
659
|
+
read -p " Archive this list? (yes/no): " ARCHIVE
|
|
660
|
+
|
|
661
|
+
if [ "$ARCHIVE" == "yes" ]; then
|
|
662
|
+
# Rename to indicate archived
|
|
663
|
+
cakemail lists update $LIST_ID -n "[ARCHIVED] $NAME"
|
|
664
|
+
echo " ✓ List archived"
|
|
665
|
+
fi
|
|
666
|
+
fi
|
|
667
|
+
done
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
## List Compliance
|
|
671
|
+
|
|
672
|
+
### GDPR Considerations
|
|
673
|
+
|
|
674
|
+
```bash
|
|
675
|
+
# Create consent-tracking attributes
|
|
676
|
+
$ cakemail attributes create 123 -n "consent_date" -t "date"
|
|
677
|
+
$ cakemail attributes create 123 -n "consent_method" -t "text"
|
|
678
|
+
$ cakemail attributes create 123 -n "consent_ip" -t "text"
|
|
679
|
+
|
|
680
|
+
# Add contact with consent tracking
|
|
681
|
+
$ cakemail contacts add 123 \
|
|
682
|
+
-e "user@example.com" \
|
|
683
|
+
-d '{
|
|
684
|
+
"consent_date": "2024-03-15",
|
|
685
|
+
"consent_method": "website_signup",
|
|
686
|
+
"consent_ip": "192.168.1.1"
|
|
687
|
+
}'
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
### CAN-SPAM Compliance
|
|
691
|
+
|
|
692
|
+
```bash
|
|
693
|
+
# Every list must have:
|
|
694
|
+
# 1. Clear unsubscribe mechanism (automatic in Cakemail)
|
|
695
|
+
# 2. Physical address in footer
|
|
696
|
+
# 3. Honest subject lines
|
|
697
|
+
# 4. No deceptive headers
|
|
698
|
+
|
|
699
|
+
# Verify sender address configured
|
|
700
|
+
$ cakemail senders list -f json | jq '.data[] | {email, confirmed, address}'
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
### CASL Compliance (Canada)
|
|
704
|
+
|
|
705
|
+
```bash
|
|
706
|
+
# Canadian Anti-Spam Law requirements
|
|
707
|
+
$ cakemail attributes create 123 -n "casl_consent" -t "boolean"
|
|
708
|
+
$ cakemail attributes create 123 -n "casl_consent_date" -t "date"
|
|
709
|
+
$ cakemail attributes create 123 -n "relationship_type" -t "text"
|
|
710
|
+
|
|
711
|
+
# Track implied vs express consent
|
|
712
|
+
$ cakemail contacts add 123 \
|
|
713
|
+
-e "canadian@example.com" \
|
|
714
|
+
-d '{
|
|
715
|
+
"casl_consent": true,
|
|
716
|
+
"casl_consent_date": "2024-03-15",
|
|
717
|
+
"relationship_type": "express"
|
|
718
|
+
}'
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
## Troubleshooting
|
|
722
|
+
|
|
723
|
+
### Cannot Delete List
|
|
724
|
+
|
|
725
|
+
**Error:** "List has active campaigns"
|
|
726
|
+
|
|
727
|
+
**Solution:**
|
|
728
|
+
```bash
|
|
729
|
+
# Find campaigns using list
|
|
730
|
+
$ cakemail campaigns list --filter "list_id==123" -f json
|
|
731
|
+
|
|
732
|
+
# Cancel or complete campaigns
|
|
733
|
+
$ cakemail campaigns cancel 790
|
|
734
|
+
|
|
735
|
+
# Or update campaigns to use different list
|
|
736
|
+
$ cakemail campaigns update 790 --list-id 124
|
|
737
|
+
|
|
738
|
+
# Then delete list
|
|
739
|
+
$ cakemail lists delete 123 --force
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
### List Growth Stagnant
|
|
743
|
+
|
|
744
|
+
**Problem:** List not growing
|
|
745
|
+
|
|
746
|
+
**Solutions:**
|
|
747
|
+
```bash
|
|
748
|
+
# Check recent imports
|
|
749
|
+
$ cakemail contacts import-list 123
|
|
750
|
+
|
|
751
|
+
# Verify signup forms active
|
|
752
|
+
# Check website forms, landing pages
|
|
753
|
+
|
|
754
|
+
# Review unsubscribe rate
|
|
755
|
+
$ cakemail lists get 123 -f json | jq '{unsub: .unsubscribed, total: .contacts_count}'
|
|
756
|
+
|
|
757
|
+
# If high unsubscribe rate (> 2%):
|
|
758
|
+
# - Review content relevance
|
|
759
|
+
# - Check send frequency
|
|
760
|
+
# - Improve targeting
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
### High Bounce Rate
|
|
764
|
+
|
|
765
|
+
**Problem:** Many bounced contacts
|
|
766
|
+
|
|
767
|
+
**Solutions:**
|
|
768
|
+
```bash
|
|
769
|
+
# Check bounce count
|
|
770
|
+
$ cakemail lists get 123 -f json | jq '.bounced'
|
|
771
|
+
|
|
772
|
+
# If > 5% of list:
|
|
773
|
+
# 1. Verify email collection process
|
|
774
|
+
# 2. Use double opt-in
|
|
775
|
+
# 3. Clean list regularly
|
|
776
|
+
# 4. Check for spam traps
|
|
777
|
+
|
|
778
|
+
# Remove hard bounces
|
|
779
|
+
# (Use list cleanup workflow above)
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
### Duplicate Contacts Across Lists
|
|
783
|
+
|
|
784
|
+
**Problem:** Same contact in multiple lists
|
|
785
|
+
|
|
786
|
+
**Not an error** - this is intentional:
|
|
787
|
+
```bash
|
|
788
|
+
# Contacts can be in multiple lists
|
|
789
|
+
$ cakemail contacts add 123 -e "user@example.com" # Newsletter
|
|
790
|
+
$ cakemail contacts add 124 -e "user@example.com" # Product Updates
|
|
791
|
+
|
|
792
|
+
# Different lists = different campaign types
|
|
793
|
+
# Contact can unsubscribe from one but stay on others
|
|
794
|
+
```
|
|
795
|
+
|
|
796
|
+
**If duplicate is unintended:**
|
|
797
|
+
```bash
|
|
798
|
+
# Remove from one list
|
|
799
|
+
$ cakemail contacts delete 124 <contact-id> --force
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
### List Language Setting Issues
|
|
803
|
+
|
|
804
|
+
**Problem:** List created with wrong language
|
|
805
|
+
|
|
806
|
+
**Solution:**
|
|
807
|
+
```bash
|
|
808
|
+
# Cannot change list language after creation
|
|
809
|
+
# Must create new list and migrate:
|
|
810
|
+
|
|
811
|
+
# 1. Create new list with correct language
|
|
812
|
+
$ cakemail lists create -n "Newsletter - Français" -l "fr"
|
|
813
|
+
|
|
814
|
+
# 2. Export contacts from old list
|
|
815
|
+
$ cakemail contacts export 123
|
|
816
|
+
|
|
817
|
+
# 3. Import to new list
|
|
818
|
+
# (See List Consolidation workflow)
|
|
819
|
+
|
|
820
|
+
# 4. Delete old list
|
|
821
|
+
$ cakemail lists delete 123 --force
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
## Best Practices Summary
|
|
825
|
+
|
|
826
|
+
1. **Focus each list** - One clear purpose per list
|
|
827
|
+
2. **Name descriptively** - Clear, self-explanatory names
|
|
828
|
+
3. **Add descriptions** - Document list purpose and use
|
|
829
|
+
4. **Monitor health** - Track active vs inactive contacts
|
|
830
|
+
5. **Clean regularly** - Remove bounces and unsubscribes
|
|
831
|
+
6. **Track consent** - Document subscription source and date
|
|
832
|
+
7. **Segment appropriately** - Use lists for major segments, segments for minor
|
|
833
|
+
8. **Archive inactive** - Don't delete, archive old lists
|
|
834
|
+
9. **Document strategy** - Keep list strategy documentation
|
|
835
|
+
10. **Review quarterly** - Assess list performance and cleanup
|
|
836
|
+
|