@divyacon/piece-mailchimp 0.0.0-stage → 0.1.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 (148) hide show
  1. package/LICENSE.MIT-AP +24 -0
  2. package/dist/index.d.ts +3 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +80 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/lib/actions/add-member-to-list.d.ts +13 -0
  7. package/dist/lib/actions/add-member-to-list.d.ts.map +1 -0
  8. package/dist/lib/actions/add-member-to-list.js +172 -0
  9. package/dist/lib/actions/add-member-to-list.js.map +1 -0
  10. package/dist/lib/actions/add-note-to-subscriber.d.ts +6 -0
  11. package/dist/lib/actions/add-note-to-subscriber.d.ts.map +1 -0
  12. package/dist/lib/actions/add-note-to-subscriber.js +95 -0
  13. package/dist/lib/actions/add-note-to-subscriber.js.map +1 -0
  14. package/dist/lib/actions/add-subscriber-to-tag.d.ts +6 -0
  15. package/dist/lib/actions/add-subscriber-to-tag.d.ts.map +1 -0
  16. package/dist/lib/actions/add-subscriber-to-tag.js +65 -0
  17. package/dist/lib/actions/add-subscriber-to-tag.js.map +1 -0
  18. package/dist/lib/actions/archive-subscriber.d.ts +5 -0
  19. package/dist/lib/actions/archive-subscriber.d.ts.map +1 -0
  20. package/dist/lib/actions/archive-subscriber.js +66 -0
  21. package/dist/lib/actions/archive-subscriber.js.map +1 -0
  22. package/dist/lib/actions/create-audience.d.ts +23 -0
  23. package/dist/lib/actions/create-audience.d.ts.map +1 -0
  24. package/dist/lib/actions/create-audience.js +196 -0
  25. package/dist/lib/actions/create-audience.js.map +1 -0
  26. package/dist/lib/actions/create-campaign.d.ts +15 -0
  27. package/dist/lib/actions/create-campaign.d.ts.map +1 -0
  28. package/dist/lib/actions/create-campaign.js +157 -0
  29. package/dist/lib/actions/create-campaign.js.map +1 -0
  30. package/dist/lib/actions/create-custom-event.d.ts +7 -0
  31. package/dist/lib/actions/create-custom-event.d.ts.map +1 -0
  32. package/dist/lib/actions/create-custom-event.js +65 -0
  33. package/dist/lib/actions/create-custom-event.js.map +1 -0
  34. package/dist/lib/actions/create-tag.d.ts +5 -0
  35. package/dist/lib/actions/create-tag.d.ts.map +1 -0
  36. package/dist/lib/actions/create-tag.js +56 -0
  37. package/dist/lib/actions/create-tag.js.map +1 -0
  38. package/dist/lib/actions/find-campaign.d.ts +6 -0
  39. package/dist/lib/actions/find-campaign.d.ts.map +1 -0
  40. package/dist/lib/actions/find-campaign.js +70 -0
  41. package/dist/lib/actions/find-campaign.js.map +1 -0
  42. package/dist/lib/actions/find-customer.d.ts +9 -0
  43. package/dist/lib/actions/find-customer.d.ts.map +1 -0
  44. package/dist/lib/actions/find-customer.js +87 -0
  45. package/dist/lib/actions/find-customer.js.map +1 -0
  46. package/dist/lib/actions/find-subscriber.d.ts +7 -0
  47. package/dist/lib/actions/find-subscriber.d.ts.map +1 -0
  48. package/dist/lib/actions/find-subscriber.js +307 -0
  49. package/dist/lib/actions/find-subscriber.js.map +1 -0
  50. package/dist/lib/actions/find-tag.d.ts +5 -0
  51. package/dist/lib/actions/find-tag.d.ts.map +1 -0
  52. package/dist/lib/actions/find-tag.js +57 -0
  53. package/dist/lib/actions/find-tag.js.map +1 -0
  54. package/dist/lib/actions/get-campaign-report.d.ts +6 -0
  55. package/dist/lib/actions/get-campaign-report.d.ts.map +1 -0
  56. package/dist/lib/actions/get-campaign-report.js +206 -0
  57. package/dist/lib/actions/get-campaign-report.js.map +1 -0
  58. package/dist/lib/actions/remove-subscriber-from-tag.d.ts +6 -0
  59. package/dist/lib/actions/remove-subscriber-from-tag.d.ts.map +1 -0
  60. package/dist/lib/actions/remove-subscriber-from-tag.js +98 -0
  61. package/dist/lib/actions/remove-subscriber-from-tag.js.map +1 -0
  62. package/dist/lib/actions/send-campaign.d.ts +4 -0
  63. package/dist/lib/actions/send-campaign.d.ts.map +1 -0
  64. package/dist/lib/actions/send-campaign.js +47 -0
  65. package/dist/lib/actions/send-campaign.js.map +1 -0
  66. package/dist/lib/actions/unsubscribe-email.d.ts +8 -0
  67. package/dist/lib/actions/unsubscribe-email.d.ts.map +1 -0
  68. package/dist/lib/actions/unsubscribe-email.js +90 -0
  69. package/dist/lib/actions/unsubscribe-email.js.map +1 -0
  70. package/dist/lib/actions/update-subscriber-status.d.ts +6 -0
  71. package/dist/lib/actions/update-subscriber-status.d.ts.map +1 -0
  72. package/dist/lib/actions/update-subscriber-status.js +54 -0
  73. package/dist/lib/actions/update-subscriber-status.js.map +1 -0
  74. package/dist/lib/common/index.d.ts +30 -0
  75. package/dist/lib/common/index.d.ts.map +1 -0
  76. package/dist/lib/common/index.js +206 -0
  77. package/dist/lib/common/index.js.map +1 -0
  78. package/dist/lib/common/types.d.ts +362 -0
  79. package/dist/lib/common/types.d.ts.map +1 -0
  80. package/dist/lib/common/types.js +54 -0
  81. package/dist/lib/common/types.js.map +1 -0
  82. package/dist/lib/triggers/email-opened-trigger.d.ts +11 -0
  83. package/dist/lib/triggers/email-opened-trigger.d.ts.map +1 -0
  84. package/dist/lib/triggers/email-opened-trigger.js +199 -0
  85. package/dist/lib/triggers/email-opened-trigger.js.map +1 -0
  86. package/dist/lib/triggers/link-clicked-trigger.d.ts +11 -0
  87. package/dist/lib/triggers/link-clicked-trigger.d.ts.map +1 -0
  88. package/dist/lib/triggers/link-clicked-trigger.js +226 -0
  89. package/dist/lib/triggers/link-clicked-trigger.js.map +1 -0
  90. package/dist/lib/triggers/new-campaign-trigger.d.ts +11 -0
  91. package/dist/lib/triggers/new-campaign-trigger.d.ts.map +1 -0
  92. package/dist/lib/triggers/new-campaign-trigger.js +147 -0
  93. package/dist/lib/triggers/new-campaign-trigger.js.map +1 -0
  94. package/dist/lib/triggers/new-customer-trigger.d.ts +11 -0
  95. package/dist/lib/triggers/new-customer-trigger.d.ts.map +1 -0
  96. package/dist/lib/triggers/new-customer-trigger.js +214 -0
  97. package/dist/lib/triggers/new-customer-trigger.js.map +1 -0
  98. package/dist/lib/triggers/new-order-trigger.d.ts +11 -0
  99. package/dist/lib/triggers/new-order-trigger.d.ts.map +1 -0
  100. package/dist/lib/triggers/new-order-trigger.js +270 -0
  101. package/dist/lib/triggers/new-order-trigger.js.map +1 -0
  102. package/dist/lib/triggers/new-segment-tag-subscriber-trigger.d.ts +19 -0
  103. package/dist/lib/triggers/new-segment-tag-subscriber-trigger.d.ts.map +1 -0
  104. package/dist/lib/triggers/new-segment-tag-subscriber-trigger.js +264 -0
  105. package/dist/lib/triggers/new-segment-tag-subscriber-trigger.js.map +1 -0
  106. package/dist/lib/triggers/subscribe-trigger.d.ts +11 -0
  107. package/dist/lib/triggers/subscribe-trigger.d.ts.map +1 -0
  108. package/dist/lib/triggers/subscribe-trigger.js +150 -0
  109. package/dist/lib/triggers/subscribe-trigger.js.map +1 -0
  110. package/dist/lib/triggers/subscriber-updated-trigger.d.ts +11 -0
  111. package/dist/lib/triggers/subscriber-updated-trigger.d.ts.map +1 -0
  112. package/dist/lib/triggers/subscriber-updated-trigger.js +157 -0
  113. package/dist/lib/triggers/subscriber-updated-trigger.js.map +1 -0
  114. package/dist/lib/triggers/unsubscribe-trigger.d.ts +11 -0
  115. package/dist/lib/triggers/unsubscribe-trigger.d.ts.map +1 -0
  116. package/dist/lib/triggers/unsubscribe-trigger.js +196 -0
  117. package/dist/lib/triggers/unsubscribe-trigger.js.map +1 -0
  118. package/package.json +45 -3
  119. package/src/index.ts +77 -0
  120. package/src/lib/actions/add-member-to-list.ts +180 -0
  121. package/src/lib/actions/add-note-to-subscriber.ts +91 -0
  122. package/src/lib/actions/add-subscriber-to-tag.ts +66 -0
  123. package/src/lib/actions/archive-subscriber.ts +64 -0
  124. package/src/lib/actions/create-audience.ts +192 -0
  125. package/src/lib/actions/create-campaign.ts +155 -0
  126. package/src/lib/actions/create-custom-event.ts +63 -0
  127. package/src/lib/actions/create-tag.ts +51 -0
  128. package/src/lib/actions/find-campaign.ts +68 -0
  129. package/src/lib/actions/find-customer.ts +88 -0
  130. package/src/lib/actions/find-subscriber.ts +307 -0
  131. package/src/lib/actions/find-tag.ts +57 -0
  132. package/src/lib/actions/get-campaign-report.ts +204 -0
  133. package/src/lib/actions/remove-subscriber-from-tag.ts +94 -0
  134. package/src/lib/actions/send-campaign.ts +42 -0
  135. package/src/lib/actions/unsubscribe-email.ts +91 -0
  136. package/src/lib/actions/update-subscriber-status.ts +53 -0
  137. package/src/lib/common/index.ts +267 -0
  138. package/src/lib/common/types.ts +410 -0
  139. package/src/lib/triggers/email-opened-trigger.ts +216 -0
  140. package/src/lib/triggers/link-clicked-trigger.ts +244 -0
  141. package/src/lib/triggers/new-campaign-trigger.ts +149 -0
  142. package/src/lib/triggers/new-customer-trigger.ts +230 -0
  143. package/src/lib/triggers/new-order-trigger.ts +288 -0
  144. package/src/lib/triggers/new-segment-tag-subscriber-trigger.ts +286 -0
  145. package/src/lib/triggers/subscribe-trigger.ts +159 -0
  146. package/src/lib/triggers/subscriber-updated-trigger.ts +165 -0
  147. package/src/lib/triggers/unsubscribe-trigger.ts +212 -0
  148. package/README.md +0 -3
@@ -0,0 +1,244 @@
1
+ import { createTrigger, TriggerStrategy, Property } from '@agnocon/pieces-framework';
2
+ import { getAccessTokenOrThrow } from '@agnocon/pieces-common';
3
+ import { mailchimpCommon } from '../common';
4
+ import { MailChimpClickWebhookRequest } from '../common/types';
5
+ import { mailchimpAuth } from '../..';
6
+
7
+ const WEBHOOK_DATA_STORE_KEY = 'mail_chimp_link_clicked_webhook_data';
8
+
9
+ type WebhookData = {
10
+ id: string;
11
+ listId: string;
12
+ };
13
+
14
+ const getLinkClickEventSummary = (request: MailChimpClickWebhookRequest): any => {
15
+ const data = request.data || {};
16
+ return {
17
+ email: data.email || 'N/A',
18
+ subscriber_id: data.id || 'N/A',
19
+ list_id: data.list_id || 'N/A',
20
+ campaign_id: data.campaign_id || 'N/A',
21
+ url: data.url || 'N/A',
22
+ ip_address: data.ip || 'N/A',
23
+ user_agent: data.user_agent || 'N/A',
24
+ timestamp: data.timestamp || request.fired_at || 'N/A',
25
+ click_data: {
26
+ url: data.url || 'N/A',
27
+ link_id: data.link_id || 'N/A',
28
+ click_count: data.click_count || 1,
29
+ is_first_click: data.is_first_click || false,
30
+ },
31
+ location_data: extractLocationData(data),
32
+ device_info: extractDeviceInfo(data.user_agent),
33
+ engagement_metrics: calculateClickMetrics(data),
34
+ };
35
+ };
36
+
37
+ const extractLocationData = (data: any): any => {
38
+ return {
39
+ ip_address: data.ip || 'N/A',
40
+ country: data.country || 'N/A',
41
+ region: data.region || 'N/A',
42
+ city: data.city || 'N/A',
43
+ timezone: data.timezone || 'N/A',
44
+ latitude: data.latitude || 'N/A',
45
+ longitude: data.longitude || 'N/A',
46
+ };
47
+ };
48
+
49
+ const extractDeviceInfo = (userAgent: string): any => {
50
+ if (!userAgent) return { device_type: 'Unknown', browser: 'Unknown', os: 'Unknown' };
51
+
52
+ const isMobile = /Mobile|Android|iPhone|iPad|Windows Phone/i.test(userAgent);
53
+ const isTablet = /iPad|Android(?=.*\bMobile\b)(?=.*\bSafari\b)/i.test(userAgent);
54
+
55
+ let deviceType = 'Desktop';
56
+ if (isTablet) deviceType = 'Tablet';
57
+ else if (isMobile) deviceType = 'Mobile';
58
+
59
+ return {
60
+ device_type: deviceType,
61
+ user_agent: userAgent,
62
+ is_mobile: isMobile,
63
+ is_tablet: isTablet,
64
+ is_desktop: !isMobile && !isTablet,
65
+ };
66
+ };
67
+
68
+ const calculateClickMetrics = (data: any): any => {
69
+ return {
70
+ click_count: data.click_count || 1,
71
+ is_first_click: data.is_first_click || false,
72
+ click_rate: data.click_rate || 0,
73
+ engagement_score: data.member_rating || 0,
74
+ vip_status: data.vip || false,
75
+ link_engagement: data.url ? 'High' : 'Low',
76
+ };
77
+ };
78
+
79
+ const assessClickEngagementLevel = (data: any): string => {
80
+ const rating = data.member_rating || 0;
81
+ const isVip = data.vip || false;
82
+ const clickCount = data.click_count || 1;
83
+
84
+ if (isVip || rating >= 4) return 'High';
85
+ if (rating >= 2 || clickCount > 1) return 'Medium';
86
+ return 'Low';
87
+ };
88
+
89
+ const identifyClickAutomationOpportunities = (data: any): string[] => {
90
+ const opportunities = [];
91
+
92
+ if (data.is_first_click) {
93
+ opportunities.push('First-time clicker - conversion funnel opportunity');
94
+ }
95
+
96
+ if (data.member_rating && data.member_rating >= 4) {
97
+ opportunities.push('High engagement - product recommendation opportunity');
98
+ }
99
+
100
+ if (data.vip) {
101
+ opportunities.push('VIP subscriber - exclusive offer opportunity');
102
+ }
103
+
104
+ if (data.url && data.url.includes('product')) {
105
+ opportunities.push('Product page click - purchase intent opportunity');
106
+ }
107
+
108
+ return opportunities.length > 0 ? opportunities : ['Standard click tracking'];
109
+ };
110
+
111
+ const assessConversionPotential = (data: any): string => {
112
+ if (data.url?.includes('product') || data.url?.includes('shop')) {
113
+ return 'High - Product page engagement';
114
+ }
115
+ if (data.url?.includes('checkout') || data.url?.includes('cart')) {
116
+ return 'Very High - Purchase intent';
117
+ }
118
+ if (data.url?.includes('signup') || data.url?.includes('register')) {
119
+ return 'High - Registration intent';
120
+ }
121
+ return 'Medium - General engagement';
122
+ };
123
+
124
+ export const mailChimpLinkClickedTrigger = createTrigger({
125
+ auth: mailchimpAuth,
126
+ name: 'link_clicked',
127
+ displayName: 'Link Clicked',
128
+ description: 'Fires when a recipient clicks a specified link in a campaign',
129
+ aiMetadata: {
130
+ description: 'Fires when a recipient in the selected audience (list) clicks a link in a campaign email. The event carries the subscriber email, campaign id, clicked URL, and client/location metadata.',
131
+ },
132
+ type: TriggerStrategy.WEBHOOK,
133
+ props: {
134
+ list_id: mailchimpCommon.mailChimpListIdDropdown,
135
+ },
136
+ sampleData: {
137
+ type: 'click',
138
+ fired_at: '2024-01-15T10:30:00Z',
139
+ data: {
140
+ id: '8a25ff1d98',
141
+ list_id: 'a6b5da1054',
142
+ campaign_id: 'campaign_123',
143
+ email: 'user@example.com',
144
+ url: 'https://example.com/product-page',
145
+ link_id: 'link_456',
146
+ ip: '192.168.1.100',
147
+ user_agent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
148
+ timestamp: '2024-01-15T10:30:00Z',
149
+ click_count: 1,
150
+ is_first_click: true,
151
+ click_rate: 0.25,
152
+ member_rating: 4,
153
+ vip: false,
154
+ country: 'US',
155
+ region: 'CA',
156
+ city: 'San Francisco',
157
+ timezone: 'America/Los_Angeles',
158
+ latitude: 37.7749,
159
+ longitude: -122.4194,
160
+ },
161
+ },
162
+
163
+ async onEnable(context): Promise<void> {
164
+ try {
165
+ const accessToken = getAccessTokenOrThrow(context.auth);
166
+ const server = await mailchimpCommon.getMailChimpServerPrefix(accessToken);
167
+
168
+ const enabledWebhookId = await mailchimpCommon.enableWebhookRequest({
169
+ server,
170
+ listId: context.propsValue.list_id as string,
171
+ token: accessToken,
172
+ webhookUrl: context.webhookUrl!,
173
+ events: {
174
+ click: true,
175
+ },
176
+ });
177
+
178
+ await context.store?.put<WebhookData>(WEBHOOK_DATA_STORE_KEY, {
179
+ id: enabledWebhookId,
180
+ listId: context.propsValue.list_id as string,
181
+ });
182
+ } catch (error: any) {
183
+ throw new Error(`Failed to enable link clicked webhook: ${error.message || JSON.stringify(error)}`);
184
+ }
185
+ },
186
+
187
+ async onDisable(context): Promise<void> {
188
+ try {
189
+ const webhookData = await context.store?.get<WebhookData>(WEBHOOK_DATA_STORE_KEY);
190
+
191
+ if (webhookData === undefined || webhookData === null) {
192
+ return;
193
+ }
194
+
195
+ const token = getAccessTokenOrThrow(context.auth);
196
+ const server = await mailchimpCommon.getMailChimpServerPrefix(token);
197
+
198
+ await mailchimpCommon.disableWebhookRequest({
199
+ server,
200
+ token,
201
+ listId: webhookData.listId,
202
+ webhookId: webhookData.id,
203
+ });
204
+ } catch (error: any) {
205
+ console.error(`Failed to disable link clicked webhook: ${error.message || JSON.stringify(error)}`);
206
+ }
207
+ },
208
+
209
+ async run(context): Promise<unknown[]> {
210
+ try {
211
+ const request = context.payload.body as MailChimpClickWebhookRequest;
212
+
213
+ if (!request || request.type !== 'click') {
214
+ return [];
215
+ }
216
+
217
+ const enhancedRequest = {
218
+ ...request,
219
+ trigger_type: 'link_clicked',
220
+ event_category: 'Link Engagement',
221
+ processed_at: new Date().toISOString(),
222
+ click_summary: getLinkClickEventSummary(request),
223
+ business_context: {
224
+ link_engagement: true,
225
+ conversion_tracking: true,
226
+ subscriber_behavior: true,
227
+ automation_trigger: true,
228
+ },
229
+ click_insights: {
230
+ device_type: extractDeviceInfo(request.data?.user_agent).device_type,
231
+ location: extractLocationData(request.data),
232
+ engagement_level: assessClickEngagementLevel(request.data),
233
+ automation_potential: identifyClickAutomationOpportunities(request.data),
234
+ conversion_opportunity: assessConversionPotential(request.data),
235
+ },
236
+ };
237
+
238
+ return [enhancedRequest];
239
+ } catch (error: any) {
240
+ console.error(`Error processing link clicked webhook: ${error.message || JSON.stringify(error)}`);
241
+ return [];
242
+ }
243
+ },
244
+ });
@@ -0,0 +1,149 @@
1
+ import { createTrigger, TriggerStrategy, Property } from '@agnocon/pieces-framework';
2
+ import { getAccessTokenOrThrow } from '@agnocon/pieces-common';
3
+ import { mailchimpCommon } from '../common';
4
+ import { MailChimpCampaignWebhookRequest } from '../common/types';
5
+ import { mailchimpAuth } from '../..';
6
+
7
+ const WEBHOOK_DATA_STORE_KEY = 'mail_chimp_campaign_webhook_data';
8
+
9
+ type WebhookData = {
10
+ id: string;
11
+ listId: string;
12
+ };
13
+
14
+ const getCampaignEventSummary = (request: MailChimpCampaignWebhookRequest): any => {
15
+ const data = request.data;
16
+ return {
17
+ campaign_id: data.campaign_id,
18
+ campaign_title: data.campaign_title,
19
+ campaign_subject: data.campaign_subject,
20
+ campaign_send_time: data.campaign_send_time,
21
+ campaign_status: data.campaign_status,
22
+ list_id: data.list_id,
23
+ subscriber_id: data.id,
24
+ event_timestamp: request.fired_at,
25
+ campaign_type: inferCampaignType(data),
26
+ delivery_status: assessDeliveryStatus(data),
27
+ };
28
+ };
29
+
30
+ const inferCampaignType = (data: any): string => {
31
+ if (data.campaign_title?.toLowerCase().includes('welcome')) return 'Welcome Series';
32
+ if (data.campaign_title?.toLowerCase().includes('newsletter')) return 'Newsletter';
33
+ if (data.campaign_title?.toLowerCase().includes('promo')) return 'Promotional';
34
+ if (data.campaign_title?.toLowerCase().includes('abandoned')) return 'Abandoned Cart';
35
+ return 'Standard Campaign';
36
+ };
37
+
38
+ const assessDeliveryStatus = (data: any): string => {
39
+ const status = data.campaign_status || '';
40
+ if (status === 'sent') return 'Delivered';
41
+ if (status === 'sending') return 'In Progress';
42
+ if (status === 'scheduled') return 'Scheduled';
43
+ if (status === 'paused') return 'Paused';
44
+ if (status === 'canceled') return 'Canceled';
45
+ return 'Unknown';
46
+ };
47
+
48
+ // Note: Campaign webhook data doesn't include performance metrics
49
+ // These would need to be fetched separately via the campaigns API if needed
50
+
51
+ export const mailChimpNewCampaignTrigger = createTrigger({
52
+ auth: mailchimpAuth,
53
+ name: 'new_campaign',
54
+ displayName: 'New Campaign',
55
+ description: 'Fires when a new campaign is created or sent',
56
+ aiMetadata: {
57
+ description: 'Fires on a campaign event tied to the selected audience (list) — when a campaign is created or sent. The event carries the campaign id, title, subject, send time, and status.',
58
+ },
59
+ type: TriggerStrategy.WEBHOOK,
60
+ props: {
61
+ list_id: mailchimpCommon.mailChimpListIdDropdown,
62
+ },
63
+ sampleData: {
64
+ type: 'campaign',
65
+ fired_at: '2024-01-15T10:30:00Z',
66
+ data: {
67
+ id: '8a25ff1d98',
68
+ list_id: 'a6b5da1054',
69
+ campaign_id: 'campaign_123',
70
+ campaign_title: 'Welcome Campaign',
71
+ campaign_subject: 'Welcome to our newsletter',
72
+ campaign_send_time: '2024-01-15T10:30:00Z',
73
+ campaign_status: 'sent',
74
+ },
75
+ },
76
+
77
+ async onEnable(context): Promise<void> {
78
+ try {
79
+ const accessToken = getAccessTokenOrThrow(context.auth);
80
+ const server = await mailchimpCommon.getMailChimpServerPrefix(accessToken);
81
+
82
+ const enabledWebhookId = await mailchimpCommon.enableWebhookRequest({
83
+ server,
84
+ listId: context.propsValue.list_id as string,
85
+ token: accessToken,
86
+ webhookUrl: context.webhookUrl!,
87
+ events: {
88
+ campaign: true,
89
+ },
90
+ });
91
+
92
+ await context.store?.put<WebhookData>(WEBHOOK_DATA_STORE_KEY, {
93
+ id: enabledWebhookId,
94
+ listId: context.propsValue.list_id as string,
95
+ });
96
+ } catch (error: any) {
97
+ throw new Error(`Failed to enable campaign webhook: ${error.message || JSON.stringify(error)}`);
98
+ }
99
+ },
100
+
101
+ async onDisable(context): Promise<void> {
102
+ try {
103
+ const webhookData = await context.store?.get<WebhookData>(WEBHOOK_DATA_STORE_KEY);
104
+
105
+ if (webhookData === undefined || webhookData === null) {
106
+ return;
107
+ }
108
+
109
+ const token = getAccessTokenOrThrow(context.auth);
110
+ const server = await mailchimpCommon.getMailChimpServerPrefix(token);
111
+
112
+ await mailchimpCommon.disableWebhookRequest({
113
+ server,
114
+ token,
115
+ listId: webhookData.listId,
116
+ webhookId: webhookData.id,
117
+ });
118
+ } catch (error: any) {
119
+ console.error(`Failed to disable campaign webhook: ${error.message || JSON.stringify(error)}`);
120
+ }
121
+ },
122
+
123
+ async run(context): Promise<unknown[]> {
124
+ try {
125
+ const request = context.payload.body as MailChimpCampaignWebhookRequest;
126
+
127
+ if (!request || request.type !== 'campaign') {
128
+ return [];
129
+ }
130
+
131
+ const enhancedRequest = {
132
+ ...request,
133
+ trigger_type: 'campaign_event',
134
+ event_category: 'Campaign Activity',
135
+ processed_at: new Date().toISOString(),
136
+ campaign_summary: getCampaignEventSummary(request),
137
+ campaign_insights: {
138
+ campaign_type: inferCampaignType(request.data),
139
+ delivery_status: assessDeliveryStatus(request.data),
140
+ },
141
+ };
142
+
143
+ return [enhancedRequest];
144
+ } catch (error: any) {
145
+ console.error(`Error processing campaign webhook: ${error.message || JSON.stringify(error)}`);
146
+ return [];
147
+ }
148
+ },
149
+ });
@@ -0,0 +1,230 @@
1
+ import { createTrigger, TriggerStrategy, Property } from '@agnocon/pieces-framework';
2
+ import { getAccessTokenOrThrow } from '@agnocon/pieces-common';
3
+ import { mailchimpCommon } from '../common';
4
+ import { mailchimpAuth } from '../..';
5
+
6
+ const WEBHOOK_DATA_STORE_KEY = 'mail_chimp_new_customer_webhook_data';
7
+
8
+ type WebhookData = {
9
+ id: string;
10
+ listId: string;
11
+ };
12
+
13
+ const getNewCustomerEventSummary = (request: any): any => {
14
+ const data = request.data || {};
15
+ return {
16
+ customer_id: data.customer_id || data.id || 'N/A',
17
+ store_id: data.store_id || 'N/A',
18
+ email: data.email || 'N/A',
19
+ first_name: data.first_name || 'N/A',
20
+ last_name: data.last_name || 'N/A',
21
+ company: data.company || 'N/A',
22
+ phone: data.phone || 'N/A',
23
+ address: data.address || 'N/A',
24
+ created_at: data.created_at || request.fired_at || 'N/A',
25
+ customer_type: data.customer_type || 'new',
26
+ has_orders: data.orders_count > 0,
27
+ total_spent: data.total_spent || 0,
28
+ orders_count: data.orders_count || 0,
29
+ };
30
+ };
31
+
32
+ const extractCustomerAddress = (address: any): any => {
33
+ if (!address) return null;
34
+
35
+ return {
36
+ street_address: {
37
+ primary: address.address1 || 'N/A',
38
+ secondary: address.address2 || 'N/A',
39
+ },
40
+ city: address.city || 'N/A',
41
+ state_province: {
42
+ name: address.province || 'N/A',
43
+ code: address.province_code || 'N/A',
44
+ },
45
+ postal_code: address.postal_code || 'N/A',
46
+ country: {
47
+ name: address.country || 'N/A',
48
+ code: address.country_code || 'N/A',
49
+ },
50
+ full_address: [
51
+ address.address1,
52
+ address.address2,
53
+ address.city,
54
+ address.province,
55
+ address.postal_code,
56
+ address.country,
57
+ ].filter(Boolean).join(', '),
58
+ };
59
+ };
60
+
61
+ const assessCustomerValue = (data: any): string => {
62
+ const totalSpent = data.total_spent || 0;
63
+ const ordersCount = data.orders_count || 0;
64
+
65
+ if (totalSpent >= 1000 || ordersCount >= 10) return 'High Value';
66
+ if (totalSpent >= 100 || ordersCount >= 3) return 'Medium Value';
67
+ return 'New Customer';
68
+ };
69
+
70
+ const identifyCustomerOpportunities = (data: any): string[] => {
71
+ const opportunities = [];
72
+
73
+ if (data.orders_count === 0) {
74
+ opportunities.push('First-time customer - welcome series opportunity');
75
+ }
76
+
77
+ if (data.total_spent > 0) {
78
+ opportunities.push('Returning customer - loyalty program opportunity');
79
+ }
80
+
81
+ if (data.company) {
82
+ opportunities.push('Business customer - B2B marketing opportunity');
83
+ }
84
+
85
+ if (data.address) {
86
+ opportunities.push('Geographic targeting opportunity');
87
+ }
88
+
89
+ return opportunities.length > 0 ? opportunities : ['Standard customer onboarding'];
90
+ };
91
+
92
+ const assessMarketingPotential = (data: any): string => {
93
+ if (data.opt_in_status && data.member_rating >= 4) {
94
+ return 'High - Opted in with high engagement';
95
+ }
96
+ if (data.opt_in_status) {
97
+ return 'Medium - Opted in for marketing';
98
+ }
99
+ if (data.company) {
100
+ return 'Medium - Business customer potential';
101
+ }
102
+ return 'Low - Limited marketing consent';
103
+ };
104
+
105
+ export const mailChimpNewCustomerTrigger = createTrigger({
106
+ auth: mailchimpAuth,
107
+ name: 'new_customer',
108
+ displayName: 'New Customer',
109
+ description: 'Fires when a new customer is added to a connected store',
110
+ aiMetadata: {
111
+ description: 'Fires when a new e-commerce customer is added to a connected Mailchimp store. The event carries the customer id, email, name, and store/order context.',
112
+ },
113
+ type: TriggerStrategy.WEBHOOK,
114
+ props: {
115
+ list_id: mailchimpCommon.mailChimpListIdDropdown,
116
+ },
117
+ sampleData: {
118
+ type: 'customer',
119
+ fired_at: '2024-01-15T10:30:00Z',
120
+ data: {
121
+ id: 'customer_123',
122
+ customer_id: 'customer_123',
123
+ store_id: 'store_456',
124
+ email: 'customer@example.com',
125
+ first_name: 'John',
126
+ last_name: 'Doe',
127
+ company: 'Example Corp',
128
+ phone: '+1-555-0123',
129
+ address: {
130
+ address1: '123 Main St',
131
+ address2: 'Suite 100',
132
+ city: 'Anytown',
133
+ province: 'California',
134
+ province_code: 'CA',
135
+ postal_code: '12345',
136
+ country: 'United States',
137
+ country_code: 'US',
138
+ },
139
+ created_at: '2024-01-15T10:30:00Z',
140
+ customer_type: 'new',
141
+ orders_count: 0,
142
+ total_spent: 0,
143
+ opt_in_status: true,
144
+ tags: ['new-customer', 'ecommerce'],
145
+ member_rating: 5,
146
+ vip: false,
147
+ },
148
+ },
149
+
150
+ async onEnable(context): Promise<void> {
151
+ try {
152
+ const accessToken = getAccessTokenOrThrow(context.auth);
153
+ const server = await mailchimpCommon.getMailChimpServerPrefix(accessToken);
154
+
155
+ const enabledWebhookId = await mailchimpCommon.enableWebhookRequest({
156
+ server,
157
+ listId: context.propsValue.list_id as string,
158
+ token: accessToken,
159
+ webhookUrl: context.webhookUrl!,
160
+ events: {
161
+ customer: true,
162
+ },
163
+ });
164
+
165
+ await context.store?.put<WebhookData>(WEBHOOK_DATA_STORE_KEY, {
166
+ id: enabledWebhookId,
167
+ listId: context.propsValue.list_id as string,
168
+ });
169
+ } catch (error: any) {
170
+ throw new Error(`Failed to enable new customer webhook: ${error.message || JSON.stringify(error)}`);
171
+ }
172
+ },
173
+
174
+ async onDisable(context): Promise<void> {
175
+ try {
176
+ const webhookData = await context.store?.get<WebhookData>(WEBHOOK_DATA_STORE_KEY);
177
+
178
+ if (webhookData === undefined || webhookData === null) {
179
+ return;
180
+ }
181
+
182
+ const token = getAccessTokenOrThrow(context.auth);
183
+ const server = await mailchimpCommon.getMailChimpServerPrefix(token);
184
+
185
+ await mailchimpCommon.disableWebhookRequest({
186
+ server,
187
+ token,
188
+ listId: webhookData.listId,
189
+ webhookId: webhookData.id,
190
+ });
191
+ } catch (error: any) {
192
+ console.error(`Failed to disable new customer webhook: ${error.message || JSON.stringify(error)}`);
193
+ }
194
+ },
195
+
196
+ async run(context): Promise<unknown[]> {
197
+ try {
198
+ const request = context.payload.body as any;
199
+
200
+ if (!request || request.type !== 'customer') {
201
+ return [];
202
+ }
203
+
204
+ const enhancedRequest = {
205
+ ...request,
206
+ trigger_type: 'new_customer',
207
+ event_category: 'Customer Registration',
208
+ processed_at: new Date().toISOString(),
209
+ customer_summary: getNewCustomerEventSummary(request),
210
+ business_context: {
211
+ customer_acquisition: true,
212
+ ecommerce_tracking: true,
213
+ onboarding_automation: true,
214
+ customer_segmentation: true,
215
+ },
216
+ customer_insights: {
217
+ customer_value: assessCustomerValue(request.data),
218
+ address_details: extractCustomerAddress(request.data?.address),
219
+ automation_opportunities: identifyCustomerOpportunities(request.data),
220
+ marketing_potential: assessMarketingPotential(request.data),
221
+ },
222
+ };
223
+
224
+ return [enhancedRequest];
225
+ } catch (error: any) {
226
+ console.error(`Error processing new customer webhook: ${error.message || JSON.stringify(error)}`);
227
+ return [];
228
+ }
229
+ },
230
+ });