+ Start a Discussion

Placing Primary Campaign Source in the Leads Category so it carries through to Opportunities

I am trying to figure out how to make the Primary Campaign Source button in the leads area so that when I convert it just goes through and I don't need to reenter it. I know how to create buttons and new fields, but this does not give me this option of one that carries through. Customer service says they know it can be done with a formula, but don't know how to do it so they suggested this board.

Are you saying you want to set which campaign should be the primary campagin source on the opportunity once the lead is converted?


The primary campaign source on the opportunity is defaulted to the last campaign associated with a lead.  This can't be changed programatically as I believe it'sa formula based on the Campagin Member created date.


One way to change it automatically is to use an Opportunity before insert trigger to change primary campaign source to the desired campaign.


If this is what you're looking to do, I can help with the syntax.


I am trying to make it so that when you enter the lead, you can select the Primary Campaign Source then so that when you convert, it carries through to all the other fields. That way when I run a report at the end of the month, I can see how many people bought using the internet for example.


On the Leads page there is a Lead Source Button, it would be nice if that button was the Primary Campaign Source so that when I ran the report it pulled the Campaign info for comparison.


I have figured this out and found the button that was required. This wasn't that hard, customer service should know how to do this.




Would you mind sharing your methodology and (if applicable) your code?


Did you ever find out how to do this? I'm trying to almost the same thing. I just need a primary campaign source on the lead.






When a lead is converted, I want to set primary campaign source to be the first campaign that the lead responded to.


I am not sure it this is possible....


1. The "before insert" on Opportunity doesn't work, because Opportunity Id is not available. I cannot go to a campaignmember and find a lead whose convertedOpportunityId is this opp. In any case, the sequence of operations in #2 would apply .

2. Seems like the lead gets updated to converted status with convertedOpportunityId field set AFTER Oppoturnity is created. So the execution sequence in SFDC is probably, an account, contact, opportunity, followed by lead update,followed by campaign member update. 

3. I did an "after update trigger" on lead. see code below. It works, but is has strange consequences that are explained in #4.

4. Let's say lead is part of campaigns C1 and C2 and it first responded to C1. Without my code, I would see C1 and C2 in Campaign Influence related list with C2 marked as primary campaign source. With my code, now I see two entries for C1 and one for C2. One entry for C2 has Contact on it, but is not marked primary campaign source, the second entry for C2 has NO contact on it, and is marked primary.




trigger setPrimaryCampaignOnOpportunityOnLeadConvert on Lead (after update) {
    Map<Id,Id> convertedLeadIdToOpportunityIdMap = new Map <Id,Id> (); 
    Lead[] OldLeads = Trigger.old;
    Lead[] newLeads = Trigger.new;
    for (integer i=0; i < newLeads.size(); i++) {
        Lead newLead = newLeads[i];
        Lead oldLead = oldLeads[i];  
        System.Debug('New Lead converted ' + newLead.isConverted); 
        if (newLead.isConverted && !oldLead.isConverted && newLead.convertedOpportunityId != null) {
            convertedLeadIdToOpportunityIdMap.put(newLead.id, newLead.convertedOpportunityId);        
    if (convertedLeadIdToOpportunityIdMap.size() == 0) return;
    CampaignMember[] cMembers = [select CampaignId, LeadId, Lead.isConverted from CampaignMember where Is_Primary_Campaign__c = true AND LeadId in :convertedLeadIdToOpportunityIdMap.KeySet()];
    System.Debug('cMembers is ' + cMembers);    
    Map<Id,Id> leadToPrimaryCampaignMap = new Map<Id,Id> ();
    for (CampaignMember cMember:cMembers) {
    Opportunity[] OppsToUpdate = new Opportunity[0];
    for (Id LeadId:convertedLeadIdToOpportunityIdMap.KeySet()) {
    	Opportunity opp = new Opportunity(Id = convertedLeadIdToOpportunityIdMap.get(LeadId));
    	opp.CampaignId = leadToPrimaryCampaignMap.get(LeadId);
    update OppsToUpdate;







So I thought of a solution, but it would appear to me that SFDC has a bug somewhere.


I created a "Primary Campaign" field on Lead that points to an Opportunity. On Opportunity, I created the same field. On lead conversion, I do field mapping of this field. In before insert trigger, I copy the Opportunity's Primary Campaign Field to the CampaignId field.


So let's says we had Campaign C1 and C2. Since the lead responded to C1, the end result is that I set opportunity's campaignId field to be this value.


When I go to the opportunity detail page, it shows C1 as Primary Campaign Source, BUT in the campaign influence related list, I see the that C2 has "Primary Campaign Source" field checked, not C1 as it should be.  The Campaign Influence reports also show C2 as primary campaign source. This messes up the reporting.


Note that when I go on the Campaign Page, it appears to be correct - i.e in the Opportunity Related list for C1, I see the opportunity, but not on C2's Opportunity related list.



Sorry for the delay - I haven't had time to test your code, but it sounds like the concern is that the Campagin is duped in Campaign influence, which looks weird.  The dupes shouldn't impact any actual reporting numbers as they should be removed, but I can see you wanting to avoid them.


btw-it doesn't look like you sorted on FirstRespondedDate below, so I'm not sure that your code below will do what you want.


One work around is to try moving the code to @future, and grabbing the Campaign based on CampaignMembers where leadId=Id of the converted lead.

1) Collect Set<Id> convertedLeadIds=new Set<Id>(), and get all of the leads where isConverted=TRUE;  If possible, also send the Map of LeadId to OpptyId (not sure if you can send maps to @future) - this saves a query later and speeds it up

2) Send that set of Ids to the @future method in another class

3) Query for CampaignMember[] cms=[SELECT ID, CampaignId, FirstRespondedDate FROM CampaignMember WHERE LeadId IN: convertedLeadIds];  There's a chance this won't work because they are converted, but pretty sure it should work fine as we still save the old convertedLeadId on campaignMember even after conversion

4) Now you need to loop through the cms for each lead, and for each lead, determine which cm has the earliest first respondedDate.  The output should be one campaignId for each LeadId

5) Grab the opptys for each lead id, and update primaryCampaignSource with that campaignId

6) Update the oppty


The downside of @future is that you dont' see the results immediately, but the campaign would be updated on the next page refresh.




Thanks for your comment. If you look at my code, I have a Is_Primary_Campaign flag on the CampaignMember - this flag is already correctly set for the campaign to which the lead responded first.


I don't think the @future code will solve the issue


Fundamentally, SFDC seems to have a bug/limitation. I have filed case number (08142809) with SFDC. . I wrote the code two different ways (first one posted in my first post), and both lead to issues. In the first case double counting, in another case plain wrong. 


If you look at this idea, it also highlights the double counting in Campaign Influence - see kkorynta 's screen shot on page 2 of the idea. Our reports don't work correctly due to this issue.