@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.
Files changed (198) 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 +41 -37
  6. package/audit-formats.js +128 -0
  7. package/cakemail.rb +20 -0
  8. package/dist/client.js +1 -1
  9. package/dist/client.js.map +1 -1
  10. package/dist/commands/account.js +1 -1
  11. package/dist/commands/account.js.map +1 -1
  12. package/dist/commands/attributes.js +1 -1
  13. package/dist/commands/attributes.js.map +1 -1
  14. package/dist/commands/campaigns.js +1 -1
  15. package/dist/commands/campaigns.js.map +1 -1
  16. package/dist/commands/contacts.js +1 -1
  17. package/dist/commands/contacts.js.map +1 -1
  18. package/dist/commands/emails.js +1 -1
  19. package/dist/commands/emails.js.map +1 -1
  20. package/dist/commands/interests.js +1 -1
  21. package/dist/commands/interests.js.map +1 -1
  22. package/dist/commands/lists.js +1 -1
  23. package/dist/commands/lists.js.map +1 -1
  24. package/dist/commands/logs.js +1 -1
  25. package/dist/commands/logs.js.map +1 -1
  26. package/dist/commands/reports.js +1 -1
  27. package/dist/commands/reports.js.map +1 -1
  28. package/dist/commands/segments.js +1 -1
  29. package/dist/commands/segments.js.map +1 -1
  30. package/dist/commands/senders.js +1 -1
  31. package/dist/commands/senders.js.map +1 -1
  32. package/dist/commands/suppressed.js +1 -1
  33. package/dist/commands/suppressed.js.map +1 -1
  34. package/dist/commands/tags.js +1 -1
  35. package/dist/commands/tags.js.map +1 -1
  36. package/dist/commands/templates.js +1 -1
  37. package/dist/commands/templates.js.map +1 -1
  38. package/dist/commands/transactional-templates.js +1 -1
  39. package/dist/commands/transactional-templates.js.map +1 -1
  40. package/dist/commands/webhooks.js +1 -1
  41. package/dist/commands/webhooks.js.map +1 -1
  42. package/dist/utils/config.js +2 -2
  43. package/dist/utils/config.js.map +1 -1
  44. package/dist/utils/errors.js +1 -1
  45. package/dist/utils/errors.js.map +1 -1
  46. package/dist/utils/progress.d.ts.map +1 -1
  47. package/dist/utils/progress.js +32 -4
  48. package/dist/utils/progress.js.map +1 -1
  49. package/dist/utils/spinner.d.ts +17 -0
  50. package/dist/utils/spinner.d.ts.map +1 -0
  51. package/dist/utils/spinner.js +43 -0
  52. package/dist/utils/spinner.js.map +1 -0
  53. package/docs/DOCUMENTATION-STANDARD.md +1068 -0
  54. package/docs/README.md +161 -0
  55. package/docs/developer/ARCHITECTURE.md +516 -0
  56. package/docs/developer/AUTH.md +204 -0
  57. package/docs/developer/CONTRIBUTING.md +227 -0
  58. package/docs/developer/DOCUMENTATION_SUMMARY.md +346 -0
  59. package/docs/developer/PROJECT_INDEX.md +365 -0
  60. package/docs/planning/API_COVERAGE.md +1045 -0
  61. package/docs/planning/BACKLOG.md +1159 -0
  62. package/docs/planning/PROFILE_SYSTEM_TASKS.md +287 -0
  63. package/docs/planning/UX_IMPLEMENTATION_PLAN.md +691 -0
  64. package/docs/planning/archive/RELEASE_CHECKLIST_v1.3.0.md +332 -0
  65. package/docs/planning/archive/RELEASE_v1.3.0.md +428 -0
  66. package/docs/planning/archive/cakemail-cli-ux-improvements.md +438 -0
  67. package/docs/planning/cakemail-profile-system-plan.md +1121 -0
  68. package/docs/testing/AI_USER_SIMULATION_DESIGN.md +1342 -0
  69. package/docs/testing/KENOGAMI_BIDIRECTIONAL_FLOW.md +1517 -0
  70. package/docs/testing/KENOGAMI_TRUTH_RECONCILIATION_SYSTEM.md +1369 -0
  71. package/docs/user-manual/.obsidian/app.json +1 -0
  72. package/docs/user-manual/.obsidian/appearance.json +1 -0
  73. package/docs/user-manual/.obsidian/core-plugins.json +33 -0
  74. package/docs/user-manual/.obsidian/workspace.json +167 -0
  75. package/docs/user-manual/01-getting-started/01-installation.md +214 -0
  76. package/docs/user-manual/01-getting-started/02-quick-start.md +432 -0
  77. package/docs/user-manual/01-getting-started/03-authentication.md +448 -0
  78. package/docs/user-manual/01-getting-started/04-configuration.md +430 -0
  79. package/docs/user-manual/01-getting-started/05-output-formats.md +447 -0
  80. package/docs/user-manual/02-core-concepts/01-accounts.md +514 -0
  81. package/docs/user-manual/02-core-concepts/02-profile-system.md +771 -0
  82. package/docs/user-manual/02-core-concepts/03-smart-defaults.md +485 -0
  83. package/docs/user-manual/02-core-concepts/04-authentication-methods.md +435 -0
  84. package/docs/user-manual/02-core-concepts/05-pagination-filtering.md +600 -0
  85. package/docs/user-manual/02-core-concepts/06-error-handling.md +718 -0
  86. package/docs/user-manual/02-core-concepts/07-api-coverage.md +483 -0
  87. package/docs/user-manual/03-email-operations/01-senders.md +490 -0
  88. package/docs/user-manual/03-email-operations/02-templates.md +444 -0
  89. package/docs/user-manual/03-email-operations/03-transactional-emails.md +706 -0
  90. package/docs/user-manual/03-email-operations/04-email-tracking.md +407 -0
  91. package/docs/user-manual/04-campaign-management/01-campaigns-basics.md +394 -0
  92. package/docs/user-manual/04-campaign-management/02-campaign-scheduling.md +630 -0
  93. package/docs/user-manual/04-campaign-management/03-campaign-testing.md +997 -0
  94. package/docs/user-manual/04-campaign-management/04-campaign-lifecycle.md +709 -0
  95. package/docs/user-manual/04-campaign-management/05-campaign-links.md +934 -0
  96. package/docs/user-manual/05-contact-management/01-lists.md +836 -0
  97. package/docs/user-manual/05-contact-management/02-contacts.md +1035 -0
  98. package/docs/user-manual/05-contact-management/03-custom-attributes.md +788 -0
  99. package/docs/user-manual/05-contact-management/04-segments.md +1028 -0
  100. package/docs/user-manual/05-contact-management/05-contact-import-export.md +1031 -0
  101. package/docs/user-manual/06-analytics-reporting/01-campaign-analytics.md +867 -0
  102. package/docs/user-manual/06-analytics-reporting/02-account-reports.md +227 -0
  103. package/docs/user-manual/07-integrations/01-webhooks-integration.md +259 -0
  104. package/docs/user-manual/07-integrations/02-automation.md +326 -0
  105. package/docs/user-manual/08-advanced-usage/01-scripting-patterns.md +672 -0
  106. package/docs/user-manual/08-advanced-usage/02-bulk-operations.md +932 -0
  107. package/docs/user-manual/08-advanced-usage/03-ci-cd-integration.md +892 -0
  108. package/docs/user-manual/08-advanced-usage/04-performance-optimization.md +766 -0
  109. package/docs/user-manual/09-command-reference/01-config.md +776 -0
  110. package/docs/user-manual/09-command-reference/02-account.md +652 -0
  111. package/docs/user-manual/09-command-reference/03-lists.md +958 -0
  112. package/docs/user-manual/09-command-reference/04-contacts.md +1408 -0
  113. package/docs/user-manual/09-command-reference/05-attributes.md +617 -0
  114. package/docs/user-manual/09-command-reference/06-segments.md +894 -0
  115. package/docs/user-manual/09-command-reference/07-senders.md +803 -0
  116. package/docs/user-manual/09-command-reference/08-templates.md +818 -0
  117. package/docs/user-manual/09-command-reference/09-campaigns.md +1250 -0
  118. package/docs/user-manual/09-command-reference/10-emails.md +807 -0
  119. package/docs/user-manual/09-command-reference/11-reports.md +1135 -0
  120. package/docs/user-manual/09-command-reference/12-webhooks.md +773 -0
  121. package/docs/user-manual/09-command-reference/13-suppressed.md +797 -0
  122. package/docs/user-manual/09-command-reference/14-interests.md +630 -0
  123. package/docs/user-manual/09-command-reference/15-tags.md +584 -0
  124. package/docs/user-manual/09-command-reference/16-logs.md +656 -0
  125. package/docs/user-manual/09-command-reference/17-transactional-templates.md +850 -0
  126. package/docs/user-manual/10-troubleshooting/01-common-errors.md +457 -0
  127. package/docs/user-manual/10-troubleshooting/02-authentication-issues.md +558 -0
  128. package/docs/user-manual/10-troubleshooting/03-connection-problems.md +634 -0
  129. package/docs/user-manual/10-troubleshooting/04-debugging.md +725 -0
  130. package/docs/user-manual/11-appendix/04-faq.md +484 -0
  131. package/docs/user-manual/11-appendix/05-glossary.md +250 -0
  132. package/docs/user-manual/README.md +0 -0
  133. package/package.json +13 -61
  134. package/src/cli.ts +125 -0
  135. package/src/client.ts +16 -0
  136. package/src/commands/account.ts +267 -0
  137. package/src/commands/accounts.ts +78 -0
  138. package/src/commands/actions.ts +249 -0
  139. package/src/commands/attributes.ts +139 -0
  140. package/src/commands/campaign-blueprints.ts +106 -0
  141. package/src/commands/campaigns.ts +469 -0
  142. package/src/commands/config.ts +77 -0
  143. package/src/commands/contacts.ts +612 -0
  144. package/src/commands/custom-attributes.ts +127 -0
  145. package/src/commands/dkims.ts +117 -0
  146. package/src/commands/domains.ts +82 -0
  147. package/src/commands/email-apis.ts +569 -0
  148. package/src/commands/emails.ts +197 -0
  149. package/src/commands/forms.ts +283 -0
  150. package/src/commands/interests.ts +155 -0
  151. package/src/commands/links.ts +38 -0
  152. package/src/commands/lists.ts +406 -0
  153. package/src/commands/logos.ts +71 -0
  154. package/src/commands/logs.ts +386 -0
  155. package/src/commands/reports.ts +306 -0
  156. package/src/commands/segments.ts +158 -0
  157. package/src/commands/senders.ts +204 -0
  158. package/src/commands/sub-accounts.ts +271 -0
  159. package/src/commands/suppressed-emails.ts +234 -0
  160. package/src/commands/suppressed.ts +198 -0
  161. package/src/commands/system-emails.ts +85 -0
  162. package/src/commands/tags.ts +146 -0
  163. package/src/commands/tasks.ts +116 -0
  164. package/src/commands/templates.ts +189 -0
  165. package/src/commands/tokens.ts +83 -0
  166. package/src/commands/transactional-emails.ts +374 -0
  167. package/src/commands/transactional-templates.ts +385 -0
  168. package/src/commands/users.ts +506 -0
  169. package/src/commands/webhooks.ts +172 -0
  170. package/src/commands/workflow-blueprints.ts +123 -0
  171. package/src/commands/workflows.ts +265 -0
  172. package/src/types/profile.ts +93 -0
  173. package/src/utils/auth.ts +272 -0
  174. package/src/utils/config-file.ts +96 -0
  175. package/src/utils/config.ts +134 -0
  176. package/src/utils/confirm.ts +32 -0
  177. package/src/utils/defaults.ts +99 -0
  178. package/src/utils/errors.ts +116 -0
  179. package/src/utils/interactive.ts +91 -0
  180. package/src/utils/list-defaults.ts +74 -0
  181. package/src/utils/output.ts +190 -0
  182. package/src/utils/progress.ts +320 -0
  183. package/src/utils/spinner.ts +22 -0
  184. package/tests/IMPLEMENTATION_STATUS.md +258 -0
  185. package/tests/PTY_SETUP.md +118 -0
  186. package/tests/PTY_TESTING_GUIDE.md +507 -0
  187. package/tests/README.md +244 -0
  188. package/tests/fixtures/api-responses/campaigns.json +34 -0
  189. package/tests/fixtures/test-config.json +13 -0
  190. package/tests/helpers/cli-runner.ts +128 -0
  191. package/tests/helpers/mock-server.ts +301 -0
  192. package/tests/helpers/pty-runner.ts +181 -0
  193. package/tests/integration/campaigns-real-api.test.ts +196 -0
  194. package/tests/integration/setup-integration.ts +50 -0
  195. package/tests/pty/campaigns.test.ts +241 -0
  196. package/tests/setup.ts +34 -0
  197. package/tsconfig.json +15 -0
  198. package/vitest.config.ts +28 -0
@@ -0,0 +1,1028 @@
1
+ # Contact Segmentation
2
+
3
+ Create dynamic contact segments that automatically update based on conditions and behaviors.
4
+
5
+ ## Overview
6
+
7
+ Segmentation allows you to:
8
+ - Target specific audience subsets
9
+ - Create dynamic, automatically-updating groups
10
+ - Filter by engagement, attributes, and behavior
11
+ - Personalize campaigns for different audiences
12
+ - Improve campaign relevance and performance
13
+ - Automate audience selection
14
+
15
+ Unlike static lists, segments are dynamic filters that automatically include contacts matching specified conditions. Segment membership updates in real-time as contact data changes.
16
+
17
+ ## Quick Start
18
+
19
+ ### Create Your First Segment
20
+
21
+ ```bash
22
+ $ cakemail segments create 123 -n "Active Subscribers" -c '{
23
+ "match": "all",
24
+ "rules": [
25
+ {"field": "status", "operator": "equals", "value": "subscribed"},
26
+ {"field": "last_open_date", "operator": "greater_than", "value": "2024-01-01"}
27
+ ]
28
+ }'
29
+ ```
30
+
31
+ **Output:**
32
+ ```
33
+ ✓ Segment created: 456
34
+ {
35
+ "id": 456,
36
+ "name": "Active Subscribers",
37
+ "contact_count": 1180
38
+ }
39
+ ```
40
+
41
+ ### View Segment Contacts
42
+
43
+ ```bash
44
+ $ cakemail segments contacts 123 456
45
+ ```
46
+
47
+ **Output:**
48
+ ```
49
+ ┌────────┬──────────────────────┬────────────┬────────────┬──────────────┐
50
+ │ ID │ Email │ First Name │ Last Name │ Status │
51
+ ├────────┼──────────────────────┼────────────┼────────────┼──────────────┤
52
+ │ 501 │ john@example.com │ John │ Doe │ subscribed │
53
+ │ 502 │ jane@example.com │ Jane │ Smith │ subscribed │
54
+ └────────┴──────────────────────┴────────────┴────────────┴──────────────┘
55
+ ```
56
+
57
+ ## Segment Basics
58
+
59
+ ### Understanding Segments vs Lists
60
+
61
+ **Lists** are static containers:
62
+ - Manually add/remove contacts
63
+ - Members don't change automatically
64
+ - Good for: Distinct audiences, newsletters
65
+
66
+ **Segments** are dynamic filters:
67
+ - Automatically include/exclude based on rules
68
+ - Membership updates as data changes
69
+ - Good for: Behavioral targeting, lifecycle stages
70
+
71
+ **Example:**
72
+ ```bash
73
+ # Static list - manually managed
74
+ $ cakemail lists create -n "Newsletter Subscribers"
75
+ $ cakemail contacts add 123 -e "user@example.com"
76
+
77
+ # Dynamic segment - rule-based
78
+ $ cakemail segments create 123 -n "Engaged Users" -c '{
79
+ "match": "all",
80
+ "rules": [
81
+ {"field": "last_open_date", "operator": "greater_than", "value": "2024-03-01"}
82
+ ]
83
+ }'
84
+ # Automatically includes contacts who opened after March 1
85
+ ```
86
+
87
+ ### Segment Conditions
88
+
89
+ Every segment has conditions that define which contacts are included.
90
+
91
+ **Basic structure:**
92
+ ```json
93
+ {
94
+ "match": "all|any",
95
+ "rules": [
96
+ {
97
+ "field": "field_name",
98
+ "operator": "comparison_type",
99
+ "value": "comparison_value"
100
+ }
101
+ ]
102
+ }
103
+ ```
104
+
105
+ **Match types:**
106
+ - `all` - Contacts must meet ALL rules (AND logic)
107
+ - `any` - Contacts must meet AT LEAST ONE rule (OR logic)
108
+
109
+ ## Creating Segments
110
+
111
+ ### By Status
112
+
113
+ **Active subscribers only:**
114
+ ```bash
115
+ $ cakemail segments create 123 -n "Active Subscribers" -c '{
116
+ "match": "all",
117
+ "rules": [
118
+ {"field": "status", "operator": "equals", "value": "subscribed"}
119
+ ]
120
+ }'
121
+ ```
122
+
123
+ **Unsubscribed for analysis:**
124
+ ```bash
125
+ $ cakemail segments create 123 -n "Unsubscribed" -c '{
126
+ "match": "all",
127
+ "rules": [
128
+ {"field": "status", "operator": "equals", "value": "unsubscribed"}
129
+ ]
130
+ }'
131
+ ```
132
+
133
+ ### By Engagement
134
+
135
+ **Highly engaged:**
136
+ ```bash
137
+ $ cakemail segments create 123 -n "Highly Engaged" -c '{
138
+ "match": "all",
139
+ "rules": [
140
+ {"field": "last_open_date", "operator": "greater_than", "value": "2024-02-01"},
141
+ {"field": "last_click_date", "operator": "greater_than", "value": "2024-02-01"}
142
+ ]
143
+ }'
144
+ ```
145
+
146
+ **Recently opened:**
147
+ ```bash
148
+ $ cakemail segments create 123 -n "Opened Last 30 Days" -c '{
149
+ "match": "all",
150
+ "rules": [
151
+ {"field": "last_open_date", "operator": "greater_than", "value": "2024-02-15"}
152
+ ]
153
+ }'
154
+ ```
155
+
156
+ **Never opened:**
157
+ ```bash
158
+ $ cakemail segments create 123 -n "Never Opened" -c '{
159
+ "match": "all",
160
+ "rules": [
161
+ {"field": "status", "operator": "equals", "value": "subscribed"},
162
+ {"field": "last_open_date", "operator": "is_empty", "value": ""}
163
+ ]
164
+ }'
165
+ ```
166
+
167
+ **Inactive subscribers:**
168
+ ```bash
169
+ $ cakemail segments create 123 -n "Inactive 90+ Days" -c '{
170
+ "match": "all",
171
+ "rules": [
172
+ {"field": "status", "operator": "equals", "value": "subscribed"},
173
+ {"field": "last_open_date", "operator": "less_than", "value": "2023-12-15"}
174
+ ]
175
+ }'
176
+ ```
177
+
178
+ ### By Custom Attributes
179
+
180
+ **Premium plan users:**
181
+ ```bash
182
+ $ cakemail segments create 123 -n "Premium Users" -c '{
183
+ "match": "all",
184
+ "rules": [
185
+ {"field": "custom_attributes.plan_type", "operator": "equals", "value": "premium"},
186
+ {"field": "status", "operator": "equals", "value": "subscribed"}
187
+ ]
188
+ }'
189
+ ```
190
+
191
+ **High-value customers:**
192
+ ```bash
193
+ $ cakemail segments create 123 -n "High Value Customers" -c '{
194
+ "match": "all",
195
+ "rules": [
196
+ {"field": "custom_attributes.lifetime_value", "operator": "greater_than", "value": "1000"}
197
+ ]
198
+ }'
199
+ ```
200
+
201
+ **VIP members:**
202
+ ```bash
203
+ $ cakemail segments create 123 -n "VIP Members" -c '{
204
+ "match": "all",
205
+ "rules": [
206
+ {"field": "custom_attributes.is_vip", "operator": "equals", "value": "true"},
207
+ {"field": "status", "operator": "equals", "value": "subscribed"}
208
+ ]
209
+ }'
210
+ ```
211
+
212
+ **Recent signups:**
213
+ ```bash
214
+ $ cakemail segments create 123 -n "New Signups - Last 7 Days" -c '{
215
+ "match": "all",
216
+ "rules": [
217
+ {"field": "custom_attributes.signup_date", "operator": "greater_than", "value": "2024-03-08"}
218
+ ]
219
+ }'
220
+ ```
221
+
222
+ ### By Date Ranges
223
+
224
+ **Trial ending soon:**
225
+ ```bash
226
+ $ cakemail segments create 123 -n "Trial Ending < 7 Days" -c '{
227
+ "match": "all",
228
+ "rules": [
229
+ {"field": "custom_attributes.trial_end_date", "operator": "less_than", "value": "2024-03-22"},
230
+ {"field": "custom_attributes.trial_end_date", "operator": "greater_than", "value": "2024-03-15"}
231
+ ]
232
+ }'
233
+ ```
234
+
235
+ **Birthday month:**
236
+ ```bash
237
+ #!/bin/bash
238
+ # Create birthday segment for current month
239
+ CURRENT_MONTH=$(date +%m)
240
+ YEAR=$(date +%Y)
241
+
242
+ $ cakemail segments create 123 -n "Birthday This Month" -c "{
243
+ \"match\": \"all\",
244
+ \"rules\": [
245
+ {\"field\": \"custom_attributes.birthday\", \"operator\": \"greater_than\", \"value\": \"$YEAR-$CURRENT_MONTH-01\"},
246
+ {\"field\": \"custom_attributes.birthday\", \"operator\": \"less_than\", \"value\": \"$YEAR-$CURRENT_MONTH-31\"}
247
+ ]
248
+ }"
249
+ ```
250
+
251
+ ### Complex Conditions
252
+
253
+ **Engaged OR recent (ANY match):**
254
+ ```bash
255
+ $ cakemail segments create 123 -n "Engaged or Recent" -c '{
256
+ "match": "any",
257
+ "rules": [
258
+ {"field": "last_click_date", "operator": "greater_than", "value": "2024-02-01"},
259
+ {"field": "subscribed_on", "operator": "greater_than", "value": "2024-03-01"}
260
+ ]
261
+ }'
262
+ ```
263
+
264
+ **Premium AND engaged:**
265
+ ```bash
266
+ $ cakemail segments create 123 -n "Premium Engaged Users" -c '{
267
+ "match": "all",
268
+ "rules": [
269
+ {"field": "custom_attributes.plan_type", "operator": "equals", "value": "premium"},
270
+ {"field": "last_open_date", "operator": "greater_than", "value": "2024-02-01"},
271
+ {"field": "status", "operator": "equals", "value": "subscribed"}
272
+ ]
273
+ }'
274
+ ```
275
+
276
+ ## Available Operators
277
+
278
+ ### Equality Operators
279
+
280
+ **equals:**
281
+ ```json
282
+ {"field": "status", "operator": "equals", "value": "subscribed"}
283
+ {"field": "custom_attributes.plan", "operator": "equals", "value": "premium"}
284
+ ```
285
+
286
+ **not_equals:**
287
+ ```json
288
+ {"field": "status", "operator": "not_equals", "value": "unsubscribed"}
289
+ {"field": "custom_attributes.plan", "operator": "not_equals", "value": "free"}
290
+ ```
291
+
292
+ ### Comparison Operators
293
+
294
+ **greater_than:**
295
+ ```json
296
+ {"field": "last_open_date", "operator": "greater_than", "value": "2024-03-01"}
297
+ {"field": "custom_attributes.lifetime_value", "operator": "greater_than", "value": "500"}
298
+ ```
299
+
300
+ **less_than:**
301
+ ```json
302
+ {"field": "last_open_date", "operator": "less_than", "value": "2024-01-01"}
303
+ {"field": "custom_attributes.age", "operator": "less_than", "value": "30"}
304
+ ```
305
+
306
+ ### String Operators
307
+
308
+ **contains:**
309
+ ```json
310
+ {"field": "email", "operator": "contains", "value": "@gmail.com"}
311
+ {"field": "custom_attributes.company", "operator": "contains", "value": "Corp"}
312
+ ```
313
+
314
+ **not_contains:**
315
+ ```json
316
+ {"field": "email", "operator": "not_contains", "value": "@spam.com"}
317
+ ```
318
+
319
+ **starts_with:**
320
+ ```json
321
+ {"field": "first_name", "operator": "starts_with", "value": "J"}
322
+ {"field": "email", "operator": "starts_with", "value": "admin"}
323
+ ```
324
+
325
+ **ends_with:**
326
+ ```json
327
+ {"field": "email", "operator": "ends_with", "value": ".edu"}
328
+ {"field": "last_name", "operator": "ends_with", "value": "son"}
329
+ ```
330
+
331
+ ### Null/Empty Operators
332
+
333
+ **is_empty:**
334
+ ```json
335
+ {"field": "first_name", "operator": "is_empty", "value": ""}
336
+ {"field": "last_open_date", "operator": "is_empty", "value": ""}
337
+ ```
338
+
339
+ **is_not_empty:**
340
+ ```json
341
+ {"field": "first_name", "operator": "is_not_empty", "value": ""}
342
+ {"field": "custom_attributes.company", "operator": "is_not_empty", "value": ""}
343
+ ```
344
+
345
+ ## Segment Workflows
346
+
347
+ ### Workflow 1: Customer Lifecycle Segments
348
+
349
+ ```bash
350
+ #!/bin/bash
351
+ # create-lifecycle-segments.sh
352
+
353
+ LIST_ID=123
354
+
355
+ echo "=== Creating Lifecycle Segments ==="
356
+ echo ""
357
+
358
+ # New customers (< 30 days)
359
+ cakemail segments create $LIST_ID -n "New Customers" -c '{
360
+ "match": "all",
361
+ "rules": [
362
+ {"field": "custom_attributes.signup_date", "operator": "greater_than", "value": "2024-02-15"}
363
+ ]
364
+ }'
365
+ echo "✓ New Customers segment created"
366
+
367
+ # Active customers (opened in last 30 days)
368
+ cakemail segments create $LIST_ID -n "Active Customers" -c '{
369
+ "match": "all",
370
+ "rules": [
371
+ {"field": "status", "operator": "equals", "value": "subscribed"},
372
+ {"field": "last_open_date", "operator": "greater_than", "value": "2024-02-15"}
373
+ ]
374
+ }'
375
+ echo "✓ Active Customers segment created"
376
+
377
+ # At-risk (no open in 30-90 days)
378
+ cakemail segments create $LIST_ID -n "At Risk" -c '{
379
+ "match": "all",
380
+ "rules": [
381
+ {"field": "status", "operator": "equals", "value": "subscribed"},
382
+ {"field": "last_open_date", "operator": "less_than", "value": "2024-02-15"},
383
+ {"field": "last_open_date", "operator": "greater_than", "value": "2023-12-15"}
384
+ ]
385
+ }'
386
+ echo "✓ At Risk segment created"
387
+
388
+ # Lapsed (no open in 90+ days)
389
+ cakemail segments create $LIST_ID -n "Lapsed Customers" -c '{
390
+ "match": "all",
391
+ "rules": [
392
+ {"field": "status", "operator": "equals", "value": "subscribed"},
393
+ {"field": "last_open_date", "operator": "less_than", "value": "2023-12-15"}
394
+ ]
395
+ }'
396
+ echo "✓ Lapsed Customers segment created"
397
+
398
+ echo ""
399
+ echo "=== Lifecycle Segments Created ==="
400
+ cakemail segments list $LIST_ID
401
+ ```
402
+
403
+ ### Workflow 2: Engagement Scoring Segments
404
+
405
+ ```bash
406
+ #!/bin/bash
407
+ # create-engagement-segments.sh
408
+
409
+ LIST_ID=123
410
+
411
+ echo "=== Creating Engagement Segments ==="
412
+ echo ""
413
+
414
+ # Highly engaged (opened AND clicked recently)
415
+ cakemail segments create $LIST_ID -n "Highly Engaged" -c '{
416
+ "match": "all",
417
+ "rules": [
418
+ {"field": "status", "operator": "equals", "value": "subscribed"},
419
+ {"field": "last_open_date", "operator": "greater_than", "value": "2024-03-01"},
420
+ {"field": "last_click_date", "operator": "greater_than", "value": "2024-03-01"}
421
+ ]
422
+ }'
423
+
424
+ # Moderately engaged (opened but no clicks)
425
+ cakemail segments create $LIST_ID -n "Moderately Engaged" -c '{
426
+ "match": "all",
427
+ "rules": [
428
+ {"field": "status", "operator": "equals", "value": "subscribed"},
429
+ {"field": "last_open_date", "operator": "greater_than", "value": "2024-02-01"},
430
+ {"field": "last_click_date", "operator": "less_than", "value": "2024-02-01"}
431
+ ]
432
+ }'
433
+
434
+ # Low engagement (no opens in 30+ days)
435
+ cakemail segments create $LIST_ID -n "Low Engagement" -c '{
436
+ "match": "all",
437
+ "rules": [
438
+ {"field": "status", "operator": "equals", "value": "subscribed"},
439
+ {"field": "last_open_date", "operator": "less_than", "value": "2024-02-15"}
440
+ ]
441
+ }'
442
+
443
+ echo "✓ Engagement segments created"
444
+ ```
445
+
446
+ ### Workflow 3: E-commerce Segments
447
+
448
+ ```bash
449
+ #!/bin/bash
450
+ # create-ecommerce-segments.sh
451
+
452
+ LIST_ID=123
453
+
454
+ echo "=== Creating E-commerce Segments ==="
455
+ echo ""
456
+
457
+ # Frequent buyers
458
+ cakemail segments create $LIST_ID -n "Frequent Buyers" -c '{
459
+ "match": "all",
460
+ "rules": [
461
+ {"field": "custom_attributes.purchase_count", "operator": "greater_than", "value": "5"},
462
+ {"field": "status", "operator": "equals", "value": "subscribed"}
463
+ ]
464
+ }'
465
+
466
+ # High-value customers
467
+ cakemail segments create $LIST_ID -n "High Value" -c '{
468
+ "match": "all",
469
+ "rules": [
470
+ {"field": "custom_attributes.lifetime_value", "operator": "greater_than", "value": "1000"}
471
+ ]
472
+ }'
473
+
474
+ # Recent purchasers (last 30 days)
475
+ cakemail segments create $LIST_ID -n "Recent Purchasers" -c '{
476
+ "match": "all",
477
+ "rules": [
478
+ {"field": "custom_attributes.last_purchase_date", "operator": "greater_than", "value": "2024-02-15"}
479
+ ]
480
+ }'
481
+
482
+ # Cart abandoners
483
+ cakemail segments create $LIST_ID -n "Abandoned Cart" -c '{
484
+ "match": "all",
485
+ "rules": [
486
+ {"field": "custom_attributes.has_active_cart", "operator": "equals", "value": "true"},
487
+ {"field": "custom_attributes.cart_abandoned_date", "operator": "greater_than", "value": "2024-03-10"}
488
+ ]
489
+ }'
490
+
491
+ echo "✓ E-commerce segments created"
492
+ ```
493
+
494
+ ### Workflow 4: SaaS/Subscription Segments
495
+
496
+ ```bash
497
+ #!/bin/bash
498
+ # create-saas-segments.sh
499
+
500
+ LIST_ID=123
501
+
502
+ echo "=== Creating SaaS Segments ==="
503
+ echo ""
504
+
505
+ # Trial users
506
+ cakemail segments create $LIST_ID -n "Active Trials" -c '{
507
+ "match": "all",
508
+ "rules": [
509
+ {"field": "custom_attributes.is_trial", "operator": "equals", "value": "true"},
510
+ {"field": "custom_attributes.trial_end_date", "operator": "greater_than", "value": "2024-03-15"}
511
+ ]
512
+ }'
513
+
514
+ # Trial ending soon
515
+ cakemail segments create $LIST_ID -n "Trial Ending Soon" -c '{
516
+ "match": "all",
517
+ "rules": [
518
+ {"field": "custom_attributes.is_trial", "operator": "equals", "value": "true"},
519
+ {"field": "custom_attributes.trial_end_date", "operator": "less_than", "value": "2024-03-22"},
520
+ {"field": "custom_attributes.trial_end_date", "operator": "greater_than", "value": "2024-03-15"}
521
+ ]
522
+ }'
523
+
524
+ # Paying customers
525
+ cakemail segments create $LIST_ID -n "Paying Customers" -c '{
526
+ "match": "all",
527
+ "rules": [
528
+ {"field": "custom_attributes.is_paying", "operator": "equals", "value": "true"}
529
+ ]
530
+ }'
531
+
532
+ # Inactive users (low usage)
533
+ cakemail segments create $LIST_ID -n "Inactive Users" -c '{
534
+ "match": "all",
535
+ "rules": [
536
+ {"field": "custom_attributes.is_paying", "operator": "equals", "value": "true"},
537
+ {"field": "custom_attributes.last_login", "operator": "less_than", "value": "2024-02-15"}
538
+ ]
539
+ }'
540
+
541
+ # Churn risk
542
+ cakemail segments create $LIST_ID -n "Churn Risk" -c '{
543
+ "match": "all",
544
+ "rules": [
545
+ {"field": "custom_attributes.health_score", "operator": "less_than", "value": "40"}
546
+ ]
547
+ }'
548
+
549
+ echo "✓ SaaS segments created"
550
+ ```
551
+
552
+ ### Workflow 5: Segment Analysis
553
+
554
+ ```bash
555
+ #!/bin/bash
556
+ # analyze-segments.sh
557
+
558
+ LIST_ID=123
559
+
560
+ echo "=== Segment Analysis ==="
561
+ echo ""
562
+
563
+ # Get all segments
564
+ SEGMENTS=$(cakemail segments list $LIST_ID -f json | jq -r '.data[].id')
565
+
566
+ echo "Segment | Name | Count | % of List"
567
+ echo "--------|------|-------|----------"
568
+
569
+ # Get total list size
570
+ TOTAL=$(cakemail contacts list $LIST_ID -f json | jq '.count')
571
+
572
+ for SEG_ID in $SEGMENTS; do
573
+ SEG=$(cakemail segments get $LIST_ID $SEG_ID -f json)
574
+
575
+ NAME=$(echo "$SEG" | jq -r '.name' | cut -c1-20)
576
+ COUNT=$(echo "$SEG" | jq -r '.contact_count')
577
+
578
+ if [ $TOTAL -gt 0 ]; then
579
+ PERCENT=$(echo "scale=1; $COUNT * 100 / $TOTAL" | bc)
580
+ else
581
+ PERCENT="0"
582
+ fi
583
+
584
+ printf "%-7s | %-20s | %5d | %5s%%\n" "$SEG_ID" "$NAME" "$COUNT" "$PERCENT"
585
+ done
586
+
587
+ echo ""
588
+ echo "Total list size: $TOTAL"
589
+ ```
590
+
591
+ ## Using Segments with Campaigns
592
+
593
+ ### Send to Segment
594
+
595
+ ```bash
596
+ # Create campaign for segment
597
+ $ cakemail campaigns create \
598
+ -n "VIP Exclusive Offer" \
599
+ -l 123 \
600
+ -s 101 \
601
+ --segment 456 \
602
+ --subject "Exclusive Offer for Our VIPs"
603
+ ```
604
+
605
+ ### Preview Segment Before Sending
606
+
607
+ ```bash
608
+ # Check segment size
609
+ $ cakemail segments get 123 456 -f json | jq '.contact_count'
610
+
611
+ # Preview contacts
612
+ $ cakemail segments contacts 123 456 -l 10
613
+
614
+ # Send test to segment sample
615
+ $ cakemail campaigns test 790 -e test@example.com
616
+ ```
617
+
618
+ ### Multiple Segments Campaign
619
+
620
+ ```bash
621
+ #!/bin/bash
622
+ # send-to-multiple-segments.sh
623
+
624
+ CAMPAIGN_NAME="March Newsletter"
625
+ LIST_ID=123
626
+ SENDER_ID=101
627
+ SEGMENTS=(456 457 458)
628
+
629
+ for SEG_ID in "${SEGMENTS[@]}"; do
630
+ SEG_NAME=$(cakemail segments get $LIST_ID $SEG_ID -f json | jq -r '.name')
631
+
632
+ echo "Creating campaign for segment: $SEG_NAME"
633
+
634
+ CAMPAIGN_ID=$(cakemail campaigns create \
635
+ -n "$CAMPAIGN_NAME - $SEG_NAME" \
636
+ -l $LIST_ID \
637
+ -s $SENDER_ID \
638
+ --segment $SEG_ID \
639
+ --subject "March Newsletter" \
640
+ -f json | jq -r '.id')
641
+
642
+ echo " Campaign created: $CAMPAIGN_ID"
643
+
644
+ # Schedule for different times
645
+ # (Example: stagger sends)
646
+ sleep 2
647
+ done
648
+ ```
649
+
650
+ ## Segment Management
651
+
652
+ ### Update Segment Conditions
653
+
654
+ ```bash
655
+ # Broaden segment
656
+ $ cakemail segments update 123 456 -c '{
657
+ "match": "any",
658
+ "rules": [
659
+ {"field": "last_open_date", "operator": "greater_than", "value": "2024-01-01"},
660
+ {"field": "last_click_date", "operator": "greater_than", "value": "2024-01-01"}
661
+ ]
662
+ }'
663
+
664
+ # Narrow segment
665
+ $ cakemail segments update 123 456 -c '{
666
+ "match": "all",
667
+ "rules": [
668
+ {"field": "status", "operator": "equals", "value": "subscribed"},
669
+ {"field": "custom_attributes.plan", "operator": "equals", "value": "premium"},
670
+ {"field": "last_open_date", "operator": "greater_than", "value": "2024-03-01"}
671
+ ]
672
+ }'
673
+ ```
674
+
675
+ ### Rename Segment
676
+
677
+ ```bash
678
+ $ cakemail segments update 123 456 -n "Highly Engaged Premium Users"
679
+ ```
680
+
681
+ ### Clone Segment
682
+
683
+ ```bash
684
+ #!/bin/bash
685
+ # clone-segment.sh
686
+
687
+ SOURCE_SEG=$1
688
+ NEW_NAME="$2"
689
+ LIST_ID=123
690
+
691
+ # Get source segment
692
+ SOURCE=$(cakemail segments get $LIST_ID $SOURCE_SEG -f json)
693
+ CONDITIONS=$(echo "$SOURCE" | jq -c '.conditions')
694
+
695
+ # Create new segment with same conditions
696
+ cakemail segments create $LIST_ID -n "$NEW_NAME" -c "$CONDITIONS"
697
+
698
+ echo "✓ Segment cloned"
699
+ ```
700
+
701
+ ### Delete Unused Segments
702
+
703
+ ```bash
704
+ #!/bin/bash
705
+ # delete-empty-segments.sh
706
+
707
+ LIST_ID=123
708
+
709
+ echo "=== Deleting Empty Segments ==="
710
+ echo ""
711
+
712
+ SEGMENTS=$(cakemail segments list $LIST_ID -f json | jq -r '.data[].id')
713
+
714
+ for SEG_ID in $SEGMENTS; do
715
+ SEG=$(cakemail segments get $LIST_ID $SEG_ID -f json)
716
+ NAME=$(echo "$SEG" | jq -r '.name')
717
+ COUNT=$(echo "$SEG" | jq -r '.contact_count')
718
+
719
+ if [ $COUNT -eq 0 ]; then
720
+ echo "Deleting empty segment: $NAME (ID: $SEG_ID)"
721
+ cakemail segments delete $LIST_ID $SEG_ID --force
722
+ fi
723
+ done
724
+
725
+ echo "✓ Cleanup complete"
726
+ ```
727
+
728
+ ## Advanced Segmentation
729
+
730
+ ### Time-Based Dynamic Segments
731
+
732
+ ```bash
733
+ #!/bin/bash
734
+ # update-time-based-segments.sh
735
+
736
+ LIST_ID=123
737
+ SEGMENT_ID=456
738
+
739
+ # Update to rolling 30-day window
740
+ THIRTY_DAYS_AGO=$(date -d "30 days ago" +%Y-%m-%d)
741
+
742
+ cakemail segments update $LIST_ID $SEGMENT_ID -c "{
743
+ \"match\": \"all\",
744
+ \"rules\": [
745
+ {\"field\": \"last_open_date\", \"operator\": \"greater_than\", \"value\": \"$THIRTY_DAYS_AGO\"}
746
+ ]
747
+ }"
748
+
749
+ echo "✓ Updated to rolling 30-day window"
750
+ ```
751
+
752
+ **Schedule with cron:**
753
+ ```bash
754
+ # Update daily at midnight
755
+ 0 0 * * * /path/to/update-time-based-segments.sh
756
+ ```
757
+
758
+ ### Combine Segments Logically
759
+
760
+ ```bash
761
+ # Segment A OR Segment B (contacts in either)
762
+ # Export both, combine, deduplicate
763
+
764
+ # Segment A AND Segment B (contacts in both)
765
+ # Use nested conditions to replicate both segment rules
766
+
767
+ # Segment A NOT Segment B (in A but not B)
768
+ # Export both, find difference
769
+ ```
770
+
771
+ ### Export Segment for External Processing
772
+
773
+ ```bash
774
+ #!/bin/bash
775
+ # export-segment.sh
776
+
777
+ LIST_ID=123
778
+ SEGMENT_ID=$1
779
+
780
+ if [ -z "$SEGMENT_ID" ]; then
781
+ echo "Usage: $0 <segment-id>"
782
+ exit 1
783
+ fi
784
+
785
+ # Get segment contacts
786
+ cakemail segments contacts $LIST_ID $SEGMENT_ID -f json | \
787
+ jq -r '.data[] | [.email, .first_name, .last_name] | @csv' > segment-export.csv
788
+
789
+ echo "✓ Exported to segment-export.csv"
790
+ ```
791
+
792
+ ## Best Practices
793
+
794
+ ### 1. Name Segments Descriptively
795
+
796
+ ```bash
797
+ # Good names
798
+ "Highly Engaged - Last 30 Days"
799
+ "Premium Plan - Active"
800
+ "Trial Ending < 7 Days"
801
+ "Cart Abandoned - Last Week"
802
+
803
+ # Avoid
804
+ "Segment 1"
805
+ "Test"
806
+ "Users"
807
+ ```
808
+
809
+ ### 2. Start Broad, Then Narrow
810
+
811
+ ```bash
812
+ # Start with broad segment
813
+ $ cakemail segments create 123 -n "Engaged Users" -c '{
814
+ "match": "all",
815
+ "rules": [
816
+ {"field": "last_open_date", "operator": "greater_than", "value": "2024-01-01"}
817
+ ]
818
+ }'
819
+
820
+ # Preview size
821
+ $ cakemail segments get 123 456 -f json | jq '.contact_count'
822
+
823
+ # If too large, narrow
824
+ $ cakemail segments update 123 456 -c '{
825
+ "match": "all",
826
+ "rules": [
827
+ {"field": "last_open_date", "operator": "greater_than", "value": "2024-03-01"},
828
+ {"field": "last_click_date", "operator": "greater_than", "value": "2024-03-01"}
829
+ ]
830
+ }'
831
+ ```
832
+
833
+ ### 3. Document Complex Segments
834
+
835
+ ```bash
836
+ # Create README for segment definitions
837
+ cat > segments-documentation.md << 'EOF'
838
+ # Segment Definitions
839
+
840
+ ## High Value Customers (ID: 456)
841
+ - **Rules:** LTV > $1000 AND Status = Subscribed
842
+ - **Purpose:** Exclusive offers and VIP treatment
843
+ - **Expected Size:** ~5% of list
844
+ - **Owner:** Marketing Team
845
+ - **Created:** 2024-03-15
846
+
847
+ ## At Risk (ID: 457)
848
+ - **Rules:** No open 30-90 days AND Status = Subscribed
849
+ - **Purpose:** Re-engagement campaigns
850
+ - **Expected Size:** ~15-20% of list
851
+ - **Owner:** Retention Team
852
+ - **Created:** 2024-03-15
853
+ EOF
854
+ ```
855
+
856
+ ### 4. Monitor Segment Health
857
+
858
+ ```bash
859
+ #!/bin/bash
860
+ # monitor-segments.sh
861
+
862
+ LIST_ID=123
863
+
864
+ echo "=== Segment Health Check ==="
865
+ echo ""
866
+
867
+ SEGMENTS=$(cakemail segments list $LIST_ID -f json | jq -r '.data[].id')
868
+
869
+ for SEG_ID in $SEGMENTS; do
870
+ SEG=$(cakemail segments get $LIST_ID $SEG_ID -f json)
871
+ NAME=$(echo "$SEG" | jq -r '.name')
872
+ COUNT=$(echo "$SEG" | jq -r '.contact_count')
873
+
874
+ echo "$NAME (ID: $SEG_ID)"
875
+ echo " Contacts: $COUNT"
876
+
877
+ if [ $COUNT -eq 0 ]; then
878
+ echo " ⚠️ Empty segment - review conditions"
879
+ elif [ $COUNT -lt 10 ]; then
880
+ echo " ⚠️ Very small segment - may need adjustment"
881
+ else
882
+ echo " ✅ Healthy"
883
+ fi
884
+
885
+ echo ""
886
+ done
887
+ ```
888
+
889
+ ### 5. Test Before Large Sends
890
+
891
+ ```bash
892
+ # Create test segment (small sample)
893
+ $ cakemail segments create 123 -n "Test - Premium Users" -c '{
894
+ "match": "all",
895
+ "rules": [
896
+ {"field": "custom_attributes.plan", "operator": "equals", "value": "premium"},
897
+ {"field": "email", "operator": "contains", "value": "@yourcompany.com"}
898
+ ]
899
+ }'
900
+
901
+ # Send to test segment first
902
+ $ cakemail campaigns create -n "Test Campaign" -l 123 -s 101 --segment 456
903
+
904
+ # Review results
905
+ # Then send to full segment
906
+ ```
907
+
908
+ ## Troubleshooting
909
+
910
+ ### Segment Has Zero Contacts
911
+
912
+ **Problem:** Created segment but contact_count is 0
913
+
914
+ **Solutions:**
915
+ ```bash
916
+ # 1. Check segment conditions
917
+ $ cakemail segments get 123 456 -f json | jq '.conditions'
918
+
919
+ # 2. Test individual rules
920
+ # Try with just one rule to see if any contacts match
921
+ $ cakemail segments update 123 456 -c '{
922
+ "match": "all",
923
+ "rules": [
924
+ {"field": "status", "operator": "equals", "value": "subscribed"}
925
+ ]
926
+ }'
927
+
928
+ # 3. Check if contacts have required attributes
929
+ $ cakemail contacts get 123 501 -f json | jq '.custom_attributes'
930
+
931
+ # 4. Verify date format
932
+ # Use YYYY-MM-DD format
933
+ $ cakemail segments update 123 456 -c '{
934
+ "match": "all",
935
+ "rules": [
936
+ {"field": "last_open_date", "operator": "greater_than", "value": "2024-03-01"}
937
+ ]
938
+ }'
939
+ ```
940
+
941
+ ### Segment Larger Than Expected
942
+
943
+ **Problem:** Segment includes more contacts than anticipated
944
+
945
+ **Solutions:**
946
+ ```bash
947
+ # Preview contacts
948
+ $ cakemail segments contacts 123 456 -l 50
949
+
950
+ # Export for analysis
951
+ $ cakemail segments contacts 123 456 -f json > review.json
952
+
953
+ # Check specific contacts
954
+ $ jq '.data[] | {email, status, last_open_date, custom_attributes}' review.json
955
+
956
+ # Adjust conditions to be more restrictive
957
+ $ cakemail segments update 123 456 -c '{
958
+ "match": "all",
959
+ "rules": [
960
+ {"field": "status", "operator": "equals", "value": "subscribed"},
961
+ {"field": "last_open_date", "operator": "greater_than", "value": "2024-03-01"},
962
+ {"field": "last_click_date", "operator": "greater_than", "value": "2024-03-01"}
963
+ ]
964
+ }'
965
+ ```
966
+
967
+ ### Custom Attribute Rule Not Working
968
+
969
+ **Problem:** Rule on custom attribute not matching contacts
970
+
971
+ **Solutions:**
972
+ ```bash
973
+ # 1. Verify attribute exists
974
+ $ cakemail attributes list 123
975
+
976
+ # 2. Check exact attribute name
977
+ $ cakemail contacts get 123 501 -f json | jq '.custom_attributes | keys'
978
+
979
+ # 3. Use correct dot notation
980
+ # Correct:
981
+ {"field": "custom_attributes.plan_type", "operator": "equals", "value": "premium"}
982
+
983
+ # Wrong:
984
+ {"field": "plan_type", "operator": "equals", "value": "premium"}
985
+
986
+ # 4. Check value type (string vs number vs boolean)
987
+ # For numbers (no quotes):
988
+ {"field": "custom_attributes.age", "operator": "greater_than", "value": "25"}
989
+
990
+ # For booleans:
991
+ {"field": "custom_attributes.is_vip", "operator": "equals", "value": "true"}
992
+ ```
993
+
994
+ ### Date Comparison Not Working
995
+
996
+ **Problem:** Date-based rules not matching correctly
997
+
998
+ **Solutions:**
999
+ ```bash
1000
+ # Use ISO format (YYYY-MM-DD)
1001
+ {"field": "last_open_date", "operator": "greater_than", "value": "2024-03-01"}
1002
+
1003
+ # Not: "03/01/2024" or "March 1, 2024"
1004
+
1005
+ # For rolling dates, use script:
1006
+ THIRTY_DAYS_AGO=$(date -d "30 days ago" +%Y-%m-%d)
1007
+
1008
+ $ cakemail segments update 123 456 -c "{
1009
+ \"match\": \"all\",
1010
+ \"rules\": [
1011
+ {\"field\": \"last_open_date\", \"operator\": \"greater_than\", \"value\": \"$THIRTY_DAYS_AGO\"}
1012
+ ]
1013
+ }"
1014
+ ```
1015
+
1016
+ ## Best Practices Summary
1017
+
1018
+ 1. **Name descriptively** - Clear, specific segment names
1019
+ 2. **Start broad** - Begin with simple rules, narrow as needed
1020
+ 3. **Preview first** - Check contacts before sending campaigns
1021
+ 4. **Document segments** - Keep record of purpose and conditions
1022
+ 5. **Monitor size** - Track segment growth/shrinkage
1023
+ 6. **Test conditions** - Verify rules match expected contacts
1024
+ 7. **Use date-based rules** - Leverage dynamic date filtering
1025
+ 8. **Combine wisely** - Use "any" vs "all" appropriately
1026
+ 9. **Regular audits** - Review and clean unused segments
1027
+ 10. **Update dynamically** - Leverage automated condition updates
1028
+