Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Violet Rails mailchimp plugin #720

Open
donrestarone opened this issue Jun 10, 2022 · 2 comments
Open

Violet Rails mailchimp plugin #720

donrestarone opened this issue Jun 10, 2022 · 2 comments
Labels
documentation Improvements or additions to documentation

Comments

@donrestarone
Copy link
Contributor

donrestarone commented Jun 10, 2022

credits to @Pralish

Mailchimp Sync V1 (soft deprecated) please use V2 below

class SyncToMailchimp
  def initialize(parameters)  
    @external_api_client = parameters[:external_api_client]
    @unsynced_api_resources = @external_api_client.api_namespace.api_resources.where("properties @> ?", {synced_to_mailchimp: false}.to_json)
		@mailchimp_uri = "https://#{@external_api_client.metadata['SERVER_PREFIX']}.api.mailchimp.com/3.0/lists/#{@external_api_client.metadata['LIST_ID']}/members?skip_merge_validation=true"
  end

  def start
    logger_namespace = ApiNamespace.find_by!(slug: @external_api_client.metadata["LOGGER_NAMESPACE"])
		@unsynced_api_resources.each do |api_resource|
       begin
					attr_to_exclude = @external_api_client.metadata['ATTR_TO_EXCLUDE']
				  merge_fields = api_resource.properties.except(*attr_to_exclude).transform_keys(&:upcase).transform_values(&:to_s).merge({"IMPROVE": api_resource.properties["what_were_you_trying_to_overcome_or_improve"].to_s})
          response = HTTParty.post(@mailchimp_uri, 
            body: { 
              "email_address": api_resource.properties["email"],
              "status": "subscribed",
              "merge_fields": merge_fields,
              "tags": @external_api_client.metadata['TAGS']
              }.to_json,
            :headers => { 'Content-Type' => 'application/json', 'Authorization' => "Basic #{@external_api_client.metadata["API_KEY"]}" } )
         if response.success?
          	api_resource.properties["synced_to_mailchimp"] = true
						api_resource.save
         end
         logger_namespace.api_resources.create!(
                properties: {
                  api_resource: api_resource.id,
           				status: response.success? ? "success" : "error",
                  response: JSON.parse(response.body),
                  timestamp: Time.zone.now
                }
          )
       rescue StandardError => e
         logger_namespace.api_resources.create!(
              properties: {
                api_resource: api_resource.id,
           			status: "error",
                response: { detail: e.message},
                timestamp: Time.zone.now
              }
            )
       end
     end
  end
end
# at the end of the file we have to implicitly return the class 
SyncToMailchimp

The following metadata need to be included for the plugin to work:

Group 1172

API_KEY: mailchimp api key - https://mailchimp.com/help/about-api-keys/

LIST_ID: Audiance ID, - https://mailchimp.com/help/find-audience-id/

SERVER_PREFIX: mailchimp url prefix, eg: us9, us10 - https://mailchimp.com/developer/marketing/guides/quick-start/#make-your-first-api-call

ATTR_TO_EXCLUDE: attributes that you don't want to sync to mailchimp

TAGS: array of tags to assign to contact

LOGGER_NAMESPACE: the slug of the API Namespace you want to use for logging

Note:

Excluding synced_to_mailchimp attribute because it is for internal use
Excluded what_were_you_trying_to_overcome_or_improve intentionally and created a short tag name 'IMPROVE' because mailchimp didn't accept tag name that long.

merge fields

172187243-1952cfc9-c39f-4e14-8df3-4802531982d1

The field label can be anything but the tags should be exactly same as the keys in api namespace.

Note: The tags are capitalized by mailchimp

@donrestarone donrestarone added the documentation Improvements or additions to documentation label Jun 10, 2022
@donrestarone
Copy link
Contributor Author

@Pralish when you get a chance, can you create a unit test for this plugin?

you can copy paste the class here: https://github.com/restarone/violet_rails/blob/master/test/fixtures/external_api_clients.yml

and use the web_mock gem to mock responses from Mailchimp

@donrestarone
Copy link
Contributor Author

donrestarone commented Jul 13, 2022

mailchimp sync v2

credits to @Pralish

class SyncToMailchimp
  def initialize(parameters)
    @external_api_client     = parameters[:external_api_client]
    @api_key                 = @external_api_client.metadata["API_KEY"]
    @unsynced_api_resources  = @external_api_client.api_namespace.api_resources.where("properties @> ?", {synced_to_mailchimp: false}.to_json)
    @mailchimp_uri           = "https://#{@external_api_client.metadata['SERVER_PREFIX']}.api.mailchimp.com/3.0/lists/#{@external_api_client.metadata['LIST_ID']}/members?skip_merge_validation=true"
    @custom_merge_fields_map = @external_api_client.metadata['CUSTOM_MERGE_FIELDS_MAP'] || {}
    @attr_to_exclude         = (@external_api_client.metadata['ATTR_TO_EXCLUDE'] || []) + @custom_merge_fields_map.keys + ['synced_to_mailchimp']
    @logger_namespace        = ApiNamespace.find_by(slug: @external_api_client.metadata["LOGGER_NAMESPACE"]) if @external_api_client.metadata["LOGGER_NAMESPACE"]
  end
  
  def start
    @unsynced_api_resources.each do |api_resource|
      begin
        merge_fields = api_resource.properties.except(*@attr_to_exclude).transform_keys(&:upcase).transform_values(&:to_s)

        @custom_merge_fields_map.each do |key, value|
          merge_fields[value.upcase] = api_resource.properties[key].to_s if value
        end

        response = HTTParty.post(@mailchimp_uri, 
          body: { 
              email_address: api_resource.properties["email"],
              status: "subscribed",
              merge_fields: merge_fields,
              tags: @external_api_client.metadata['TAGS'] || []
            }.to_json,

          headers: {
              'Content-Type': 'application/json',
              'Authorization': "Basic #{@api_key}" 
            } 
          )

        if response.success?
          api_resource.properties["synced_to_mailchimp"] = true
          api_resource.save
        end

        @logger_namespace.api_resources.create!(
          properties: {
            api_resource: api_resource.id,
            status: response.success? ? "success" : "error",
            response: JSON.parse(response.body),
            timestamp: Time.zone.now
          }
        ) if @logger_namespace

      rescue StandardError => e
        @logger_namespace.api_resources.create!(
          properties: {
            api_resource: api_resource.id,
            status: "error",
            response: { detail: e.message},
            timestamp: Time.zone.now
          }
        ) if @logger_namespace
      end
    end
  end
end

# at the end of the file we have to implicitly return the class 
SyncToMailchimp

Required api_namespace properties

email :

  • type: string
  • email is a required field on mailchimp

synced_to_mailchimp :

  • type: boolean
  • to keep track of synced api resources
  • this property won't be sent to mailchimp

Required Metadata

API_KEY:

LIST_ID:

SERVER_PREFIX:

Optional Metadata

CUSTOM_MERGE_FIELDS_MAP

  • type: object
  • By default, merge field name is same as uppercased property name. eg. first_name property will have FIRST_NAME merge field on mailchimp
  • this metadata will allow you to override the default behavior if needed
  • eg: what_were_you_trying_to_overcome_or_improve property name is too long. Mailchimp does not allow long field name. So we map this property name to a shorter merge field name 'IMPROVE'.
  • eg. { 'what_were_you_trying_to_overcome_or_improve': 'IMPROVE' }

ATTR_TO_EXCLUDE:

  • type: array
  • properties that you don't want to sync to mailchimp
  • 'synced_to_mailchimp' property will be auto excluded

TAGS:

  • type: array
  • array of tags to assign to contact
  • eg: storyteller

LOGGER_NAMESPACE:

  • type: string
  • slug of logger api namespace
  • logger namespace must have following properties
    • status: string
    • response: object
    • api_resource: number
    • timestamp: string

Screen Shot 2022-07-09 at 10 50 24 AM

Screen Shot 2022-07-09 at 11 32 06 AM

On Mailchimp:

Create fields on mailchimp with same name as properties on api namespace. You can create fields with different names from api namespace properties, but you will need to map it correctly using CUSTOM_MERGE_FIELDS_MAP metadata.

Screen.Recording.2022-06-05.at.8.35.02.AM.mov

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

1 participant