Skip to content

Commit

Permalink
feat(CE): Added Mailchimp Destination Connector (#437)
Browse files Browse the repository at this point in the history
* feat(CE): Added Mailchimp Destination Connector
  • Loading branch information
xyfer17 authored Nov 11, 2024
1 parent 93e8767 commit 9b59278
Show file tree
Hide file tree
Showing 11 changed files with 526 additions and 1 deletion.
2 changes: 2 additions & 0 deletions integrations/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ gem "google-cloud-ai_platform-v1"

gem "tiny_tds"

gem "MailchimpMarketing"

group :development, :test do
gem "simplecov", require: false
gem "simplecov_json_formatter", require: false
Expand Down
5 changes: 5 additions & 0 deletions integrations/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ PATH
GEM
remote: https://rubygems.org/
specs:
MailchimpMarketing (3.0.80)
excon (>= 0.76.0, < 1)
json (~> 2.1, >= 2.1.0)
activesupport (7.1.3.3)
base64
bigdecimal
Expand Down Expand Up @@ -151,6 +154,7 @@ GEM
bigdecimal (>= 3.1.4)
ethon (0.16.0)
ffi (>= 1.15.0)
excon (0.112.0)
faraday (2.8.1)
base64
faraday-net_http (>= 2.0, < 3.1)
Expand Down Expand Up @@ -407,6 +411,7 @@ PLATFORMS
x86_64-linux

DEPENDENCIES
MailchimpMarketing
activesupport
async-websocket (~> 0.8.0)
aws-sdk-athena
Expand Down
2 changes: 2 additions & 0 deletions integrations/lib/multiwoven/integrations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
require "aws-sdk-sagemakerruntime"
require "google/cloud/ai_platform/v1"
require "grpc"
require "MailchimpMarketing"

# Service
require_relative "integrations/config"
Expand Down Expand Up @@ -90,6 +91,7 @@
require_relative "integrations/destination/oracle_db/client"
require_relative "integrations/destination/microsoft_excel/client"
require_relative "integrations/destination/microsoft_sql/client"
require_relative "integrations/destination/mailchimp/client"

module Multiwoven
module Integrations
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# frozen_string_literal: true

module Multiwoven
module Integrations
module Destination
module Mailchimp
include Multiwoven::Integrations::Core

API_VERSION = "3.0"

class Client < DestinationConnector
prepend Multiwoven::Integrations::Core::RateLimiter

def check_connection(connection_config)
connection_config = connection_config.with_indifferent_access
initialize_client(connection_config)
authenticate_client
success_status
rescue StandardError => e
failure_status(e)
end

def discover(_connection_config = nil)
catalog = build_catalog(load_catalog)
catalog.to_multiwoven_message
rescue StandardError => e
handle_exception(e, {
context: "MAILCHIMP:DISCOVER:EXCEPTION",
type: "error"
})
end

def write(sync_config, records, _action = "create")
@sync_config = sync_config
initialize_client(sync_config.destination.connection_specification)
process_records(records, sync_config.stream)
rescue StandardError => e
handle_exception(e, {
context: "MAILCHIMP:WRITE:EXCEPTION",
type: "error",
sync_id: @sync_config.sync_id,
sync_run_id: @sync_config.sync_run_id
})
end

private

def initialize_client(config)
config = config.with_indifferent_access
@client = MailchimpMarketing::Client.new
@client.set_config({
api_key: config[:api_key],
server: config[:api_key].split("-").last
})
@list_id = config[:list_id]
@email_template_id = config[:email_template_id] || ""
end

def process_records(records, stream)
log_message_array = []
write_success = 0
write_failure = 0
properties = stream.json_schema[:properties]

records.each do |record_object|
record = extract_data(record_object, properties)
args = [stream.name, "Id", record]
begin
response = send_to_mailchimp(record, stream.name)
write_success += 1
log_message_array << log_request_response("info", args, response)
rescue StandardError => e
handle_exception(e, {
context: "MAILCHIMP:WRITE:EXCEPTION",
type: "error",
sync_id: @sync_config.sync_id,
sync_run_id: @sync_config.sync_run_id
})
write_failure += 1
log_message_array << log_request_response("error", args, e.message)
end
end
tracking_message(write_success, write_failure, log_message_array)
end

def send_to_mailchimp(record, stream_name)
case stream_name
when "Audience"
@client.lists.set_list_member(@list_id, Digest::MD5.hexdigest(record[:email].downcase), {
email_address: record[:email],
status_if_new: "subscribed",
merge_fields: {
FNAME: record[:first_name],
LNAME: record[:last_name]
}
})
when "Tags"
@client.lists.update_list_member_tags(@list_id, Digest::MD5.hexdigest(record[:email].downcase), {
tags: record[:tags].map { |tag| { name: tag, status: "active" } }
})
when "Campaigns"
campaign = @client.campaigns.create({
type: "regular",
recipients: { list_id: @list_id },
settings: {
subject_line: record[:subject],
from_name: record[:from_name],
reply_to: record[:reply_to]
}
})
if @email_template_id
@client.campaigns.set_content(campaign["id"], {
template: { id: @email_template_id }
})
else
@client.campaigns.set_content(campaign["id"], {
plain_text: record[:content]
})
end
@client.campaigns.send(campaign["id"])
else
raise "Unsupported stream type: #{stream_name}"
end
end

def authenticate_client
@client.lists.get_all_lists
end

def load_catalog
read_json(CATALOG_SPEC_PATH)
end

def log_debug(message)
Multiwoven::Integrations::Service.logger.debug(message)
end
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
{
"request_rate_limit": 100000,
"request_rate_limit_unit": "day",
"request_rate_concurrency": 10,
"streams": [
{
"name": "Audience",
"action": "create",
"json_schema": {
"type": "object",
"additionalProperties": true,
"required": ["email"],
"properties": {
"email": {
"type": "string",
"format": "email"
},
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"status": {
"type": "string",
"enum": ["subscribed", "unsubscribed", "cleaned", "pending"]
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"merge_fields": {
"type": "object",
"additionalProperties": true,
"properties": {
"FNAME": {
"type": "string"
},
"LNAME": {
"type": "string"
}
}
},
"language": {
"type": "string"
},
"vip": {
"type": "boolean"
},
"timestamp_signup": {
"type": "string",
"format": "date-time"
},
"ip_signup": {
"type": "string",
"format": "ipv4"
},
"timestamp_opt": {
"type": "string",
"format": "date-time"
},
"ip_opt": {
"type": "string",
"format": "ipv4"
}
}
},
"supported_sync_modes": ["incremental"],
"source_defined_cursor": true,
"default_cursor_field": ["timestamp_opt"],
"source_defined_primary_key": [["email"]]
},
{
"name": "Tags",
"action": "create",
"json_schema": {
"type": "object",
"additionalProperties": true,
"required": ["email", "tags"],
"properties": {
"email": {
"type": "string",
"format": "email"
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"supported_sync_modes": ["incremental"],
"source_defined_cursor": true,
"default_cursor_field": ["updated"]
},
{
"name": "Campaigns",
"action": "create",
"json_schema": {
"type": "object",
"additionalProperties": true,
"required": ["subject", "from_name", "reply_to", "recipients"],
"properties": {
"subject": {
"type": "string"
},
"from_name": {
"type": "string"
},
"reply_to": {
"type": "string",
"format": "email"
},
"recipients": {
"type": "object",
"properties": {
"list_id": {
"type": "string"
}
}
},
"template_id": {
"type": "string"
},
"content": {
"type": "string"
},
"send_time": {
"type": "string",
"format": "date-time"
}
}
},
"supported_sync_modes": ["full_refresh"],
"source_defined_cursor": false
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"data": {
"name": "Mailchimp",
"title": "Mailchimp",
"connector_type": "destination",
"category": "Marketing Automation",
"documentation_url": "https://docs.multiwoven.com/destinations/crm/mailchimp",
"github_issue_label": "destination-mailchimp",
"icon": "icon.svg",
"license": "MIT",
"release_stage": "alpha",
"support_level": "community",
"tags": ["language:ruby", "multiwoven"]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"documentation_url": "https://docs.multiwoven.com/integrations/destination/mailchimp",
"stream_type": "static",
"connection_specification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Mailchimp",
"type": "object",
"required": ["api_key", "list_id"],
"properties": {
"api_key": {
"type": "string",
"multiwoven_secret": true,
"title": "API Key",
"order": 0
},
"list_id": {
"type": "string",
"title": "List Id",
"order": 1
},
"email_template_id": {
"type": "string",
"title": "Email Template Id",
"order": 2
}
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 9b59278

Please sign in to comment.