Add Mailchimp (Actions) cloud destination#3855
Open
mdkhan-tw wants to merge 1 commit into
Open
Conversation
New cloud-mode destination for Mailchimp Marketing API v3.0 with native
v2 Journeys compatibility. Supports two P0 actions:
- Add or Update Audience Member: upserts a subscriber via
PUT /lists/{list_id}/members/{subscriber_hash}, mapping traits to merge
fields. Uses status_if_new to protect existing consent status. Batching
via POST /lists/{list_id} (up to 500 members, update_existing).
- Add or Remove Member Tags: applies/removes tags via
POST /lists/{list_id}/members/{subscriber_hash}/tags with active/inactive
status, plus tags_to_add / tags_to_remove convenience inputs. Surfaces a
clear error when the member does not exist (404).
Auth is API key over HTTP Basic Auth; the datacenter prefix is resolved
from the API key suffix and overridable via a setting. Subscriber hash is
the MD5 of the lowercased email (via the shared hashing util).
NOTE: not registered in destinations/index.ts yet - the production metadata
ID is assigned when the destination is created in Segment production and must
match across environments.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because no GitHub Actions runner was available. Make sure your repository has a runner available to run Copilot's review, or add a copilot-setup-steps.yml file specifying one with the runs-on attribute. See the docs for more details.
Adds a new cloud-mode Mailchimp (Actions) destination with two actions (member upsert + member tag updates), including batching support for upserts, datacenter resolution, and Jest test coverage.
Changes:
- Introduces
actions-mailchimpdestination definition, metadata, and settings/auth handling (Basic Auth + datacenter resolution). - Implements
addOrUpdateMember(single + batch) andaddOrRemoveTags(single) with shared request/transform utilities. - Adds unit + snapshot tests for auth, both actions, batching, and 404 behavior.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/destination-actions/src/destinations/actions-mailchimp/index.ts | Defines destination, authentication, presets, and action registration. |
| packages/destination-actions/src/destinations/actions-mailchimp/metadata.json | Declares destination metadata and action field schemas/mappings. |
| packages/destination-actions/src/destinations/actions-mailchimp/constants.ts | Adds Mailchimp base URL/path builders and enums. |
| packages/destination-actions/src/destinations/actions-mailchimp/utils.ts | Implements subscriber hashing, request payload shaping, batching, and error handling. |
| packages/destination-actions/src/destinations/actions-mailchimp/types.ts | Adds typed request/response interfaces for Mailchimp endpoints. |
| packages/destination-actions/src/destinations/actions-mailchimp/generated-types.ts | Generated settings types. |
| packages/destination-actions/src/destinations/actions-mailchimp/addOrUpdateMember/index.ts | Implements the “Add or Update Audience Member” action + batching config. |
| packages/destination-actions/src/destinations/actions-mailchimp/addOrUpdateMember/generated-types.ts | Generated payload types for member upsert action. |
| packages/destination-actions/src/destinations/actions-mailchimp/addOrUpdateMember/tests/index.test.ts | Tests single upsert, missing email, and batch request behavior. |
| packages/destination-actions/src/destinations/actions-mailchimp/addOrRemoveTags/index.ts | Implements the “Add or Remove Member Tags” action. |
| packages/destination-actions/src/destinations/actions-mailchimp/addOrRemoveTags/generated-types.ts | Generated payload types for tags action. |
| packages/destination-actions/src/destinations/actions-mailchimp/addOrRemoveTags/tests/index.test.ts | Tests tag payload composition and 404 error surfacing. |
| packages/destination-actions/src/destinations/actions-mailchimp/tests/index.test.ts | Tests testAuthentication behavior including datacenter override. |
| packages/destination-actions/src/destinations/actions-mailchimp/tests/snapshot.test.ts | Snapshot tests for request bodies/headers across actions. |
| packages/destination-actions/src/destinations/actions-mailchimp/tests/snapshots/snapshot.test.ts.snap | Snapshot outputs for the new destination. |
Comment on lines
+30
to
+35
| const resolveEmail = (email?: string): string => { | ||
| if (!email || email.trim() === '') { | ||
| throw new PayloadValidationError('An email address is required to identify the audience member.') | ||
| } | ||
| return email | ||
| } |
|
|
||
| const buildMemberBody = (payload: MemberPayload): UpsertMemberRequest => { | ||
| const body: UpsertMemberRequest = { | ||
| email_address: payload.email_address, |
Comment on lines
+89
to
+92
| const body: BatchMembersRequest = { | ||
| members: members.slice(0, DEFAULT_BATCH_SIZE), | ||
| update_existing: true | ||
| } |
Comment on lines
+146
to
+155
| } catch (error) { | ||
| const status = (error as { response?: { status?: number }; status?: number })?.response?.status | ||
| if (status === 404) { | ||
| throw new APIError( | ||
| 'Audience member not found. Run the "Add or Update Audience Member" action to create the member before applying tags.', | ||
| 404 | ||
| ) | ||
| } | ||
| throw error | ||
| } |
Comment on lines
+106
to
+112
| if (payload.tags && payload.tags.length > 0) { | ||
| for (const tag of payload.tags) { | ||
| if (tag && tag.name && tag.name.trim() !== '') { | ||
| tags.push({ name: tag.name, status: tag.status }) | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a new cloud-mode Mailchimp (Actions) destination for the Mailchimp Marketing API v3.0, with native v2 Journeys compatibility. This replaces the constraints of the Classic Mailchimp destination (hardcoded field mappings, identify-only, no tag management) with flexible merge-field mapping, behavioral tag management, batching, and structured error handling.
Implements the two P0 actions from the PRD:
Actions
addOrUpdateMember)identifyPUT /lists/{list_id}/members/{subscriber_hash}(batch:POST /lists/{list_id})addOrRemoveTags)trackPOST /lists/{list_id}/members/{subscriber_hash}/tagsKey details
anystring:apiKey). Datacenter prefix auto-resolved from the API key suffix (e.g.-us6), overridable via adataCentersetting.processHashingutil.addOrUpdateMemberdefaults tostatus_if_newso existing/unsubscribed members' consent status is preserved (CAN-SPAM / GDPR);statusis a separate opt-in field.addOrUpdateMemberimplementsperformBatch(POST /lists/{list_id}, up to 500 members,update_existing: true, grouped bylist_id). The tags endpoint is strictly per-member with no bulk variant, soaddOrRemoveTagshas noperformBatch.{name, status}[]plustags_to_add/tags_to_removeconvenience inputs (tags_to_adddefaults to the event name). A 404 (member not found) is surfaced as a clear, actionableAPIError.constants.ts(URLs/enums),types.ts(typed request/response interfaces),utils.ts(send/transform/batch logic);perform/performBatchare thin wrappers.Testing
./bin/run serve): drove both actions with real HTTP requests. Verified datacenter resolution, subscriber-hash construction, correct single vs batch endpoints, and thedataCenteroverride reaching the real Mailchimp API (authoritative403on a fake key).yarn types,tsc --noEmit, andeslintall clean.packages/destination-actions/src/destinations/index.tswith the production-assigned metadata ID. It is intentionally not registered here: the metadata ID is a real MongoDB ObjectId assigned when the destination is created in Segment production and must match across environments — a placeholder ID would pollute the shared registry.Out of scope (per PRD)
Outbound email/campaigns, device-mode, reading data back from Mailchimp, audience (list) CRUD, multi-audience fan-out, OAuth 2.0 (future consideration).
🤖 Generated with Claude Code