Video Assets for Mailchimp + Salesforce: Part 6 - Sync Campaign Member from Mailchimp
This page contains the assets for the video on Blu Tiger academy that walks you through how to create the apex classes and apex trigger to automate the creation of campaign members from the MC Subscriber Activity records. Copy and paste the code below into your org per the instructions in the video.
Apex Classes & Apex Trigger Code
Apex Class - MCSubscriberActivityTriggerHandler
public class MCSubscriberActivityTriggerHandler{ public void afterInsert(ListnewRecords) { MapCampaignMemberStatusMap = new Map Map(); cmMCSAMap = new Map Map(); ldctSubscriberMap = new Map List(); contactIdsList = new List List(); leadIdsList = new List List(); campaignIdsList = new List List(); contactSubscriberList = new List Set(); newCampaignMembersSet = new Set Set(); existingCampaignMembersSet = new Set List(); CampaignMembersToUpdate = new List List(); CampaignMembersToInsert = new List //set up all the member status mappings CampaignMemberStatusMap.Put('open','Opened'); CampaignMemberStatusMap.Put('click','Clicked'); CampaignMemberStatusMap.Put('bounce','Bounced'); CampaignMemberStatusMap.Put('unsub','Unsubscribed'); CampaignMemberStatusMap.Put('sent','Sent'); //Make a list of the subscribers and campaigns List(); subscriberActivityList = [Select Id,MC4SF__MC_Subscriber__c,MC4SF__MC_Campaign__c,MC4SF__MC_Campaign__r.Campaign__c,MC4SF__Action__c FROM MC4SF__MC_Subscriber_Activity__c WHERE Id IN :newRecords]; for(MC4SF__MC_Subscriber_Activity__c mcsa:subscriberActivityList){ if(mcsa.MC4SF__MC_Subscriber__c != NULL) contactSubscriberList.Add(mcsa.MC4SF__MC_Subscriber__c); if(mcsa.MC4SF__MC_Campaign__r.Campaign__c != NULL) campaignIdsList.Add(mcsa.MC4SF__MC_Campaign__r.Campaign__c); } //Create a contact list and map to the subscriber for(Contact ct: [Select Id,MC4SF__MC_Subscriber__c FROM Contact WHERE MC4SF__MC_Subscriber__c IN :contactSubscriberList]){ ldctSubscriberMap.Put(ct.MC4SF__MC_Subscriber__c,ct.Id); contactIdsList.Add(ct.Id); } //Create a lead list and map to the subscriber for(Lead ld: [Select Id,MC4SF__MC_Subscriber__c FROM Lead WHERE MC4SF__MC_Subscriber__c IN :contactSubscriberList]){ ldctSubscriberMap.Put(ld.MC4SF__MC_Subscriber__c,ld.Id); leadIdsList.Add(ld.Id); } //Create a map of campaignId and lead/contact Id combination to the campaign member for(CampaignMember cm: [Select Id,ContactId,LeadId,CampaignId,Status FROM CampaignMember WHERE (ContactId IN :contactIdsList OR LeadId IN :leadIdsList) AND CampaignId IN :campaignIdsList]){ if(cm.ContactId != NULL) cmMCSAMap.Put(cm.CampaignId + '_' + cm.ContactId, cm); else if(cm.LeadId != NULL) cmMCSAMap.Put(cm.CampaignId + '_' + cm.LeadId, cm); } //Loop through each subscriber activity for(MC4SF__MC_Subscriber_Activity__c mcsa:subscriberActivityList){ //Get the associated contact/lead if(ldctSubscriberMap.ContainsKey(mcsa.MC4SF__MC_Subscriber__c) && ldctSubscriberMap.Get(mcsa.MC4SF__MC_Subscriber__c) != NULL && mcsa.MC4SF__MC_Campaign__c != NULL && mcsa.MC4SF__MC_Campaign__r.Campaign__c != NULL){ Id contactOrLeadId = ldctSubscriberMap.Get(mcsa.MC4SF__MC_Subscriber__c); //Check if contact belongs to campaign already, if so, update it's status if(cmMCSAMap.ContainsKey(mcsa.MC4SF__MC_Campaign__r.Campaign__c + '_' + contactOrLeadId) && cmMCSAMap.get(mcsa.MC4SF__MC_Campaign__r.Campaign__c + '_' + contactOrLeadId) != NULL){ CampaignMember existingCM = cmMCSAMap.get(mcsa.MC4SF__MC_Campaign__r.Campaign__c + '_' + contactOrLeadId); //Update the campaign member only if the status conditions are met and this particular record is not being updated in the same transaction if((!(existingCM.Status == 'Clicked' && (mcsa.MC4SF__Action__c=='sent' || mcsa.MC4SF__Action__c=='open'))) && (!existingCampaignMembersSet.Contains(mcsa.MC4SF__MC_Campaign__r.Campaign__c + '_' + contactOrLeadId)) ){ if(CampaignMemberStatusMap.ContainsKey(mcsa.MC4SF__Action__c) && CampaignMemberStatusMap.Get(mcsa.MC4SF__Action__c) != NULL) existingCM.Status = CampaignMemberStatusMap.Get(mcsa.MC4SF__Action__c); CampaignMembersToUpdate.Add(existingCM); existingCampaignMembersSet.Add(mcsa.MC4SF__MC_Campaign__r.Campaign__c + '_' + contactOrLeadId); } } //Else, add it to the campaign else{ //Check if the record is already part of the current transaction if(!newCampaignMembersSet.Contains(mcsa.MC4SF__MC_Campaign__r.Campaign__c + '_' + contactOrLeadId)){ CampaignMember newCM = new CampaignMember(CampaignId=mcsa.MC4SF__MC_Campaign__r.Campaign__c); if(contactOrLeadId != NULL && String.ValueOf(contactOrLeadId).startsWith('00Q')) newCM.LeadId=contactOrLeadId; else newCM.ContactId=contactOrLeadId; if(CampaignMemberStatusMap.ContainsKey(mcsa.MC4SF__Action__c) && CampaignMemberStatusMap.Get(mcsa.MC4SF__Action__c) != NULL) newCM.Status=CampaignMemberStatusMap.Get(mcsa.MC4SF__Action__c); CampaignMembersToInsert.Add(newCM); newCampaignMembersSet.Add(mcsa.MC4SF__MC_Campaign__r.Campaign__c + '_' + contactOrLeadId); } } } } if(CampaignMembersToUpdate.size() > 0) update CampaignMembersToUpdate; if(CampaignMembersToInsert.size() > 0) insert CampaignMembersToInsert; } }
Apex Class - MCSubscriberActivityTriggerHandler_Test
@isTest public class MCSubscriberActivityTriggerHandler_Test{ private static testMethod void testCreateSubscriberActivity() { Account newAccount = new Account(Name='Test Account'); insert newAccount; Lead newLead = new Lead(FirstName='Test', LastName='Lead', Company='Test Company'); insert newLead; Contact newContact = new Contact(FirstName='Test',LastName='Contact',AccountId=newAccount.Id); insert newContact; /*Campaign newCampaign = new Campaign(Name='Test Campaign'); insert newCampaign;*/ MC4SF__MC_Campaign__c mcCampaign = new MC4SF__MC_Campaign__c(MC4SF__MailChimp_ID__c='123'); insert mcCampaign; MC4SF__MC_Campaign__c cp = [Select Id,Campaign__c FROM MC4SF__MC_Campaign__c WHERE Id=:mcCampaign.Id]; CampaignMember newLeadCM = new CampaignMember(CampaignId=cp.Campaign__c,LeadId=newLead.Id,Status='Not Clicked'); insert newLeadCM; MC4SF__MC_List__c mcAudience = new MC4SF__MC_List__c(MC4SF__MailChimp_ID__c='123'); insert mcAudience; MC4SF__MC_Subscriber__c newLdSubscriber = new MC4SF__MC_Subscriber__c(MC4SF__Email2__c='test1@test.com',MC4SF__MC_List__c=mcAudience.Id); insert newLdSubscriber; MC4SF__MC_Subscriber__c newCtSubscriber = new MC4SF__MC_Subscriber__c(MC4SF__Email2__c='test2@test.com',MC4SF__MC_List__c=mcAudience.Id); insert newCtSubscriber; newLead.MC4SF__MC_Subscriber__c=newLdSubscriber.Id; update newLead; newContact.MC4SF__MC_Subscriber__c=newCtSubscriber.Id; update newContact; MC4SF__MC_Subscriber_Activity__c subLdActivity = new MC4SF__MC_Subscriber_Activity__c(MC4SF__MC_Subscriber__c=newLdSubscriber.Id,MC4SF__MC_Campaign__c=mcCampaign.Id,MC4SF__Action__c='click'); insert subLdActivity; MC4SF__MC_Subscriber_Activity__c subCtActivity = new MC4SF__MC_Subscriber_Activity__c(MC4SF__MC_Subscriber__c=newCtSubscriber.Id,MC4SF__MC_Campaign__c=mcCampaign.Id,MC4SF__Action__c='click'); insert subCtActivity; } }
Apex Trigger - MCSubscriberActivityTrigger
trigger MCSubscriberActivityTrigger on MC4SF__MC_Subscriber_Activity__c (after insert) { MCSubscriberActivityTriggerHandler handler = new MCSubscriberActivityTriggerHandler(); if(trigger.IsAfter && trigger.IsInsert) handler.afterInsert(Trigger.new); }
Code to Run Mc Subscriber Activity Batch from Developer Console
Database.executeBatch(new MC4SF.ActivityBatch(), 50);
Congratulations! You have just completed creating automation to add campaign members to your Salesforce Campaigns. Now its time to test! If you must test this in production because you are already using Mailchimp, then you must deploy these components via a change set to production. If you are not familiar with how to do this, follow the steps below.
How to Deploy Your Components to Production
In the sandbox: Setup -> Outbound Change Sets -> New

- Enter Name - this can be whatever you want

- Click Add

- Select Component Type = Apex Trigger
- Check the box for Apex Trigger = MCSubscriberActivityTrigger
- Click Add to Change Set

- Select Component Type = Apex Classes
- Check the boxes next to Apex Classes = MCSubscriberActivityTriggerHandler and MCSubscriberTriggerHandlerTest
- Click Add to Change Set

- Click Upload

- Select Production -> Upload

If you do not see Production in this screen, you will need to update the Deployment Settings in production for this sandbox. Follow these steps:
- Go to Production -> Setup -> Deployment Settings -> Edit next to the sandbox you are deploying from.

- Select Allow Inbound Changes -> Save

- Go to Production -> Setup -> Inbound Change Sets -> Change Sets Awaiting Deployment -> Deploy
- It may take anywhere from 30 seconds to 5 minutes to see your change set in production. You will receive an email when it is ready to deploy.

- Select Default -> Deploy

- The Deployment Details screen will run all of the apex tests and it will show two green circles when it has successfully deployed. You may have a different number in the second green circle, it just depends on the amount of code you have in your org.

Great job! You have just successfully deployed your code to production and now you are ready to make sure everything is working in production. Yay!
How to Test the Automation
Since Mailchimp can only be connected to one environment, this testing is probably being done directly in production. Make sure to send the test email to contacts with your own email address.
Follow these steps to test the automation:
- Create a campaign in MailChimp and send it to at least three recipients that have email addresses you have access to or get someone to help you test. Make sure they are test contacts.
- Do different actions on the email for each recipient. Ex: #1 - should open the email, #2 - should open and click the email #3 - should not open the email
- Go to MC Setup tab in Salesforce -> Campaigns -> Click Refresh MC Campaigns button. You should see your test campaign show up in the list.

- Click the Gear icon in Salesforce on the top right hand side of the screen -> Developer Console

- Select Debug -> Open Execute Anonymous Window

- Copy and paste the code below into the screen and click Execute. Thanks for this tip Spencer Widman!
- This step prevents us from having to wait for the daily sync between Mailchimp and Salesforce. By running this line of code in the developer console, we are making the batch process start that triggers the MC Subscriber Activity records to sync from Mailchimp to Salesforce.
Database.executeBatch(new MC4SF.ActivityBatch(), 50);

Give it a minute or two and check your campaign to see if the people were added to it.
If they weren't in the campaign, check the MC Subscriber Activity tab in Salesforce to see if any records came in after running the batch. If there are no records in the tab, confirm the batch ran successfully by checking the Apex Jobs.
You may run into errors if the Campaign__c field on the MC Campaign record is blank. Refer to this article Part 3: Mailchimp to Salesforce Integration - Campaign Sync on how to get this field updated automatically.
If everything worked, then we recommend running one more test with the real sync and then you should be ready to go.
Any comments, questions, concerns - let us know in the comments! We would love to hear from you!