function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Jean Grey 10Jean Grey 10 

Trigger add contact to campaign

I'm working on a trigger to add contacts to a campaign based on temporary fields stored on the contact. This is working for new campaign members inserted, but I need to update the status on the campaign member record if it changes on the contact. I understand I need to update the existing campaign member rather than try to insert a new one, but I'm unsure how to go about that. Here is my code:
 
trigger addToCampaignContact on Contact (after insert, after update) {
	public List<CampaignMember> cmList = new List<CampaignMember>();
    public Set<Id> conSet = new Set<Id>();
    public List<Contact> conList = new List<Contact>();

	//create list of contact members to add
	for(Contact c:Trigger.New){
        if(c.Campaign_Id__c != NULL && c.Member_Status__c != NULL){
            conSet.add(c.Id);
        
        cmList.add( new CampaignMember(
            CampaignId = c.Campaign_Id__c,
            ContactId = c.Id,
            Status = c.Member_Status__c,
            UTM_Name__c = c.UTM_Campaign_Name__c,
            Content__c= c.UTM_Content__c,
            Medium__c=c.UTM_Medium__c,
            Source__c=c.UTM_Source__c,
            UTM_Term__c=c.UTM_Term__c
            ));
        }}
    system.debug('insert cmList '+cmList);
    if(!cmList.isEmpty()){
    insert cmList;}
}

/*    
    //update contacts back to null to prep for future campaign
    conList = [SELECT Id, Campaign_Id__c, Member_Status__c, UTM_Campaign_Name__c 
               FROM Contact WHERE Id IN :conSet];
    for(Contact c:conList){
        c.Campaign_Id__c=NULL;
        c.Member_Status__c=NULL;
        c.UTM_Source__c=NULL;
        c.UTM_Medium__c=NULL;
        c.UTM_Campaign_Name__c=NULL;
        c.UTM_Content__c=NULL;
        c.UTM_Term__c=NULL;
    }
    system.debug('update conList '+conList);
    //update conList;
    */
Error when I try to update the member status field on the contact to update the campaign member: 
Error:Apex trigger addToCampaignContact caused an unexpected exception, contact your administrator: addToCampaignContact: execution of AfterUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: DUPLICATE_VALUE, Already a campaign member.: []: Trigger.addToCampaignContact: line 32, column 1

Any help is much appreciated!
Best Answer chosen by Jean Grey 10
Steven NsubugaSteven Nsubuga
I made some changes to the update code
trigger addToCampaignContact on Contact (after insert, after update) {
    public List<CampaignMember> cmList = new List<CampaignMember>();
    public Set<Id> conSet = new Set<Id>();
    public List<Contact> conUpdate = new List<Contact>();
    public List<Contact> conList = new List<Contact>();

    try{
        //create list of contact members to add to campaign
        if(Trigger.IsInsert){
        for(Contact c:Trigger.New){
            
            if(c.Campaign_Id__c != NULL && c.Member_Status__c != NULL){
                conSet.add(c.Id);
                conList.add(new Contact(
                Id=c.Id));
            
            cmList.add( new CampaignMember(
                CampaignId = c.Campaign_Id__c,
                ContactId = c.Id,
                Status = c.Member_Status__c,
                UTM_Name__c = c.UTM_Campaign_Name__c,
                Content__c= c.UTM_Content__c,
                Medium__c=c.UTM_Medium__c,
                Source__c=c.UTM_Source__c,
                UTM_Term__c=c.UTM_Term__c
                ));
            }}
        system.debug('insert cmList '+cmList);
        if(!cmList.isEmpty()){
        insert cmList;}
    }
        //update existing campaign members if Status or UTM parameters change
        else if(Trigger.IsUpdate){
            

			Set<Id> contactIdSet = new Set<Id>();
            for(Id cId : Trigger.newMap.keySet()){
                if(Trigger.oldMap.get(cId).Member_Status__c != Trigger.newMap.get(cId).Member_Status__c ||
                   Trigger.oldMap.get(cId).UTM_Campaign_Name__c != Trigger.newMap.get(cId).UTM_Campaign_Name__c ||
                   Trigger.oldMap.get(cId).UTM_Content__c != Trigger.newMap.get(cId).UTM_Content__c ||
                   Trigger.oldMap.get(cId).UTM_Medium__c != Trigger.newMap.get(cId).UTM_Medium__c ||
                   Trigger.oldMap.get(cId).UTM_Source__c != Trigger.newMap.get(cId).UTM_Source__c ||
                   Trigger.oldMap.get(cId).UTM_Term__c != Trigger.newMap.get(cId).UTM_Term__c){
					   
					contactIdSet.add(cId);   
                }
			}
			cmList=[SELECT Id, CampaignId,ContactId,Status,UTM_Name__c,Content__c,Medium__c,Source__c,UTM_Term__c
                   FROM CampaignMember WHERE ContactId IN :contactIdSet];	
			for(CampaignMember cm : cmList){
				Contact c = Trigger.NewMap.get(cm.ContactId);
				cm.CampaignId = c.Campaign_Id__c;
				cm.Status = c.Member_Status__c;
				cm.UTM_Name__c = c.UTM_Campaign_Name__c;
				cm.Content__c= c.UTM_Content__c;
				cm.Medium__c=c.UTM_Medium__c;
				cm.Source__c=c.UTM_Source__c;
				cm.UTM_Term__c=c.UTM_Term__c;
			}
			update cmList;
        }
    }
    catch(Exception e){
        system.debug('exception: '+e);
    }
    try{
                //update contacts back to null to prep for future campaign
        for(Contact c:conList){
            conUpdate.add(new Contact(
                Id = c.Id,
                Campaign_Id__c=NULL,
                Member_Status__c=NULL,
                UTM_Source__c=NULL,
                UTM_Medium__c=NULL,
                UTM_Campaign_Name__c=NULL,
                UTM_Content__c=NULL,
                UTM_Term__c=NULL
                ));
        }
        system.debug('update conUpdate '+conUpdate);
        update conUpdate;
    }
    catch(Exception e){
        system.debug('exception: '+e);
    }
}

 

All Answers

Steven NsubugaSteven Nsubuga
Hi Jean, try this
trigger addToCampaignContact on Contact (after insert, after update) {
	public List<CampaignMember> cmList = new List<CampaignMember>();
    public Set<Id> conSet = new Set<Id>();
    public List<Contact> conList = new List<Contact>();

	//create list of contact members to add
	if (Trigger.IsInsert) {
		for(Contact c : Trigger.New){
			if(c.Campaign_Id__c != NULL && c.Member_Status__c != NULL){
				conSet.add(c.Id);
			
			cmList.add( new CampaignMember(
				CampaignId = c.Campaign_Id__c,
				ContactId = c.Id,
				Status = c.Member_Status__c,
				UTM_Name__c = c.UTM_Campaign_Name__c,
				Content__c= c.UTM_Content__c,
				Medium__c=c.UTM_Medium__c,
				Source__c=c.UTM_Source__c,
				UTM_Term__c=c.UTM_Term__c
				));
			}}
		system.debug('insert cmList '+cmList);
		if(!cmList.isEmpty()){
		insert cmList;}
	
	}
	else if (Trigger.IsUpdate) {
		cmList = [SELECT Id, CampaignId, ContactId, Status, UTM_Name__c,Content__c, Medium__c,Source__c, UTM_Term__c
					FROM CampaignMember WHERE ContactId IN Trigger.NewMap.keyset()];
					
		for(CampaignMember cm : cmList){
			Contact c = Trigger.NewMap.get(cm.ContactId);
			cm.CampaignId = c.Campaign_Id__c;
			cm.Status = c.Member_Status__c;
			cm.UTM_Name__c = c.UTM_Campaign_Name__c;
			cm.Content__c= c.UTM_Content__c;
			cm.Medium__c=c.UTM_Medium__c;
			cm.Source__c=c.UTM_Source__c;
			cm.UTM_Term__c=c.UTM_Term__c;
		}
		update cmList;
	}
}

 
Jean Grey 10Jean Grey 10
Thanks so much for your input. The insert works great but the update does not work. The field changes on the Contact but nothing happens to the campaign member record. Here is my full code: 
trigger addToCampaignContact on Contact (after insert, after update) {
    public List<CampaignMember> cmList = new List<CampaignMember>();
    public Set<Id> conSet = new Set<Id>();
    public List<Contact> conUpdate = new List<Contact>();
    public List<Contact> conList = new List<Contact>();

    try{
        //create list of contact members to add to campaign
        if(Trigger.IsInsert){
        for(Contact c:Trigger.New){
            
            if(c.Campaign_Id__c != NULL && c.Member_Status__c != NULL){
                conSet.add(c.Id);
                conList.add(new Contact(
                Id=c.Id));
            
            cmList.add( new CampaignMember(
                CampaignId = c.Campaign_Id__c,
                ContactId = c.Id,
                Status = c.Member_Status__c,
                UTM_Name__c = c.UTM_Campaign_Name__c,
                Content__c= c.UTM_Content__c,
                Medium__c=c.UTM_Medium__c,
                Source__c=c.UTM_Source__c,
                UTM_Term__c=c.UTM_Term__c
                ));
            }}
        system.debug('insert cmList '+cmList);
        if(!cmList.isEmpty()){
        insert cmList;}
    }
        //update existing campaign members if Status or UTM parameters change
        else if(Trigger.IsUpdate){
            cmList=[SELECT Id, CampaignId,ContactId,Status,UTM_Name__c,Content__c,Medium__c,Source__c,UTM_Term__c
                   FROM CampaignMember WHERE ContactId IN :Trigger.NewMap.keyset()];

            for(Id cId : Trigger.newMap.keySet() ){
                if(Trigger.oldMap.get(cId).Member_Status__c != Trigger.newMap.get(cId).Member_Status__c ||
                   Trigger.oldMap.get(cId).UTM_Campaign_Name__c != Trigger.newMap.get(cId).UTM_Campaign_Name__c ||
                   Trigger.oldMap.get(cId).UTM_Content__c != Trigger.newMap.get(cId).UTM_Content__c ||
                   Trigger.oldMap.get(cId).UTM_Medium__c != Trigger.newMap.get(cId).UTM_Medium__c ||
                   Trigger.oldMap.get(cId).UTM_Source__c != Trigger.newMap.get(cId).UTM_Source__c ||
                   Trigger.oldMap.get(cId).UTM_Term__c != Trigger.newMap.get(cId).UTM_Term__c){
                        
                for(CampaignMember cm : cmList){
                    Contact c = Trigger.NewMap.get(cm.ContactId);
                    cm.CampaignId = c.Campaign_Id__c;
                    cm.Status = c.Member_Status__c;
                    cm.UTM_Name__c = c.UTM_Campaign_Name__c;
                    cm.Content__c= c.UTM_Content__c;
                    cm.Medium__c=c.UTM_Medium__c;
                    cm.Source__c=c.UTM_Source__c;
                    cm.UTM_Term__c=c.UTM_Term__c;
        }}}
        update cmList;
        }
    }
    catch(Exception e){
        system.debug('exception: '+e);
    }
    try{
                //update contacts back to null to prep for future campaign
        for(Contact c:conList){
            conUpdate.add(new Contact(
                Id = c.Id,
                Campaign_Id__c=NULL,
                Member_Status__c=NULL,
                UTM_Source__c=NULL,
                UTM_Medium__c=NULL,
                UTM_Campaign_Name__c=NULL,
                UTM_Content__c=NULL,
                UTM_Term__c=NULL
                ));
        }
        system.debug('update conUpdate '+conUpdate);
        update conUpdate;
    }
    catch(Exception e){
        system.debug('exception: '+e);
    }
}

 
Steven NsubugaSteven Nsubuga
I made some changes to the update code
trigger addToCampaignContact on Contact (after insert, after update) {
    public List<CampaignMember> cmList = new List<CampaignMember>();
    public Set<Id> conSet = new Set<Id>();
    public List<Contact> conUpdate = new List<Contact>();
    public List<Contact> conList = new List<Contact>();

    try{
        //create list of contact members to add to campaign
        if(Trigger.IsInsert){
        for(Contact c:Trigger.New){
            
            if(c.Campaign_Id__c != NULL && c.Member_Status__c != NULL){
                conSet.add(c.Id);
                conList.add(new Contact(
                Id=c.Id));
            
            cmList.add( new CampaignMember(
                CampaignId = c.Campaign_Id__c,
                ContactId = c.Id,
                Status = c.Member_Status__c,
                UTM_Name__c = c.UTM_Campaign_Name__c,
                Content__c= c.UTM_Content__c,
                Medium__c=c.UTM_Medium__c,
                Source__c=c.UTM_Source__c,
                UTM_Term__c=c.UTM_Term__c
                ));
            }}
        system.debug('insert cmList '+cmList);
        if(!cmList.isEmpty()){
        insert cmList;}
    }
        //update existing campaign members if Status or UTM parameters change
        else if(Trigger.IsUpdate){
            

			Set<Id> contactIdSet = new Set<Id>();
            for(Id cId : Trigger.newMap.keySet()){
                if(Trigger.oldMap.get(cId).Member_Status__c != Trigger.newMap.get(cId).Member_Status__c ||
                   Trigger.oldMap.get(cId).UTM_Campaign_Name__c != Trigger.newMap.get(cId).UTM_Campaign_Name__c ||
                   Trigger.oldMap.get(cId).UTM_Content__c != Trigger.newMap.get(cId).UTM_Content__c ||
                   Trigger.oldMap.get(cId).UTM_Medium__c != Trigger.newMap.get(cId).UTM_Medium__c ||
                   Trigger.oldMap.get(cId).UTM_Source__c != Trigger.newMap.get(cId).UTM_Source__c ||
                   Trigger.oldMap.get(cId).UTM_Term__c != Trigger.newMap.get(cId).UTM_Term__c){
					   
					contactIdSet.add(cId);   
                }
			}
			cmList=[SELECT Id, CampaignId,ContactId,Status,UTM_Name__c,Content__c,Medium__c,Source__c,UTM_Term__c
                   FROM CampaignMember WHERE ContactId IN :contactIdSet];	
			for(CampaignMember cm : cmList){
				Contact c = Trigger.NewMap.get(cm.ContactId);
				cm.CampaignId = c.Campaign_Id__c;
				cm.Status = c.Member_Status__c;
				cm.UTM_Name__c = c.UTM_Campaign_Name__c;
				cm.Content__c= c.UTM_Content__c;
				cm.Medium__c=c.UTM_Medium__c;
				cm.Source__c=c.UTM_Source__c;
				cm.UTM_Term__c=c.UTM_Term__c;
			}
			update cmList;
        }
    }
    catch(Exception e){
        system.debug('exception: '+e);
    }
    try{
                //update contacts back to null to prep for future campaign
        for(Contact c:conList){
            conUpdate.add(new Contact(
                Id = c.Id,
                Campaign_Id__c=NULL,
                Member_Status__c=NULL,
                UTM_Source__c=NULL,
                UTM_Medium__c=NULL,
                UTM_Campaign_Name__c=NULL,
                UTM_Content__c=NULL,
                UTM_Term__c=NULL
                ));
        }
        system.debug('update conUpdate '+conUpdate);
        update conUpdate;
    }
    catch(Exception e){
        system.debug('exception: '+e);
    }
}

 
This was selected as the best answer
Jean Grey 10Jean Grey 10
I added a set for Campaigns and used it in the if statement to prevent multiple campaign members from being overwritten. It's working perfectly, thank you!
Steven NsubugaSteven Nsubuga
You're welcome Jean!
Jean Grey 10Jean Grey 10
EDIT: After some additional testing I can see that the first loop is only adding campaign members for brand new records, it will not add an existing contact to a new campaign. To move forward with deployment as scheduled, I've commented out the second section and will just worry about new campaign members for now. I'll keep working on the second section and post an update if I figure it out. Thanks for all your help!
 
trigger addToCampaignContact on Contact (after insert, after update) {
    public List<CampaignMember> cmList = new List<CampaignMember>();
    public Set<Id> campSet = new Set<Id>();
    public Set<Id> conSet = new Set<Id>();
    public List<Contact> conUpdate = new List<Contact>();
    public List<Contact> conList = new List<Contact>();

    try{
        //create list of contact members to add to campaign
        if(Trigger.IsInsert || Trigger.IsUpdate){
        for(Contact c:Trigger.New){
            
            if(c.Campaign_Id__c != NULL && c.Member_Status__c != NULL){
                conSet.add(c.Id);
                campSet.add(c.Campaign_Id__c);
                conList.add(new Contact(
                Id=c.Id));
            
            cmList.add( new CampaignMember(
                CampaignId = c.Campaign_Id__c,
                ContactId = c.Id,
                Status = c.Member_Status__c,
                UTM_Name__c = c.UTM_Campaign_Name__c,
                Content__c= c.UTM_Content__c,
                Medium__c=c.UTM_Medium__c,
                Source__c=c.UTM_Source__c,
                UTM_Term__c=c.UTM_Term__c
                ));
            }}
        system.debug('upsert cmList '+cmList);
        if(!cmList.isEmpty()){
        upsert cmList;}
    }
        /*
        //update existing campaign members if Status or UTM parameters change
        else if(Trigger.IsUpdate){
            Set<Id> contactIdSet = new Set<Id>();
            for(Id cId : Trigger.newMap.keySet()){
                if(Trigger.oldMap.get(cId).Member_Status__c != Trigger.newMap.get(cId).Member_Status__c ||
                   Trigger.oldMap.get(cId).UTM_Campaign_Name__c != Trigger.newMap.get(cId).UTM_Campaign_Name__c ||
                   Trigger.oldMap.get(cId).UTM_Content__c != Trigger.newMap.get(cId).UTM_Content__c ||
                   Trigger.oldMap.get(cId).UTM_Medium__c != Trigger.newMap.get(cId).UTM_Medium__c ||
                   Trigger.oldMap.get(cId).UTM_Source__c != Trigger.newMap.get(cId).UTM_Source__c ||
                   Trigger.oldMap.get(cId).UTM_Term__c != Trigger.newMap.get(cId).UTM_Term__c){
                       contactIdSet.add(cId);
                       campSet.add(Trigger.newMap.get(cId).Campaign_Id__c);
                }
            }
            cmList=[SELECT Id, CampaignId,ContactId,Status,UTM_Name__c,Content__c,Medium__c,Source__c,UTM_Term__c
                   FROM CampaignMember WHERE ContactId IN :contactIdSet and CampaignId IN :campSet];   
            for(CampaignMember cm : cmList){
                Contact c = Trigger.NewMap.get(cm.ContactId);
                cm.Status = c.Member_Status__c;
                cm.UTM_Name__c = c.UTM_Campaign_Name__c;
                cm.Content__c= c.UTM_Content__c;
                cm.Medium__c=c.UTM_Medium__c;
                cm.Source__c=c.UTM_Source__c;
                cm.UTM_Term__c=c.UTM_Term__c;
            }
            system.debug('contactIdSet '+contactIdSet);
            system.debug('campSet '+campSet);
            system.debug('update cmList '+cmList);
            update cmList;
            system.debug('cmList after update '+cmList);
        }
*/
    }
    catch(Exception e){
        system.debug('exception: '+e);
    }
    try{
		//update contacts back to null to prep for future campaign
        for(Contact c:conList){
            conUpdate.add(new Contact(
                Id = c.Id,
                Campaign_Id__c=NULL,
                Member_Status__c=NULL,
                UTM_Source__c=NULL,
                UTM_Medium__c=NULL,
                UTM_Campaign_Name__c=NULL,
                UTM_Content__c=NULL,
                UTM_Term__c=NULL
                ));
        }
        system.debug('update conUpdate '+conUpdate);
        update conUpdate;

    }
    catch(Exception e){
        system.debug('exception: '+e);
    }
}