class SubscribedTo::MailChimp::WebHook

Allows for the usage of MailChimp webhooks. apidocs.mailchimp.com/webhooks/

To get started:

1) On the list tools page, click the “WebHooks” link.

2) Enter the webhook URL as:

http://mywebapp.com/subscribed_to/mail_chimp?key=<secret_key_defined_in_config>

3) Enable updates for events:

4) Send updates when a change was made by…

5) Click “Update”

Constants

LIMIT

Attributes

enabled_models[RW]

Public Class Methods

process(params) click to toggle source

Handles MailChimp webhook request. Takes in a hash of parameters from the webhook.

Responds to four webhook events:

  • subscribe

  • unsubscribe

  • upemail

  • profile

If a request comes in that does not match one of the four event types, it writes a warning to the default logger

TODO: Write to a SubscribedTo specific log instead

# File lib/subscribed_to/mail_chimp/web_hook.rb, line 42
def self.process(params)
  type = params.delete("type").to_sym
  hook = self.new(params)

  hook.respond_to?(type) ?
    hook.send(type.to_sym, params["data"]) :
    Rails.logger.warn("WARNING: MailChimp WebHook does not support the #{type} event.")
rescue NoMethodError => e
  Rails.logger.warn("WARNING: MailChimp WebHook: #{e.message}")
end

Public Instance Methods

profile(params) click to toggle source

If a user updates any of their subscription information via a MailChimp web form, we need to update that info in the web app.

We only update the attributes defined in the SubscribedTo.mail_chimp_config merge vars. If more information is sent via the merge vars from MailChimp, but it is not defined in the mail_chimp_config, it is ignored.

# File lib/subscribed_to/mail_chimp/web_hook.rb, line 117
def profile(params)
  web_id = params["web_id"]

  subscriber = nil
  enabled_models.each { |model| subscriber ||= model.constantize.find_by_mail_chimp_id(web_id) }

  unless over_the_limit(subscriber.updated_at)
    subscriber.class.merge_vars.each { |key, method| subscriber.send("#{method.to_s}=", params["merges"][key]) unless params["merges"][key].blank? }
    subscriber.save_without_update_list_member(:validate => false)
  end
end
subscribe(params) click to toggle source

When a user registers on the site, they are automatically queued for inclusion on the mailing list (if they opt-in).

After a user confirms their subscription (MailChimp recommends a double opt-in strategy, but it's not required), a webhook request is sent which includes the “web_id” - a unique ID for mail chimp users. We'll record this id to use with other updates.

# File lib/subscribed_to/mail_chimp/web_hook.rb, line 64
def subscribe(params)
  web_id = params["web_id"]
  email  = params["merges"]["EMAIL"]

  subscriber = nil
  enabled_models.each { |model| subscriber ||= model.constantize.find_by_email(email) }

  subscriber.subscribed_to_list = true
  subscriber.mail_chimp_id = web_id.to_i
  subscriber.save_without_update_list_member(:validate => false)
end
unsubscribe(params) click to toggle source

Set the subscribed_to_list attribute to false to prevent any future MailChimp API calls when the user updates their profile in the web app.

# File lib/subscribed_to/mail_chimp/web_hook.rb, line 78
def unsubscribe(params)
  web_id = params["web_id"]

  subscriber = nil
  enabled_models.each { |model| subscriber ||= model.constantize.find_by_mail_chimp_id(web_id) }

  subscriber.subscribed_to_list = false
  subscriber.save_without_update_list_member(:validate => false)
end
upemail(params) click to toggle source

If a user updates their email from one of the MailChimp forms (they may get there from a link in an email, or from the confirm subscription page), then a webhook will be sent to the app with the a notice of the changed email. This method will update the web app users's email.

Is this a good idea?

Theoretically, it seems like the best idea is to keep the web app user and mailing list subscriber email addresses in sync.

However, if the web app makes use of login by email, this could create confusion for the user. In this case, it may be best to send an email to the user notifying them that their login information has changed.

# File lib/subscribed_to/mail_chimp/web_hook.rb, line 99
def upemail(params)
  old_email = params["old_email"]
  new_email = params["new_email"]

  subscriber = nil
  enabled_models.each { |model| subscriber ||= model.constantize.find_by_email(old_email) }

  unless over_the_limit(subscriber.updated_at)
    subscriber.email = new_email
    subscriber.save_without_update_list_member(:validate => false)
  end
end

Private Instance Methods

over_the_limit(updated_at) click to toggle source
# File lib/subscribed_to/mail_chimp/web_hook.rb, line 131
def over_the_limit(updated_at)
  (Time.zone.now - updated_at).seconds <= LIMIT
end