@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,159 @@
1
+ import { createTrigger, TriggerStrategy, Property } from '@agnocon/pieces-framework';
2
+ import { getAccessTokenOrThrow } from '@agnocon/pieces-common';
3
+ import { mailchimpCommon } from '../common';
4
+ import { MailChimpSubscribeWebhookRequest } from '../common/types';
5
+ import { mailchimpAuth } from '../..';
6
+
7
+ const WEBHOOK_DATA_STORE_KEY = 'mail_chimp_subscribe_webhook_data';
8
+
9
+ type WebhookData = {
10
+ id: string;
11
+ listId: string;
12
+ };
13
+
14
+ const getSubscribeEventSummary = (request: any): 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
+ email_type: data.email_type || 'html',
21
+ ip_address: data.ip_opt || data.ip_signup || 'N/A',
22
+ signup_timestamp: data.timestamp_signup || 'N/A',
23
+ opt_in_timestamp: data.timestamp_opt || 'N/A',
24
+ has_merge_fields: !!data.merges,
25
+ merge_field_count: data.merges ? Object.keys(data.merges).length : 0,
26
+ merge_fields_summary: data.merges ? {
27
+ first_name: data.merges.FNAME || 'N/A',
28
+ last_name: data.merges.LNAME || 'N/A',
29
+ company: data.merges.COMPANY || 'N/A',
30
+ phone: data.merges.PHONE || 'N/A',
31
+ interests: data.merges.INTERESTS || 'N/A',
32
+ has_address: !!data.merges.ADDRESS,
33
+ } : null,
34
+ };
35
+ };
36
+
37
+ export const mailChimpSubscribeTrigger = createTrigger({
38
+ auth: mailchimpAuth,
39
+ name: 'subscribe',
40
+ displayName: 'Member Subscribed to Audience',
41
+ description: 'Fires when a new subscriber joins your Mailchimp audience. This trigger captures new subscriptions, opt-ins, and audience growth events with comprehensive subscriber information.',
42
+ aiMetadata: {
43
+ description: 'Fires when a contact subscribes (opts in) to the selected Mailchimp audience (list), representing a new or re-activated subscriber. The event carries the subscriber email, merge fields, and signup metadata.',
44
+ },
45
+ type: TriggerStrategy.WEBHOOK,
46
+ props: {
47
+ list_id: mailchimpCommon.mailChimpListIdDropdown,
48
+ },
49
+ sampleData: {
50
+ type: 'subscribe',
51
+ fired_at: '2024-01-15T10:30:00Z',
52
+ data: {
53
+ id: '8a25ff1d98',
54
+ list_id: 'a6b5da1054',
55
+ email: 'api@mailchimp.com',
56
+ email_type: 'html',
57
+ ip_opt: '192.168.1.100',
58
+ ip_signup: '192.168.1.100',
59
+ timestamp_signup: '2024-01-15T10:30:00Z',
60
+ timestamp_opt: '2024-01-15T10:30:00Z',
61
+ merges: {
62
+ EMAIL: 'api@mailchimp.com',
63
+ FNAME: 'Mailchimp',
64
+ LNAME: 'API',
65
+ COMPANY: 'Mailchimp Inc',
66
+ PHONE: '+1-555-0123',
67
+ INTERESTS: 'Group1,Group2',
68
+ ADDRESS: {
69
+ addr1: '675 Ponce de Leon Ave NE',
70
+ addr2: 'Suite 5000',
71
+ city: 'Atlanta',
72
+ state: 'GA',
73
+ zip: '30308',
74
+ country: 'US',
75
+ },
76
+ },
77
+ member_rating: 5,
78
+ vip: false,
79
+ language: 'en',
80
+ source: 'api',
81
+ tags: ['api-signup', 'new-subscriber'],
82
+ },
83
+ },
84
+
85
+ async onEnable(context): Promise<void> {
86
+ try {
87
+ const accessToken = getAccessTokenOrThrow(context.auth);
88
+ const server = await mailchimpCommon.getMailChimpServerPrefix(accessToken);
89
+
90
+ const enabledWebhookId = await mailchimpCommon.enableWebhookRequest({
91
+ server,
92
+ listId: context.propsValue.list_id as string,
93
+ token: accessToken,
94
+ webhookUrl: context.webhookUrl!,
95
+ events: {
96
+ subscribe: true,
97
+ },
98
+ });
99
+
100
+ await context.store?.put<WebhookData>(WEBHOOK_DATA_STORE_KEY, {
101
+ id: enabledWebhookId,
102
+ listId: context.propsValue.list_id as string,
103
+ });
104
+ } catch (error: any) {
105
+ throw new Error(`Failed to enable subscribe webhook: ${error.message || JSON.stringify(error)}`);
106
+ }
107
+ },
108
+
109
+ async onDisable(context): Promise<void> {
110
+ try {
111
+ const webhookData = await context.store?.get<WebhookData>(WEBHOOK_DATA_STORE_KEY);
112
+
113
+ if (webhookData === undefined || webhookData === null) {
114
+ return;
115
+ }
116
+
117
+ const token = getAccessTokenOrThrow(context.auth);
118
+ const server = await mailchimpCommon.getMailChimpServerPrefix(token);
119
+
120
+ await mailchimpCommon.disableWebhookRequest({
121
+ server,
122
+ token,
123
+ listId: webhookData.listId,
124
+ webhookId: webhookData.id,
125
+ });
126
+ } catch (error: any) {
127
+ console.error(`Failed to disable subscribe webhook: ${error.message || JSON.stringify(error)}`);
128
+ }
129
+ },
130
+
131
+ async run(context): Promise<unknown[]> {
132
+ try {
133
+ const request = context.payload.body as MailChimpSubscribeWebhookRequest;
134
+
135
+ if (!request || request.type !== 'subscribe') {
136
+ return [];
137
+ }
138
+
139
+ const enhancedRequest = {
140
+ ...request,
141
+ trigger_type: 'member_subscribed',
142
+ event_category: 'New Subscription',
143
+ processed_at: new Date().toISOString(),
144
+ subscription_summary: getSubscribeEventSummary(request),
145
+ business_context: {
146
+ audience_growth: true,
147
+ new_lead: true,
148
+ marketing_opportunity: true,
149
+ engagement_potential: 'high',
150
+ },
151
+ };
152
+
153
+ return [enhancedRequest];
154
+ } catch (error: any) {
155
+ console.error(`Error processing subscribe webhook: ${error.message || JSON.stringify(error)}`);
156
+ return [];
157
+ }
158
+ },
159
+ });
@@ -0,0 +1,165 @@
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_subscriber_updated_webhook_data';
7
+
8
+ type WebhookData = {
9
+ id: string;
10
+ listId: string;
11
+ };
12
+
13
+ const getEventCategory = (eventType: string): string => {
14
+ switch (eventType) {
15
+ case 'profile':
16
+ return 'Profile Update';
17
+ case 'subscribe':
18
+ return 'New Subscription';
19
+ case 'upemail':
20
+ return 'Email Change';
21
+ case 'cleaned':
22
+ return 'Email Cleanup';
23
+ default:
24
+ return 'Unknown Event';
25
+ }
26
+ };
27
+
28
+ const getSubscriberSummary = (request: any): any => {
29
+ const data = request.data || {};
30
+ return {
31
+ email: data.email || data.new_email || 'N/A',
32
+ subscriber_id: data.id || 'N/A',
33
+ list_id: data.list_id || 'N/A',
34
+ email_type: data.email_type || 'html',
35
+ member_rating: data.member_rating || 0,
36
+ vip_status: data.vip ? 'VIP' : 'Standard',
37
+ language: data.language || 'en',
38
+ has_merge_fields: !!data.merges,
39
+ merge_field_count: data.merges ? Object.keys(data.merges).length : 0,
40
+ last_activity: data.last_changed || data.timestamp_opt || data.timestamp_signup || 'N/A',
41
+ ip_address: data.ip_opt || data.ip_signup || 'N/A',
42
+ };
43
+ };
44
+
45
+ export const mailChimpSubscriberUpdatedTrigger = createTrigger({
46
+ auth: mailchimpAuth,
47
+ name: 'subscriber_updated',
48
+ displayName: 'Subscriber Updated',
49
+ description: 'Fires when a subscriber profile is updated, including changes to merge fields, interests, or contact information. This trigger captures profile updates, new subscriptions, and subscriber modifications.',
50
+ aiMetadata: {
51
+ description: 'Fires on subscriber-record changes in the selected audience (list) — covering profile/merge-field updates, new subscriptions, email-address changes, and cleaned addresses. The event carries the subscriber email, merge fields, and (for email changes) the old and new addresses.',
52
+ },
53
+ type: TriggerStrategy.WEBHOOK,
54
+ props: {
55
+ list_id: mailchimpCommon.mailChimpListIdDropdown,
56
+ },
57
+ sampleData: {
58
+ type: 'profile',
59
+ fired_at: '2024-01-15T10:30:00Z',
60
+ data: {
61
+ id: '8a25ff1d98',
62
+ list_id: 'a6b5da1054',
63
+ email: 'user@example.com',
64
+ email_type: 'html',
65
+ merges: {
66
+ EMAIL: 'user@example.com',
67
+ FNAME: 'John',
68
+ LNAME: 'Doe',
69
+ COMPANY: 'Example Corp',
70
+ PHONE: '+1-555-0123',
71
+ INTERESTS: 'Group1,Group2',
72
+ ADDRESS: {
73
+ addr1: '123 Main St',
74
+ addr2: 'Suite 100',
75
+ city: 'Anytown',
76
+ state: 'CA',
77
+ zip: '12345',
78
+ country: 'US',
79
+ },
80
+ },
81
+ new_email: 'newuser@example.com',
82
+ old_email: 'user@example.com',
83
+ member_rating: 5,
84
+ vip: false,
85
+ language: 'en',
86
+ ip_opt: '192.168.1.100',
87
+ ip_signup: '192.168.1.100',
88
+ timestamp_signup: '2024-01-01T09:00:00Z',
89
+ timestamp_opt: '2024-01-01T09:00:00Z',
90
+ last_changed: '2024-01-15T10:30:00Z',
91
+ },
92
+ },
93
+
94
+ async onEnable(context): Promise<void> {
95
+ try {
96
+ const accessToken = getAccessTokenOrThrow(context.auth);
97
+ const server = await mailchimpCommon.getMailChimpServerPrefix(accessToken);
98
+
99
+ const enabledWebhookId = await mailchimpCommon.enableWebhookRequest({
100
+ server,
101
+ listId: context.propsValue.list_id as string,
102
+ token: accessToken,
103
+ webhookUrl: context.webhookUrl!,
104
+ events: {
105
+ profile: true,
106
+ subscribe: true,
107
+ upemail: true,
108
+ cleaned: true,
109
+ },
110
+ });
111
+
112
+ await context.store?.put<WebhookData>(WEBHOOK_DATA_STORE_KEY, {
113
+ id: enabledWebhookId,
114
+ listId: context.propsValue.list_id as string,
115
+ });
116
+ } catch (error: any) {
117
+ throw new Error(`Failed to enable subscriber updated webhook: ${error.message || JSON.stringify(error)}`);
118
+ }
119
+ },
120
+
121
+ async onDisable(context): Promise<void> {
122
+ try {
123
+ const webhookData = await context.store?.get<WebhookData>(WEBHOOK_DATA_STORE_KEY);
124
+
125
+ if (webhookData === undefined || webhookData === null) {
126
+ return;
127
+ }
128
+
129
+ const token = getAccessTokenOrThrow(context.auth);
130
+ const server = await mailchimpCommon.getMailChimpServerPrefix(token);
131
+
132
+ await mailchimpCommon.disableWebhookRequest({
133
+ server,
134
+ token,
135
+ listId: webhookData.listId,
136
+ webhookId: webhookData.id,
137
+ });
138
+ } catch (error: any) {
139
+ console.error(`Failed to disable subscriber updated webhook: ${error.message || JSON.stringify(error)}`);
140
+ }
141
+ },
142
+
143
+ async run(context): Promise<unknown[]> {
144
+ try {
145
+ const request = context.payload.body as any;
146
+
147
+ if (request === undefined || !['profile', 'subscribe', 'upemail', 'cleaned'].includes(request.type)) {
148
+ return [];
149
+ }
150
+
151
+ const enhancedRequest = {
152
+ ...request,
153
+ trigger_type: 'subscriber_updated',
154
+ event_category: getEventCategory(request.type),
155
+ processed_at: new Date().toISOString(),
156
+ subscriber_summary: getSubscriberSummary(request),
157
+ };
158
+
159
+ return [enhancedRequest];
160
+ } catch (error: any) {
161
+ console.error(`Error processing subscriber updated webhook: ${error.message || JSON.stringify(error)}`);
162
+ return [];
163
+ }
164
+ },
165
+ });
@@ -0,0 +1,212 @@
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_unsubscribe_webhook_data';
7
+
8
+ type WebhookData = {
9
+ id: string;
10
+ listId: string;
11
+ };
12
+
13
+ const getUnsubscribeEventSummary = (request: any): any => {
14
+ const data = request.data || {};
15
+ return {
16
+ email: data.email || 'N/A',
17
+ subscriber_id: data.id || 'N/A',
18
+ list_id: data.list_id || 'N/A',
19
+ email_type: data.email_type || 'html',
20
+ ip_address: data.ip_opt || data.ip_signup || 'N/A',
21
+ signup_timestamp: data.timestamp_signup || 'N/A',
22
+ opt_in_timestamp: data.timestamp_opt || 'N/A',
23
+ unsubscribe_timestamp: request.fired_at || 'N/A',
24
+ has_merge_fields: !!data.merges,
25
+ merge_field_count: data.merges ? Object.keys(data.merges).length : 0,
26
+ merge_fields_summary: data.merges ? {
27
+ first_name: data.merges.FNAME || 'N/A',
28
+ last_name: data.merges.LNAME || 'N/A',
29
+ company: data.merges.COMPANY || 'N/A',
30
+ phone: data.merges.PHONE || 'N/A',
31
+ interests: data.merges.INTERESTS || 'N/A',
32
+ has_address: !!data.merges.ADDRESS,
33
+ } : null,
34
+ member_rating: data.member_rating || 0,
35
+ vip_status: data.vip ? 'VIP' : 'Standard',
36
+ language: data.language || 'en',
37
+ };
38
+ };
39
+
40
+ const calculateSubscriberLifetime = (request: any): string => {
41
+ const data = request.data || {};
42
+ const signupTime = data.timestamp_signup ? new Date(data.timestamp_signup) : null;
43
+ const unsubscribeTime = request.fired_at ? new Date(request.fired_at) : null;
44
+
45
+ if (signupTime && unsubscribeTime) {
46
+ const diffTime = Math.abs(unsubscribeTime.getTime() - signupTime.getTime());
47
+ const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
48
+ return `${diffDays} days`;
49
+ }
50
+ return 'Unknown';
51
+ };
52
+
53
+ const assessEngagementLevel = (request: any): string => {
54
+ const data = request.data || {};
55
+ const rating = data.member_rating || 0;
56
+
57
+ if (rating >= 4) return 'High';
58
+ if (rating >= 2) return 'Medium';
59
+ return 'Low';
60
+ };
61
+
62
+ const identifyChurnFactors = (request: any): string[] => {
63
+ const factors = [];
64
+ const data = request.data || {};
65
+
66
+ if (data.member_rating && data.member_rating < 3) {
67
+ factors.push('Low engagement rating');
68
+ }
69
+
70
+ if (request.unsubscribe_reason) {
71
+ factors.push(`Reason: ${request.unsubscribe_reason}`);
72
+ }
73
+
74
+ if (request.campaign_id) {
75
+ factors.push('Campaign-specific unsubscribe');
76
+ }
77
+
78
+ return factors.length > 0 ? factors : ['No specific factors identified'];
79
+ };
80
+
81
+ export const mailChimpUnsubscriberTrigger = createTrigger({
82
+ auth: mailchimpAuth,
83
+ name: 'unsubscribe',
84
+ displayName: 'Member Unsubscribed from Audience',
85
+ description: 'Fires when a subscriber unsubscribes from your Mailchimp audience. This trigger captures unsubscribe events, opt-outs, and audience churn with comprehensive subscriber information for retention analysis.',
86
+ aiMetadata: {
87
+ description: 'Fires when a contact unsubscribes (opts out) from the selected Mailchimp audience (list). The event carries the subscriber email, merge fields, and, when available, the unsubscribe reason and originating campaign.',
88
+ },
89
+ type: TriggerStrategy.WEBHOOK,
90
+ props: {
91
+ list_id: mailchimpCommon.mailChimpListIdDropdown,
92
+ },
93
+ sampleData: {
94
+ type: 'unsubscribe',
95
+ fired_at: '2024-01-15T10:30:00Z',
96
+ data: {
97
+ id: '8a25ff1d98',
98
+ list_id: 'a6b5da1054',
99
+ email: 'api@mailchimp.com',
100
+ email_type: 'html',
101
+ ip_opt: '192.168.1.100',
102
+ ip_signup: '192.168.1.100',
103
+ timestamp_signup: '2024-01-01T09:00:00Z',
104
+ timestamp_opt: '2024-01-01T09:00:00Z',
105
+ merges: {
106
+ EMAIL: 'api@mailchimp.com',
107
+ FNAME: 'Mailchimp',
108
+ LNAME: 'API',
109
+ COMPANY: 'Mailchimp Inc',
110
+ PHONE: '+1-555-0123',
111
+ INTERESTS: 'Group1,Group2',
112
+ ADDRESS: {
113
+ addr1: '675 Ponce de Leon Ave NE',
114
+ addr2: 'Suite 5000',
115
+ city: 'Atlanta',
116
+ state: 'GA',
117
+ zip: '30308',
118
+ country: 'US',
119
+ },
120
+ },
121
+ member_rating: 3,
122
+ vip: false,
123
+ language: 'en',
124
+ source: 'api',
125
+ tags: ['api-signup', 'churned-subscriber'],
126
+ unsubscribe_reason: 'too_many_emails',
127
+ campaign_id: 'campaign_123',
128
+ campaign_title: 'Weekly Newsletter',
129
+ },
130
+ },
131
+
132
+ async onEnable(context): Promise<void> {
133
+ try {
134
+ const accessToken = getAccessTokenOrThrow(context.auth);
135
+ const server = await mailchimpCommon.getMailChimpServerPrefix(accessToken);
136
+
137
+ const enabledWebhookId = await mailchimpCommon.enableWebhookRequest({
138
+ server,
139
+ listId: context.propsValue.list_id as string,
140
+ token: accessToken,
141
+ webhookUrl: context.webhookUrl!,
142
+ events: {
143
+ unsubscribe: true,
144
+ profile: true,
145
+ },
146
+ });
147
+
148
+ await context.store?.put<WebhookData>(WEBHOOK_DATA_STORE_KEY, {
149
+ id: enabledWebhookId,
150
+ listId: context.propsValue.list_id as string,
151
+ });
152
+ } catch (error: any) {
153
+ throw new Error(`Failed to enable unsubscribe webhook: ${error.message || JSON.stringify(error)}`);
154
+ }
155
+ },
156
+
157
+ async onDisable(context): Promise<void> {
158
+ try {
159
+ const webhookData = await context.store?.get<WebhookData>(WEBHOOK_DATA_STORE_KEY);
160
+
161
+ if (webhookData === undefined || webhookData === null) {
162
+ return;
163
+ }
164
+
165
+ const token = getAccessTokenOrThrow(context.auth);
166
+ const server = await mailchimpCommon.getMailChimpServerPrefix(token);
167
+
168
+ await mailchimpCommon.disableWebhookRequest({
169
+ server,
170
+ token,
171
+ listId: webhookData.listId,
172
+ webhookId: webhookData.id,
173
+ });
174
+ } catch (error: any) {
175
+ console.error(`Failed to disable unsubscribe webhook: ${error.message || JSON.stringify(error)}`);
176
+ }
177
+ },
178
+
179
+ async run(context): Promise<unknown[]> {
180
+ try {
181
+ const request = context.payload.body as any;
182
+
183
+ if (request === undefined || request.type !== 'unsubscribe') {
184
+ return [];
185
+ }
186
+
187
+ const enhancedRequest = {
188
+ ...request,
189
+ trigger_type: 'member_unsubscribed',
190
+ event_category: 'Unsubscribe Event',
191
+ processed_at: new Date().toISOString(),
192
+ unsubscribe_summary: getUnsubscribeEventSummary(request),
193
+ business_context: {
194
+ audience_churn: true,
195
+ retention_concern: true,
196
+ feedback_opportunity: true,
197
+ re_engagement_potential: 'medium',
198
+ },
199
+ retention_insights: {
200
+ subscriber_lifetime: calculateSubscriberLifetime(request),
201
+ engagement_level: assessEngagementLevel(request),
202
+ churn_risk_factors: identifyChurnFactors(request),
203
+ },
204
+ };
205
+
206
+ return [enhancedRequest];
207
+ } catch (error: any) {
208
+ console.error(`Error processing unsubscribe webhook: ${error.message || JSON.stringify(error)}`);
209
+ return [];
210
+ }
211
+ },
212
+ });
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.