@cakemail-org/cakemail-cli 1.5.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.
Files changed (234) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/.env.example +40 -0
  3. package/.env.test.example +45 -0
  4. package/CHANGELOG.md +1031 -0
  5. package/README.md +319 -15
  6. package/audit-formats.js +128 -0
  7. package/cakemail.rb +20 -0
  8. package/dist/cli.js +27 -10
  9. package/dist/cli.js.map +1 -1
  10. package/dist/client.d.ts +2 -0
  11. package/dist/client.d.ts.map +1 -1
  12. package/dist/client.js +16 -6
  13. package/dist/client.js.map +1 -1
  14. package/dist/commands/account.js +1 -1
  15. package/dist/commands/account.js.map +1 -1
  16. package/dist/commands/attributes.js +1 -1
  17. package/dist/commands/attributes.js.map +1 -1
  18. package/dist/commands/campaigns.d.ts.map +1 -1
  19. package/dist/commands/campaigns.js +103 -8
  20. package/dist/commands/campaigns.js.map +1 -1
  21. package/dist/commands/config.d.ts.map +1 -1
  22. package/dist/commands/config.js +63 -4
  23. package/dist/commands/config.js.map +1 -1
  24. package/dist/commands/contacts.d.ts.map +1 -1
  25. package/dist/commands/contacts.js +91 -12
  26. package/dist/commands/contacts.js.map +1 -1
  27. package/dist/commands/emails.js +1 -1
  28. package/dist/commands/emails.js.map +1 -1
  29. package/dist/commands/interests.d.ts +5 -0
  30. package/dist/commands/interests.d.ts.map +1 -0
  31. package/dist/commands/interests.js +172 -0
  32. package/dist/commands/interests.js.map +1 -0
  33. package/dist/commands/lists.d.ts.map +1 -1
  34. package/dist/commands/lists.js +6 -8
  35. package/dist/commands/lists.js.map +1 -1
  36. package/dist/commands/logs.d.ts +5 -0
  37. package/dist/commands/logs.d.ts.map +1 -0
  38. package/dist/commands/logs.js +237 -0
  39. package/dist/commands/logs.js.map +1 -0
  40. package/dist/commands/reports.js +1 -1
  41. package/dist/commands/reports.js.map +1 -1
  42. package/dist/commands/segments.js +1 -1
  43. package/dist/commands/segments.js.map +1 -1
  44. package/dist/commands/senders.d.ts.map +1 -1
  45. package/dist/commands/senders.js +11 -8
  46. package/dist/commands/senders.js.map +1 -1
  47. package/dist/commands/suppressed.js +1 -1
  48. package/dist/commands/suppressed.js.map +1 -1
  49. package/dist/commands/tags.d.ts +5 -0
  50. package/dist/commands/tags.d.ts.map +1 -0
  51. package/dist/commands/tags.js +124 -0
  52. package/dist/commands/tags.js.map +1 -0
  53. package/dist/commands/templates.js +1 -1
  54. package/dist/commands/templates.js.map +1 -1
  55. package/dist/commands/transactional-templates.d.ts +5 -0
  56. package/dist/commands/transactional-templates.d.ts.map +1 -0
  57. package/dist/commands/transactional-templates.js +354 -0
  58. package/dist/commands/transactional-templates.js.map +1 -0
  59. package/dist/commands/webhooks.js +1 -1
  60. package/dist/commands/webhooks.js.map +1 -1
  61. package/dist/utils/auth.d.ts +8 -1
  62. package/dist/utils/auth.d.ts.map +1 -1
  63. package/dist/utils/auth.js +39 -11
  64. package/dist/utils/auth.js.map +1 -1
  65. package/dist/utils/config-file.d.ts +7 -0
  66. package/dist/utils/config-file.d.ts.map +1 -1
  67. package/dist/utils/config-file.js +15 -0
  68. package/dist/utils/config-file.js.map +1 -1
  69. package/dist/utils/config.d.ts +2 -0
  70. package/dist/utils/config.d.ts.map +1 -1
  71. package/dist/utils/config.js +12 -4
  72. package/dist/utils/config.js.map +1 -1
  73. package/dist/utils/errors.js +1 -1
  74. package/dist/utils/errors.js.map +1 -1
  75. package/dist/utils/list-defaults.d.ts +33 -0
  76. package/dist/utils/list-defaults.d.ts.map +1 -0
  77. package/dist/utils/list-defaults.js +52 -0
  78. package/dist/utils/list-defaults.js.map +1 -0
  79. package/dist/utils/output.d.ts.map +1 -1
  80. package/dist/utils/output.js +36 -13
  81. package/dist/utils/output.js.map +1 -1
  82. package/dist/utils/progress.d.ts.map +1 -1
  83. package/dist/utils/progress.js +32 -4
  84. package/dist/utils/progress.js.map +1 -1
  85. package/dist/utils/spinner.d.ts +17 -0
  86. package/dist/utils/spinner.d.ts.map +1 -0
  87. package/dist/utils/spinner.js +43 -0
  88. package/dist/utils/spinner.js.map +1 -0
  89. package/docs/DOCUMENTATION-STANDARD.md +1068 -0
  90. package/docs/README.md +161 -0
  91. package/docs/developer/ARCHITECTURE.md +516 -0
  92. package/docs/developer/AUTH.md +204 -0
  93. package/docs/developer/CONTRIBUTING.md +227 -0
  94. package/docs/developer/DOCUMENTATION_SUMMARY.md +346 -0
  95. package/docs/developer/PROJECT_INDEX.md +365 -0
  96. package/docs/planning/API_COVERAGE.md +1045 -0
  97. package/docs/planning/BACKLOG.md +1159 -0
  98. package/docs/planning/PROFILE_SYSTEM_TASKS.md +287 -0
  99. package/docs/planning/UX_IMPLEMENTATION_PLAN.md +691 -0
  100. package/docs/planning/archive/RELEASE_CHECKLIST_v1.3.0.md +332 -0
  101. package/docs/planning/archive/RELEASE_v1.3.0.md +428 -0
  102. package/docs/planning/archive/cakemail-cli-ux-improvements.md +438 -0
  103. package/docs/planning/cakemail-profile-system-plan.md +1121 -0
  104. package/docs/testing/AI_USER_SIMULATION_DESIGN.md +1342 -0
  105. package/docs/testing/KENOGAMI_BIDIRECTIONAL_FLOW.md +1517 -0
  106. package/docs/testing/KENOGAMI_TRUTH_RECONCILIATION_SYSTEM.md +1369 -0
  107. package/docs/user-manual/.obsidian/app.json +1 -0
  108. package/docs/user-manual/.obsidian/appearance.json +1 -0
  109. package/docs/user-manual/.obsidian/core-plugins.json +33 -0
  110. package/docs/user-manual/.obsidian/workspace.json +167 -0
  111. package/docs/user-manual/01-getting-started/01-installation.md +214 -0
  112. package/docs/user-manual/01-getting-started/02-quick-start.md +432 -0
  113. package/docs/user-manual/01-getting-started/03-authentication.md +448 -0
  114. package/docs/user-manual/01-getting-started/04-configuration.md +430 -0
  115. package/docs/user-manual/01-getting-started/05-output-formats.md +447 -0
  116. package/docs/user-manual/02-core-concepts/01-accounts.md +514 -0
  117. package/docs/user-manual/02-core-concepts/02-profile-system.md +771 -0
  118. package/docs/user-manual/02-core-concepts/03-smart-defaults.md +485 -0
  119. package/docs/user-manual/02-core-concepts/04-authentication-methods.md +435 -0
  120. package/docs/user-manual/02-core-concepts/05-pagination-filtering.md +600 -0
  121. package/docs/user-manual/02-core-concepts/06-error-handling.md +718 -0
  122. package/docs/user-manual/02-core-concepts/07-api-coverage.md +483 -0
  123. package/docs/user-manual/03-email-operations/01-senders.md +490 -0
  124. package/docs/user-manual/03-email-operations/02-templates.md +444 -0
  125. package/docs/user-manual/03-email-operations/03-transactional-emails.md +706 -0
  126. package/docs/user-manual/03-email-operations/04-email-tracking.md +407 -0
  127. package/docs/user-manual/04-campaign-management/01-campaigns-basics.md +394 -0
  128. package/docs/user-manual/04-campaign-management/02-campaign-scheduling.md +630 -0
  129. package/docs/user-manual/04-campaign-management/03-campaign-testing.md +997 -0
  130. package/docs/user-manual/04-campaign-management/04-campaign-lifecycle.md +709 -0
  131. package/docs/user-manual/04-campaign-management/05-campaign-links.md +934 -0
  132. package/docs/user-manual/05-contact-management/01-lists.md +836 -0
  133. package/docs/user-manual/05-contact-management/02-contacts.md +1035 -0
  134. package/docs/user-manual/05-contact-management/03-custom-attributes.md +788 -0
  135. package/docs/user-manual/05-contact-management/04-segments.md +1028 -0
  136. package/docs/user-manual/05-contact-management/05-contact-import-export.md +1031 -0
  137. package/docs/user-manual/06-analytics-reporting/01-campaign-analytics.md +867 -0
  138. package/docs/user-manual/06-analytics-reporting/02-account-reports.md +227 -0
  139. package/docs/user-manual/07-integrations/01-webhooks-integration.md +259 -0
  140. package/docs/user-manual/07-integrations/02-automation.md +326 -0
  141. package/docs/user-manual/08-advanced-usage/01-scripting-patterns.md +672 -0
  142. package/docs/user-manual/08-advanced-usage/02-bulk-operations.md +932 -0
  143. package/docs/user-manual/08-advanced-usage/03-ci-cd-integration.md +892 -0
  144. package/docs/user-manual/08-advanced-usage/04-performance-optimization.md +766 -0
  145. package/docs/user-manual/09-command-reference/01-config.md +776 -0
  146. package/docs/user-manual/09-command-reference/02-account.md +652 -0
  147. package/docs/user-manual/09-command-reference/03-lists.md +958 -0
  148. package/docs/user-manual/09-command-reference/04-contacts.md +1408 -0
  149. package/docs/user-manual/09-command-reference/05-attributes.md +617 -0
  150. package/docs/user-manual/09-command-reference/06-segments.md +894 -0
  151. package/docs/user-manual/09-command-reference/07-senders.md +803 -0
  152. package/docs/user-manual/09-command-reference/08-templates.md +818 -0
  153. package/docs/user-manual/09-command-reference/09-campaigns.md +1250 -0
  154. package/docs/user-manual/09-command-reference/10-emails.md +807 -0
  155. package/docs/user-manual/09-command-reference/11-reports.md +1135 -0
  156. package/docs/user-manual/09-command-reference/12-webhooks.md +773 -0
  157. package/docs/user-manual/09-command-reference/13-suppressed.md +797 -0
  158. package/docs/user-manual/09-command-reference/14-interests.md +630 -0
  159. package/docs/user-manual/09-command-reference/15-tags.md +584 -0
  160. package/docs/user-manual/09-command-reference/16-logs.md +656 -0
  161. package/docs/user-manual/09-command-reference/17-transactional-templates.md +850 -0
  162. package/docs/user-manual/10-troubleshooting/01-common-errors.md +457 -0
  163. package/docs/user-manual/10-troubleshooting/02-authentication-issues.md +558 -0
  164. package/docs/user-manual/10-troubleshooting/03-connection-problems.md +634 -0
  165. package/docs/user-manual/10-troubleshooting/04-debugging.md +725 -0
  166. package/docs/user-manual/11-appendix/04-faq.md +484 -0
  167. package/docs/user-manual/11-appendix/05-glossary.md +250 -0
  168. package/docs/user-manual/README.md +0 -0
  169. package/package.json +13 -47
  170. package/src/cli.ts +125 -0
  171. package/src/client.ts +16 -0
  172. package/src/commands/account.ts +267 -0
  173. package/src/commands/accounts.ts +78 -0
  174. package/src/commands/actions.ts +249 -0
  175. package/src/commands/attributes.ts +139 -0
  176. package/src/commands/campaign-blueprints.ts +106 -0
  177. package/src/commands/campaigns.ts +469 -0
  178. package/src/commands/config.ts +77 -0
  179. package/src/commands/contacts.ts +612 -0
  180. package/src/commands/custom-attributes.ts +127 -0
  181. package/src/commands/dkims.ts +117 -0
  182. package/src/commands/domains.ts +82 -0
  183. package/src/commands/email-apis.ts +569 -0
  184. package/src/commands/emails.ts +197 -0
  185. package/src/commands/forms.ts +283 -0
  186. package/src/commands/interests.ts +155 -0
  187. package/src/commands/links.ts +38 -0
  188. package/src/commands/lists.ts +406 -0
  189. package/src/commands/logos.ts +71 -0
  190. package/src/commands/logs.ts +386 -0
  191. package/src/commands/reports.ts +306 -0
  192. package/src/commands/segments.ts +158 -0
  193. package/src/commands/senders.ts +204 -0
  194. package/src/commands/sub-accounts.ts +271 -0
  195. package/src/commands/suppressed-emails.ts +234 -0
  196. package/src/commands/suppressed.ts +198 -0
  197. package/src/commands/system-emails.ts +85 -0
  198. package/src/commands/tags.ts +146 -0
  199. package/src/commands/tasks.ts +116 -0
  200. package/src/commands/templates.ts +189 -0
  201. package/src/commands/tokens.ts +83 -0
  202. package/src/commands/transactional-emails.ts +374 -0
  203. package/src/commands/transactional-templates.ts +385 -0
  204. package/src/commands/users.ts +506 -0
  205. package/src/commands/webhooks.ts +172 -0
  206. package/src/commands/workflow-blueprints.ts +123 -0
  207. package/src/commands/workflows.ts +265 -0
  208. package/src/types/profile.ts +93 -0
  209. package/src/utils/auth.ts +272 -0
  210. package/src/utils/config-file.ts +96 -0
  211. package/src/utils/config.ts +134 -0
  212. package/src/utils/confirm.ts +32 -0
  213. package/src/utils/defaults.ts +99 -0
  214. package/src/utils/errors.ts +116 -0
  215. package/src/utils/interactive.ts +91 -0
  216. package/src/utils/list-defaults.ts +74 -0
  217. package/src/utils/output.ts +190 -0
  218. package/src/utils/progress.ts +320 -0
  219. package/src/utils/spinner.ts +22 -0
  220. package/tests/IMPLEMENTATION_STATUS.md +258 -0
  221. package/tests/PTY_SETUP.md +118 -0
  222. package/tests/PTY_TESTING_GUIDE.md +507 -0
  223. package/tests/README.md +244 -0
  224. package/tests/fixtures/api-responses/campaigns.json +34 -0
  225. package/tests/fixtures/test-config.json +13 -0
  226. package/tests/helpers/cli-runner.ts +128 -0
  227. package/tests/helpers/mock-server.ts +301 -0
  228. package/tests/helpers/pty-runner.ts +181 -0
  229. package/tests/integration/campaigns-real-api.test.ts +196 -0
  230. package/tests/integration/setup-integration.ts +50 -0
  231. package/tests/pty/campaigns.test.ts +241 -0
  232. package/tests/setup.ts +34 -0
  233. package/tsconfig.json +15 -0
  234. package/vitest.config.ts +28 -0
@@ -0,0 +1,788 @@
1
+ # Custom Attributes
2
+
3
+ Extend contact records with custom fields to store business-specific data beyond standard email and name fields.
4
+
5
+ ## Overview
6
+
7
+ Custom attributes allow you to:
8
+ - Store unlimited additional contact data
9
+ - Track customer preferences and behavior
10
+ - Enable advanced segmentation
11
+ - Personalize campaigns with custom data
12
+ - Integrate with your business systems
13
+ - Build comprehensive customer profiles
14
+
15
+ Custom attributes are the key to making Cakemail work for your specific business needs.
16
+
17
+ ## Quick Start
18
+
19
+ ### Create Your First Attribute
20
+
21
+ ```bash
22
+ $ cakemail attributes create 123 -n "plan_type" -t "text"
23
+ ```
24
+
25
+ **Output:**
26
+ ```
27
+ ✓ Custom attribute created: plan_type
28
+
29
+ Name: plan_type
30
+ Type: text
31
+ List: 123
32
+ ```
33
+
34
+ ### Add Contact with Custom Data
35
+
36
+ ```bash
37
+ $ cakemail contacts add 123 \
38
+ -e "customer@example.com" \
39
+ -f "Jane" \
40
+ -l "Doe" \
41
+ -d '{"plan_type":"premium"}'
42
+ ```
43
+
44
+ ### View Attributes
45
+
46
+ ```bash
47
+ $ cakemail attributes list 123
48
+ ```
49
+
50
+ **Output:**
51
+ ```
52
+ ┌──────────────────┬──────────┬─────────────────────┐
53
+ │ Name │ Type │ Created │
54
+ ├──────────────────┼──────────┼─────────────────────┤
55
+ │ plan_type │ text │ 2024-01-15 10:30:00 │
56
+ │ signup_date │ date │ 2024-02-01 14:20:00 │
57
+ │ lifetime_value │ number │ 2024-02-15 09:00:00 │
58
+ │ is_vip │ boolean │ 2024-03-01 11:45:00 │
59
+ └──────────────────┴──────────┴─────────────────────┘
60
+ ```
61
+
62
+ ## Attribute Types
63
+
64
+ ### Text Attributes
65
+
66
+ Store string values like names, categories, or IDs.
67
+
68
+ **Create:**
69
+ ```bash
70
+ $ cakemail attributes create 123 -n "plan_type" -t "text"
71
+ $ cakemail attributes create 123 -n "customer_id" -t "text"
72
+ $ cakemail attributes create 123 -n "company_name" -t "text"
73
+ ```
74
+
75
+ **Use cases:**
76
+ - Plan tiers (free, basic, premium, enterprise)
77
+ - Customer segments (new, active, lapsed)
78
+ - Industry categories (technology, retail, finance)
79
+ - Product preferences (red, blue, green)
80
+ - External system IDs
81
+
82
+ **Example values:**
83
+ ```json
84
+ {
85
+ "plan_type": "premium",
86
+ "customer_id": "CUST-12345",
87
+ "company_name": "Acme Corporation",
88
+ "industry": "Technology",
89
+ "preferred_color": "blue"
90
+ }
91
+ ```
92
+
93
+ ### Number Attributes
94
+
95
+ Store numeric values like counts, amounts, or scores.
96
+
97
+ **Create:**
98
+ ```bash
99
+ $ cakemail attributes create 123 -n "purchase_count" -t "number"
100
+ $ cakemail attributes create 123 -n "lifetime_value" -t "number"
101
+ $ cakemail attributes create 123 -n "engagement_score" -t "number"
102
+ ```
103
+
104
+ **Use cases:**
105
+ - Purchase counts
106
+ - Lifetime value (dollars)
107
+ - Engagement scores
108
+ - Account age (days)
109
+ - Product quantities
110
+
111
+ **Example values:**
112
+ ```json
113
+ {
114
+ "purchase_count": 15,
115
+ "lifetime_value": 2499.99,
116
+ "engagement_score": 87,
117
+ "account_age_days": 365,
118
+ "cart_items": 3
119
+ }
120
+ ```
121
+
122
+ ### Date Attributes
123
+
124
+ Store dates in ISO format (YYYY-MM-DD).
125
+
126
+ **Create:**
127
+ ```bash
128
+ $ cakemail attributes create 123 -n "signup_date" -t "date"
129
+ $ cakemail attributes create 123 -n "last_purchase" -t "date"
130
+ $ cakemail attributes create 123 -n "trial_ends" -t "date"
131
+ ```
132
+
133
+ **Use cases:**
134
+ - Signup/registration dates
135
+ - Last purchase dates
136
+ - Trial expiration dates
137
+ - Birthday/anniversary dates
138
+ - Renewal dates
139
+
140
+ **Example values:**
141
+ ```json
142
+ {
143
+ "signup_date": "2024-01-15",
144
+ "last_purchase": "2024-03-10",
145
+ "trial_ends": "2024-04-15",
146
+ "birthday": "1990-06-15",
147
+ "renewal_date": "2024-12-31"
148
+ }
149
+ ```
150
+
151
+ ### Boolean Attributes
152
+
153
+ Store true/false flags.
154
+
155
+ **Create:**
156
+ ```bash
157
+ $ cakemail attributes create 123 -n "is_vip" -t "boolean"
158
+ $ cakemail attributes create 123 -n "opted_in_sms" -t "boolean"
159
+ $ cakemail attributes create 123 -n "email_verified" -t "boolean"
160
+ ```
161
+
162
+ **Use cases:**
163
+ - VIP status
164
+ - Feature flags
165
+ - Opt-in preferences
166
+ - Verification status
167
+ - Active/inactive indicators
168
+
169
+ **Example values:**
170
+ ```json
171
+ {
172
+ "is_vip": true,
173
+ "opted_in_sms": false,
174
+ "email_verified": true,
175
+ "marketing_consent": true,
176
+ "account_locked": false
177
+ }
178
+ ```
179
+
180
+ ## Attribute Naming
181
+
182
+ ### Best Naming Practices
183
+
184
+ **Good names:**
185
+ ```bash
186
+ $ cakemail attributes create 123 -n "plan_type" -t "text" # Clear purpose
187
+ $ cakemail attributes create 123 -n "last_login_date" -t "date" # Descriptive
188
+ $ cakemail attributes create 123 -n "is_premium" -t "boolean" # Clear boolean
189
+ $ cakemail attributes create 123 -n "total_spent" -t "number" # Clear metric
190
+ ```
191
+
192
+ **Avoid:**
193
+ ```bash
194
+ $ cakemail attributes create 123 -n "pt" -t "text" # Too short
195
+ $ cakemail attributes create 123 -n "Plan Type" -t "text" # Spaces
196
+ $ cakemail attributes create 123 -n "PLAN" -t "text" # All caps
197
+ $ cakemail attributes create 123 -n "thePlanTypeForCustomer" -t "text" # Too verbose
198
+ ```
199
+
200
+ ### Naming Conventions
201
+
202
+ **Use snake_case:**
203
+ ```bash
204
+ plan_type # ✓
205
+ lifetime_value # ✓
206
+ last_purchase_date # ✓
207
+ is_vip # ✓
208
+ ```
209
+
210
+ **Not camelCase or spaces:**
211
+ ```bash
212
+ planType # ✗
213
+ lifetimeValue # ✗
214
+ "last purchase" # ✗
215
+ "Is VIP" # ✗
216
+ ```
217
+
218
+ **Boolean prefix:**
219
+ ```bash
220
+ is_vip # ✓ Clear it's boolean
221
+ has_subscription # ✓ Clear it's boolean
222
+ email_verified # ✓ Clear it's boolean
223
+
224
+ vip # ✗ Not obvious it's boolean
225
+ subscription # ✗ Not obvious it's boolean
226
+ ```
227
+
228
+ ## Attribute Workflows
229
+
230
+ ### Workflow 1: Customer Data Setup
231
+
232
+ ```bash
233
+ #!/bin/bash
234
+ # setup-customer-attributes.sh
235
+
236
+ LIST_ID=123
237
+
238
+ echo "=== Setting Up Customer Attributes ==="
239
+ echo ""
240
+
241
+ # Basic info
242
+ echo "Creating basic customer attributes..."
243
+ cakemail attributes create $LIST_ID -n "customer_id" -t "text"
244
+ cakemail attributes create $LIST_ID -n "company_name" -t "text"
245
+ cakemail attributes create $LIST_ID -n "industry" -t "text"
246
+ cakemail attributes create $LIST_ID -n "company_size" -t "text"
247
+
248
+ # Subscription
249
+ echo "Creating subscription attributes..."
250
+ cakemail attributes create $LIST_ID -n "plan_type" -t "text"
251
+ cakemail attributes create $LIST_ID -n "signup_date" -t "date"
252
+ cakemail attributes create $LIST_ID -n "trial_ends" -t "date"
253
+ cakemail attributes create $LIST_ID -n "is_paying" -t "boolean"
254
+
255
+ # Engagement
256
+ echo "Creating engagement attributes..."
257
+ cakemail attributes create $LIST_ID -n "last_login_date" -t "date"
258
+ cakemail attributes create $LIST_ID -n "login_count" -t "number"
259
+ cakemail attributes create $LIST_ID -n "feature_usage_score" -t "number"
260
+
261
+ # Financial
262
+ echo "Creating financial attributes..."
263
+ cakemail attributes create $LIST_ID -n "lifetime_value" -t "number"
264
+ cakemail attributes create $LIST_ID -n "purchase_count" -t "number"
265
+ cakemail attributes create $LIST_ID -n "last_purchase_date" -t "date"
266
+ cakemail attributes create $LIST_ID -n "average_order_value" -t "number"
267
+
268
+ echo ""
269
+ echo "✓ Attribute setup complete"
270
+ echo ""
271
+
272
+ # Show all attributes
273
+ cakemail attributes list $LIST_ID
274
+ ```
275
+
276
+ ### Workflow 2: E-commerce Attributes
277
+
278
+ ```bash
279
+ #!/bin/bash
280
+ # setup-ecommerce-attributes.sh
281
+
282
+ LIST_ID=123
283
+
284
+ echo "=== E-commerce Attribute Setup ==="
285
+ echo ""
286
+
287
+ # Purchase behavior
288
+ cakemail attributes create $LIST_ID -n "total_orders" -t "number"
289
+ cakemail attributes create $LIST_ID -n "total_spent" -t "number"
290
+ cakemail attributes create $LIST_ID -n "average_order_value" -t "number"
291
+ cakemail attributes create $LIST_ID -n "last_order_date" -t "date"
292
+ cakemail attributes create $LIST_ID -n "first_order_date" -t "date"
293
+
294
+ # Preferences
295
+ cakemail attributes create $LIST_ID -n "favorite_category" -t "text"
296
+ cakemail attributes create $LIST_ID -n "preferred_brand" -t "text"
297
+ cakemail attributes create $LIST_ID -n "size_preference" -t "text"
298
+
299
+ # Loyalty
300
+ cakemail attributes create $LIST_ID -n "loyalty_points" -t "number"
301
+ cakemail attributes create $LIST_ID -n "loyalty_tier" -t "text"
302
+ cakemail attributes create $LIST_ID -n "is_vip" -t "boolean"
303
+
304
+ # Cart behavior
305
+ cakemail attributes create $LIST_ID -n "cart_abandoned_date" -t "date"
306
+ cakemail attributes create $LIST_ID -n "cart_value" -t "number"
307
+ cakemail attributes create $LIST_ID -n "has_active_cart" -t "boolean"
308
+
309
+ echo "✓ E-commerce attributes created"
310
+ ```
311
+
312
+ ### Workflow 3: SaaS Attributes
313
+
314
+ ```bash
315
+ #!/bin/bash
316
+ # setup-saas-attributes.sh
317
+
318
+ LIST_ID=123
319
+
320
+ echo "=== SaaS Attribute Setup ==="
321
+ echo ""
322
+
323
+ # Account
324
+ cakemail attributes create $LIST_ID -n "account_id" -t "text"
325
+ cakemail attributes create $LIST_ID -n "plan_name" -t "text"
326
+ cakemail attributes create $LIST_ID -n "mrr" -t "number"
327
+ cakemail attributes create $LIST_ID -n "arr" -t "number"
328
+
329
+ # Subscription lifecycle
330
+ cakemail attributes create $LIST_ID -n "trial_start_date" -t "date"
331
+ cakemail attributes create $LIST_ID -n "trial_end_date" -t "date"
332
+ cakemail attributes create $LIST_ID -n "subscription_start" -t "date"
333
+ cakemail attributes create $LIST_ID -n "next_billing_date" -t "date"
334
+ cakemail attributes create $LIST_ID -n "is_trial" -t "boolean"
335
+ cakemail attributes create $LIST_ID -n "is_paying" -t "boolean"
336
+
337
+ # Usage
338
+ cakemail attributes create $LIST_ID -n "last_login" -t "date"
339
+ cakemail attributes create $LIST_ID -n "login_count_30d" -t "number"
340
+ cakemail attributes create $LIST_ID -n "feature_adoption_score" -t "number"
341
+ cakemail attributes create $LIST_ID -n "active_users" -t "number"
342
+
343
+ # Health
344
+ cakemail attributes create $LIST_ID -n "health_score" -t "number"
345
+ cakemail attributes create $LIST_ID -n "churn_risk" -t "text"
346
+ cakemail attributes create $LIST_ID -n "support_tickets_30d" -t "number"
347
+
348
+ echo "✓ SaaS attributes created"
349
+ ```
350
+
351
+ ### Workflow 4: Attribute Audit
352
+
353
+ ```bash
354
+ #!/bin/bash
355
+ # audit-attributes.sh
356
+
357
+ LIST_ID=123
358
+
359
+ echo "=== Attribute Audit ==="
360
+ echo ""
361
+
362
+ # Get all attributes
363
+ ATTRIBUTES=$(cakemail attributes list $LIST_ID -f json | jq -r '.data[] | "\(.name):\(.type)"')
364
+
365
+ echo "Attribute | Type | Usage (%)"
366
+ echo "----------|------|----------"
367
+
368
+ # Check usage for each attribute
369
+ for ATTR in $ATTRIBUTES; do
370
+ NAME=$(echo "$ATTR" | cut -d: -f1)
371
+ TYPE=$(echo "$ATTR" | cut -d: -f2)
372
+
373
+ # Get contacts with this attribute set
374
+ TOTAL=$(cakemail contacts list $LIST_ID -f json | jq '.count')
375
+
376
+ # Note: This is simplified - actual implementation would need to check each contact
377
+ # For demonstration purposes
378
+ USAGE="~%"
379
+
380
+ printf "%-20s | %-8s | %s\n" "$NAME" "$TYPE" "$USAGE"
381
+ done
382
+
383
+ echo ""
384
+ echo "Review attributes with low usage for potential removal"
385
+ ```
386
+
387
+ ### Workflow 5: Attribute Migration
388
+
389
+ ```bash
390
+ #!/bin/bash
391
+ # migrate-attributes.sh
392
+
393
+ SOURCE_LIST=123
394
+ TARGET_LIST=124
395
+
396
+ echo "=== Migrating Attributes ==="
397
+ echo "From: List $SOURCE_LIST"
398
+ echo "To: List $TARGET_LIST"
399
+ echo ""
400
+
401
+ # Get source attributes
402
+ ATTRIBUTES=$(cakemail attributes list $SOURCE_LIST -f json)
403
+
404
+ echo "$ATTRIBUTES" | jq -r '.data[] | "\(.name):\(.type)"' | while IFS=: read NAME TYPE; do
405
+ echo "Creating: $NAME ($TYPE)"
406
+
407
+ # Create in target list
408
+ cakemail attributes create $TARGET_LIST -n "$NAME" -t "$TYPE" 2>/dev/null
409
+
410
+ if [ $? -eq 0 ]; then
411
+ echo " ✓ Created"
412
+ else
413
+ echo " ⚠️ Already exists or error"
414
+ fi
415
+ done
416
+
417
+ echo ""
418
+ echo "✓ Attribute migration complete"
419
+ ```
420
+
421
+ ## Using Attributes with Contacts
422
+
423
+ ### Add Contact with Attributes
424
+
425
+ ```bash
426
+ $ cakemail contacts add 123 \
427
+ -e "customer@example.com" \
428
+ -f "Jane" \
429
+ -l "Doe" \
430
+ -d '{
431
+ "plan_type": "premium",
432
+ "signup_date": "2024-03-15",
433
+ "is_vip": true,
434
+ "lifetime_value": 599.99,
435
+ "purchase_count": 8
436
+ }'
437
+ ```
438
+
439
+ ### Update Contact Attributes
440
+
441
+ ```bash
442
+ # Update single attribute
443
+ $ cakemail contacts update 123 501 -d '{"plan_type":"enterprise"}'
444
+
445
+ # Update multiple attributes
446
+ $ cakemail contacts update 123 501 -d '{
447
+ "plan_type": "enterprise",
448
+ "is_vip": true,
449
+ "lifetime_value": 1299.99
450
+ }'
451
+ ```
452
+
453
+ ### Query by Attributes
454
+
455
+ ```bash
456
+ # Find premium users
457
+ $ cakemail contacts list 123 --filter "custom_attributes.plan_type==premium"
458
+
459
+ # Find VIP customers
460
+ $ cakemail contacts list 123 --filter "custom_attributes.is_vip==true"
461
+
462
+ # Find high-value customers
463
+ $ cakemail contacts list 123 --filter "custom_attributes.lifetime_value>=1000"
464
+
465
+ # Find recent signups
466
+ $ cakemail contacts list 123 --filter "custom_attributes.signup_date>=2024-03-01"
467
+ ```
468
+
469
+ ## Segmentation with Attributes
470
+
471
+ ### Create Segments Based on Attributes
472
+
473
+ ```bash
474
+ # Premium plan segment
475
+ $ cakemail segments create 123 -n "Premium Users" -c '{
476
+ "match": "all",
477
+ "rules": [
478
+ {"field": "custom_attributes.plan_type", "operator": "equals", "value": "premium"}
479
+ ]
480
+ }'
481
+
482
+ # High-value customers
483
+ $ cakemail segments create 123 -n "High Value" -c '{
484
+ "match": "all",
485
+ "rules": [
486
+ {"field": "custom_attributes.lifetime_value", "operator": "greater_than", "value": "1000"}
487
+ ]
488
+ }'
489
+
490
+ # At-risk trial users
491
+ $ cakemail segments create 123 -n "Trial Ending Soon" -c '{
492
+ "match": "all",
493
+ "rules": [
494
+ {"field": "custom_attributes.is_trial", "operator": "equals", "value": "true"},
495
+ {"field": "custom_attributes.trial_ends", "operator": "less_than", "value": "2024-04-01"}
496
+ ]
497
+ }'
498
+
499
+ # Engaged VIPs
500
+ $ cakemail segments create 123 -n "Engaged VIPs" -c '{
501
+ "match": "all",
502
+ "rules": [
503
+ {"field": "custom_attributes.is_vip", "operator": "equals", "value": "true"},
504
+ {"field": "last_open_date", "operator": "greater_than", "value": "2024-03-01"}
505
+ ]
506
+ }'
507
+ ```
508
+
509
+ ## Campaign Personalization
510
+
511
+ ### Use Attributes in Campaigns
512
+
513
+ Campaign HTML with merge tags:
514
+
515
+ ```html
516
+ <p>Hi {{first_name}},</p>
517
+
518
+ <p>As a {{custom_attributes.plan_type}} member, you have access to:</p>
519
+
520
+ {{#if custom_attributes.is_vip}}
521
+ <p><strong>VIP Benefits:</strong></p>
522
+ <ul>
523
+ <li>Priority Support</li>
524
+ <li>Exclusive Features</li>
525
+ <li>Early Access</li>
526
+ </ul>
527
+ {{/if}}
528
+
529
+ <p>You've been with us since {{custom_attributes.signup_date}}.</p>
530
+
531
+ <p>Your lifetime savings: ${{custom_attributes.lifetime_value}}</p>
532
+
533
+ <p>Thanks for {{custom_attributes.purchase_count}} purchases!</p>
534
+ ```
535
+
536
+ ### Conditional Content
537
+
538
+ ```html
539
+ {{#if custom_attributes.plan_type == "free"}}
540
+ <div class="upgrade-prompt">
541
+ <h2>Upgrade to Premium</h2>
542
+ <p>Get more features for just $9.99/month</p>
543
+ <a href="https://example.com/upgrade">Upgrade Now</a>
544
+ </div>
545
+ {{/if}}
546
+
547
+ {{#if custom_attributes.cart_abandoned_date}}
548
+ <div class="cart-reminder">
549
+ <h2>You Left Items in Your Cart</h2>
550
+ <p>Complete your purchase and save {{custom_attributes.cart_value}}!</p>
551
+ <a href="https://example.com/cart">Return to Cart</a>
552
+ </div>
553
+ {{/if}}
554
+ ```
555
+
556
+ ## Attribute Best Practices
557
+
558
+ ### 1. Plan Schema First
559
+
560
+ ```bash
561
+ # Document your attribute schema
562
+ cat > attribute-schema.md << 'EOF'
563
+ # Customer Attributes Schema
564
+
565
+ ## Account
566
+ - customer_id (text): External CRM ID
567
+ - account_type (text): individual | business
568
+ - signup_date (date): Registration date
569
+
570
+ ## Subscription
571
+ - plan_type (text): free | basic | premium | enterprise
572
+ - is_paying (boolean): Active paid subscription
573
+ - mrr (number): Monthly recurring revenue
574
+
575
+ ## Engagement
576
+ - last_login (date): Last login date
577
+ - login_count_30d (number): Logins in last 30 days
578
+ - health_score (number): 0-100 engagement score
579
+
580
+ ## Financial
581
+ - lifetime_value (number): Total revenue
582
+ - purchase_count (number): Total orders
583
+ - average_order_value (number): AOV
584
+ EOF
585
+ ```
586
+
587
+ ### 2. Use Consistent Types
588
+
589
+ ```bash
590
+ # All dates as date type
591
+ $ cakemail attributes create 123 -n "signup_date" -t "date"
592
+ $ cakemail attributes create 123 -n "last_purchase" -t "date"
593
+ $ cakemail attributes create 123 -n "trial_ends" -t "date"
594
+
595
+ # All monetary values as number
596
+ $ cakemail attributes create 123 -n "lifetime_value" -t "number"
597
+ $ cakemail attributes create 123 -n "monthly_spend" -t "number"
598
+ $ cakemail attributes create 123 -n "cart_value" -t "number"
599
+
600
+ # All flags as boolean
601
+ $ cakemail attributes create 123 -n "is_vip" -t "boolean"
602
+ $ cakemail attributes create 123 -n "email_verified" -t "boolean"
603
+ $ cakemail attributes create 123 -n "marketing_consent" -t "boolean"
604
+ ```
605
+
606
+ ### 3. Validate Data Before Setting
607
+
608
+ ```bash
609
+ #!/bin/bash
610
+ # validate-and-set.sh
611
+
612
+ LIST_ID=123
613
+ CONTACT_ID=501
614
+ PLAN="$1"
615
+
616
+ # Validate plan type
617
+ VALID_PLANS=("free" "basic" "premium" "enterprise")
618
+
619
+ if [[ ! " ${VALID_PLANS[@]} " =~ " ${PLAN} " ]]; then
620
+ echo "❌ Invalid plan: $PLAN"
621
+ echo "Valid plans: ${VALID_PLANS[@]}"
622
+ exit 1
623
+ fi
624
+
625
+ # Set attribute
626
+ cakemail contacts update $LIST_ID $CONTACT_ID -d "{\"plan_type\":\"$PLAN\"}"
627
+ echo "✓ Plan set to: $PLAN"
628
+ ```
629
+
630
+ ### 4. Keep Attributes Synchronized
631
+
632
+ ```bash
633
+ #!/bin/bash
634
+ # sync-from-crm.sh
635
+
636
+ LIST_ID=123
637
+
638
+ echo "=== Syncing from CRM ==="
639
+ echo ""
640
+
641
+ # Fetch from your CRM (example)
642
+ CUSTOMERS=$(curl -s "https://api.yourcrm.com/customers")
643
+
644
+ echo "$CUSTOMERS" | jq -c '.[]' | while read CUSTOMER; do
645
+ EMAIL=$(echo "$CUSTOMER" | jq -r '.email')
646
+ PLAN=$(echo "$CUSTOMER" | jq -r '.plan')
647
+ LTV=$(echo "$CUSTOMER" | jq -r '.lifetime_value')
648
+ LAST_PURCHASE=$(echo "$CUSTOMER" | jq -r '.last_purchase_date')
649
+
650
+ # Find contact
651
+ CONTACTS=$(cakemail contacts list $LIST_ID --filter "email==$EMAIL" -f json)
652
+ CONTACT_ID=$(echo "$CONTACTS" | jq -r '.data[0].id')
653
+
654
+ if [ "$CONTACT_ID" != "null" ]; then
655
+ # Update attributes
656
+ cakemail contacts update $LIST_ID $CONTACT_ID -d "{
657
+ \"plan_type\": \"$PLAN\",
658
+ \"lifetime_value\": $LTV,
659
+ \"last_purchase_date\": \"$LAST_PURCHASE\"
660
+ }"
661
+ echo " Synced: $EMAIL"
662
+ fi
663
+ done
664
+
665
+ echo ""
666
+ echo "✓ CRM sync complete"
667
+ ```
668
+
669
+ ### 5. Remove Unused Attributes
670
+
671
+ ```bash
672
+ #!/bin/bash
673
+ # cleanup-unused.sh
674
+
675
+ LIST_ID=123
676
+
677
+ echo "=== Cleaning Up Unused Attributes ==="
678
+ echo ""
679
+
680
+ # List of deprecated attributes
681
+ DEPRECATED=(
682
+ "old_field"
683
+ "legacy_score"
684
+ "temp_attribute"
685
+ )
686
+
687
+ for ATTR in "${DEPRECATED[@]}"; do
688
+ echo "Removing: $ATTR"
689
+ cakemail attributes delete $LIST_ID $ATTR --force
690
+ done
691
+
692
+ echo ""
693
+ echo "✓ Cleanup complete"
694
+ ```
695
+
696
+ ## Troubleshooting
697
+
698
+ ### Attribute Not Appearing
699
+
700
+ **Problem:** Created attribute but it's not showing
701
+
702
+ **Solution:**
703
+ ```bash
704
+ # Verify attribute was created
705
+ $ cakemail attributes list 123
706
+
707
+ # Check specific attribute
708
+ $ cakemail attributes get 123 plan_type
709
+
710
+ # If not found, recreate
711
+ $ cakemail attributes create 123 -n "plan_type" -t "text"
712
+ ```
713
+
714
+ ### Cannot Set Attribute Value
715
+
716
+ **Problem:** Attribute value not saving on contact
717
+
718
+ **Solutions:**
719
+ ```bash
720
+ # 1. Ensure attribute exists
721
+ $ cakemail attributes list 123
722
+
723
+ # 2. Check data type matches
724
+ $ cakemail attributes get 123 lifetime_value
725
+ # If type is "number", use number not string:
726
+ $ cakemail contacts update 123 501 -d '{"lifetime_value":599.99}' # ✓
727
+ $ cakemail contacts update 123 501 -d '{"lifetime_value":"599.99"}' # ✗
728
+
729
+ # 3. Check JSON format
730
+ $ cakemail contacts update 123 501 -d '{"plan":"premium"}' # ✓ Valid JSON
731
+ $ cakemail contacts update 123 501 -d '{plan:premium}' # ✗ Invalid JSON
732
+ ```
733
+
734
+ ### Wrong Data Type
735
+
736
+ **Problem:** Created attribute with wrong type
737
+
738
+ **Solution:**
739
+ ```bash
740
+ # Type cannot be changed
741
+ # Must delete and recreate
742
+
743
+ # 1. Export contacts with old attribute
744
+ $ cakemail contacts export 123
745
+
746
+ # 2. Delete old attribute
747
+ $ cakemail attributes delete 123 old_name --force
748
+
749
+ # 3. Create with correct type
750
+ $ cakemail attributes create 123 -n "new_name" -t "number"
751
+
752
+ # 4. Re-import contacts with new attribute
753
+ # (Update CSV with new column)
754
+ $ cakemail contacts import 123 --file updated.csv
755
+ ```
756
+
757
+ ### Date Format Issues
758
+
759
+ **Problem:** Dates not saving correctly
760
+
761
+ **Solution:**
762
+ ```bash
763
+ # Use ISO format: YYYY-MM-DD
764
+ $ cakemail contacts update 123 501 -d '{"signup_date":"2024-03-15"}' # ✓
765
+
766
+ # Wrong formats:
767
+ # "03/15/2024" # ✗ US format
768
+ # "15/03/2024" # ✗ European format
769
+ # "March 15, 2024" # ✗ Text format
770
+
771
+ # Convert if needed
772
+ DATE="03/15/2024"
773
+ ISO_DATE=$(date -d "$DATE" +%Y-%m-%d) # Converts to 2024-03-15
774
+ ```
775
+
776
+ ## Best Practices Summary
777
+
778
+ 1. **Plan schema first** - Design attributes before creating
779
+ 2. **Use descriptive names** - Clear, self-explanatory names
780
+ 3. **Choose correct types** - Match data type to usage
781
+ 4. **Validate input** - Check values before setting
782
+ 5. **Document attributes** - Keep schema documentation
783
+ 6. **Consistent naming** - Use snake_case
784
+ 7. **Sync regularly** - Keep attributes updated from source systems
785
+ 8. **Remove unused** - Delete deprecated attributes
786
+ 9. **Test thoroughly** - Verify attributes work in campaigns
787
+ 10. **Monitor usage** - Track which attributes are actually used
788
+