Auto-Create Campaign Members for New Leads

After you finish reading this, check out a newer post that “bulkifies” the trigger.

I created a simple & very useful Apex script that will auto-create Campaign Members for me when new leads are entered manually or via Web to Lead IF the Lead Source value matches the Name of a Campaign record I have in my Salesforce database.  If there is no match, then the code finishes.

This is useful for me because I get Leads sent to me everytime someone Test Drives, Installs or clicks Contact Me on an Arrowpointe AppExchange product.  I will typically get duplicates in my org, which I go about merging.  If I don’t have Campaign Member records, I lose sight of all the activity someone did on AppExchange across my apps!  With Campaign Members populated, I can have a record of someone test driving Auto vCard and then installing it, then test driving User Adoption Dashboard and then installing it and then test driving Arrowpointe Maps and so on. Also, using Campaign Members, I am essentially compiling an easily accessible list of people who have performed certain actions on my AppExchange apps.

Up until now, I was manually creating Campaign Members and then merging my Leads.  However, now I let Salesforce take care of the tedious Campaign Member creation (I still do the merging).

The code is simple and is officially living on the Arrowpointe Google Code site.  The code isn’t likely to change anytime soon, so I am posting a working copy here for you. This is a useful script to have in your quiver in case you need it. The nice thing is that the trigger only takes effect when there is a match. Thus, in order to get it working for a specific Lead Source, all you need to do is create a Campaign with a matching name. Voila!


trigger Create_CampaignMember_For_New_Leads on Lead (after insert) {

	try {	
		if ( == 1) {
			List <CampaignMember> cm = new list<CampaignMember>();
			for(Lead L : {
					String cname = L.leadsource;
					// Added for AppExchange Partners that get leads via AppExchange where Salesforce added the "dup-" term to signify a duplicate
					String replaceText2 = 'dup-';
					cname = cname.replace(replaceText2,'');
					List <Campaign> c = [select id, name from Campaign where name = :cname limit 1];
						CampaignMember cml = new CampaignMember();
						cml.campaignid = c[0].id;
						cml.leadid =;
				insert cm;
	} catch(Exception e) {
		system.debug ('error: ' + e.getMessage() );

Test Class

public class Create_CampaignMember_For_New_Leads {

	static testMethod void Create_CampaignMember_For_New_Leads() {
			List <Lead> Leads;
			// Create a Lead with a Lead Source matching a Campaign
			Lead L1 = new Lead();
			L1.lastname = 'Create_CampaignMember_For_New_Leads';
			L1.firstname = 'Test For'; = 'Company Name';
			L1.leadsource = 'Web'; // Make sure you have an active Campaign with this name
			insert L1;
			String holder =;
			List <CampaignMember> cm = [select id from CampaignMember where leadid = :holder limit 1];
			// Create a Lead without a Lead Source matching a Campaign
			Lead L2 = new Lead();
			L2.lastname = 'Create_CampaignMember_For_New_Leads';
			L2.firstname = 'Test For'; = 'Company Name';
			L2.leadsource = 'No Matching Campaign'; // Make sure you DON'T have an active Campaign with this name 
			insert L2;
			String holder2 =;
			List <CampaignMember> cm2 = [select id from CampaignMember where leadid = :holder2 limit 1];

Let me know what you think, if I am doing anything inefficiently and other suggestions you might have. This is my first foray into Apex Code, so I had to start simple.


  1. Steve Andersen Said,

    June 19, 2008 @ 6:58 pm

    Nice work Scott!

    I’ve got a similar trigger–I’m actually passing in the Campaign Id since I’m in control of my Lead forms.

    The only thing I would say is you could make it bulk safe so that it works for batches up to 200. The main trick with balk-safing your triggers is pulling all your SOQL and DML statements out of loops. You only get 20 DML statements and I can’t recall right now how many SOQL statements.

    It’s possible in almost all cases to make stuff bulk safe, but it sure makes the code more complex and harder to understand! In this case you’d have to collect all your LeadSources in a Set and then do a SOQL for all the campaigns where the name is in that set. Then that result would have to be in a Map so you can make the “join” between the Lead and the Campaign Id.

    I’m sure you’ve looked into this already since you’ve got the protection in there so it won’t run in bulk.

    Congrats on the nice piece on the wiki! You’ve earned it!

  2. Scott Hemmeter Said,

    June 26, 2008 @ 9:11 am


    Thanks for the bulk safe tips. I will modify.

    I assume you know that you can include Campaign ID and Member Status in the HTML your web to lead forms and have that information populated without Apex, right? This solution will essentially let you have a specific campaign in your HTML (ABC Campaign – Landing Page XYX) and have a Campaign populated by Apex based upon lead source (e.g. Web Campaigns). The end result is a new lead with 2 Campaigns associated to it.

  3. Bookmarks about Appexchange Said,

    August 20, 2008 @ 3:15 pm

    […] – bookmarked by 1 members originally found by maizanessarox on 2008-08-06 Auto-Create Campaign Members for New Leads – bookmarked by […]

  4. Hudi Said,

    December 3, 2009 @ 7:23 pm

    Thanks for the info Scott,
    Is there any way to do this for multiple campaigns at one time? Can it be done using custom checkboxes instead of the lead source page?

  5. Scott Hemmeter Said,

    December 10, 2009 @ 3:01 pm

    @Hudi, it can absolutely be done for multiple campaigns. The code would be totally different, but you can make a trigger key off of anything. The example in this post was about matching up lead source with campaign name.

  6. Bo Laurent Said,

    April 3, 2011 @ 3:03 pm

    Hmm. I would also suggest that it is never a good idea to catch all exceptions and then just smother them. If you are debugging, you can find the exception in the logs. If you are not debugging, you should not catch an exception unless you are going to resolve it or rethrow it.

RSS feed for comments on this post