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
Swami DeshanelSwami Deshanel 

How do you remove Primary Campaign Source on Opportunity if Campaign Member Responded is False

I would like to remove primary campaign source from the contact and opportunity on lead conversion unless the lead had Responded to the campaign.  

I tried this trigger, but it doenst work, and i cant figure out why

trigger checkPrimaryCampaignSource on Opportunity (before update) {
for (Opportunity o: Trigger.new) {
Lead l = [SELECT id,converteddate FROM Lead WHERE ConvertedOpportunityId =:o.ID LIMIT 1];
try {
if(l.converteddate!=null){
CampaignMember cm = [Select id,Status, HasResponded FROM campaignmember WHERE LeadId=:l.id AND CampaignId=:o.Campaign.id];
if (cm.HasResponded ==false){
o.CampaignId=null;
}
}
} catch (Exception e){
system.debug('error: ' +e);
}
}



}
Best Answer chosen by Swami Deshanel
CheyneCheyne
Aha, the CampaignMembers query is returning an empty list. Try writing the trigger on the Lead instead. This trigger is working in my developer instance:

trigger checkPrimaryCampaignSource on Lead (after update) {
    //This will be a set of all opportunity IDs for leads that were just converted
    Set<Id> convertedOppIds = new Set<Id>();
    for (Lead l :Trigger.new) {
        if (l.IsConverted == true) {
            convertedOppIds.add(l.ConvertedOpportunityId);
        }
    }
   
    //Now get a set of all of the campaign members related to the converted leads who have not responded to any of the campaigns
    List<CampaignMember> campaignMembers = [SELECT Id, Lead.ConvertedOpportunityId FROM CampaignMember WHERE Lead.ConvertedOpportunityId IN :convertedOppIds AND HasResponded = false];
    //Construct a set of opportunity ids that were converted from leads who did not respond to the campaign
    Set<Id> nonResponsiveOppIds = new Set<Id>();
    for (CampaignMember cm : campaignMembers) {
        nonResponsiveOppIds.add(cm.Lead.ConvertedOpportunityId);
    }
   
    //Now we can get a list of all of the opportunities where we need to remove the primary campaign source
    List<Opportunity> oppsToUpdate = [SELECT CampaignId FROM Opportunity WHERE Id IN :nonResponsiveOppIds];
    for (Opportunity opp : oppsToUpdate) {
        opp.CampaignId = null;
    }
   
    if (oppsToUpdate.size() > 0) {
        update oppsToUpdate;
    }
}

All Answers

CheyneCheyne
If you're trying to update that field at the time the lead is converted, you may have to do an after insert trigger instead of a before update, since the opportunity is just being created when the lead is converted. The trigger will need to fire after insert so that the lead record has the ConvertedOpportunityId. Note that, since this trigger would run after the insert, you'll have to run an update operation on the update opportunities.You're probably going to run into recursive trigger issues, so I would check out this article (http://developer.force.com/cookbook/recipe/controlling-recursive-triggers" target="_blank). 

Also, you should move your SOQL queries to the outside of the loop, so that you don't run into any governor limits. Here is a rough idea of what you might want to do, but keep in mind that you'll have to read the article above to stop this from firing recursively:

trigger checkPrimaryCampaignSource on Opportunity (after insert) {
  //Construct a set of all campaign ids related to opportunities in the trigger
  Set<Id> campaignIds = new Set<Id>();
  for (Opportunity opp : trigger.new) {
    campaignIds.add(opp.CampaignId);
  }
  
  //Now get a list of all of the campaign members who have not responded to any of the campaigns
  CampaignMember campaignMembers = [SELECT Id, Lead.ConvertedOpportunityId FROM CampaignMember WHERE Lead.ConvertedOpportunityId IN :trigger.newMap.keySet() AND HasResponded = false];
  //Construct a set of opportunity ids that were converted from leads who did not respond to the campaign
  Set<Id> nonResponsiveOppIds = new Set<Id>();
  for (CampaignMember cm : campaignMembers) {
    nonResponsiveOppIds.add(cm.Lead.ConvertedOpportunityId);
  }
  
  //Now, go through the opportunities and update them if necessary
  List<Opportunity> oppsToUpdate = new List<Opportunity>();
  for (Opportunity opp : trigger.new) {
    if (nonResponsiveOppIds.contains(opp.Id)) {
      //trigger.new is read only, so we must make a new opportunity
      Opportunity updatedOpp = new Opportuntiy(Id=opp.Id, CampaignId=null);
      oppsToUpdate.add(updatedOpp);
    }
  }
  if (oppsToUpdate.size() > 0) {
    update oppsToUpdate;
  }
}
Swami DeshanelSwami Deshanel
Thanks for your response.   I am having trouble with your code.   I am getting this error:  Error: Compile Error: Loop must iterate over a collection type: SOBJECT:CampaignMember at line 12 column 28
CheyneCheyne
Sorry, you need to define campaignMembers as a List:

List<CampaignMember> campaignMembers = [SELECT Id, Lead.ConvertedOpportunityId FROM CampaignMember WHERE Lead.ConvertedOpportunityId IN :trigger.newMap.keySet() AND HasResponded = false];
Swami DeshanelSwami Deshanel
Again, thanks for your quick response.   I made the change you just mentioned, and now it saves with no errors, but when I tested it in my sandbox, it doesnt do anything.  I tested it by creating a lead, assigning it to a campaign without a responded status, converted the lead and it still had that campaign as the primary campaign source.   
CheyneCheyne
I would add some system.debug statements and then check your logs to see what is going on. Specifically, I would check to see what is in the campaignMembers list and what is in the nonResponseOppIds set. If those are empty, then there might be something wrong with the SOQL query. If they're populated, with the correct opportunity ID, then there must be something going wrong in that second for loop.
Swami DeshanelSwami Deshanel
Unfortunately I am very new to APEX (I can copy someone elses code and modify it to work, usually) and do not know how to do a System.Debug.  
CheyneCheyne
You would add these two lines into your code:

system.debug('Campaign Members ==> ' + campaignMembers);
system.debug('Non-responsive opportunity IDs ==> ' + nonResponseOppIds);

after your first for loop. Then go into Setup -> Monitoring ->Debug Logs (or Setup -> Logs -> Debug Logs if you are in the new Setup), and add a new Monitored User. Then perform an action so that your trigger runs. After that, if you refresh the debug logs page, you should see a new log corresponding to the operation you just performed. Click on View Log and find your debug statements (they should be labeled with user_debug, so you should be able to use CTRL+f in your browser to easily find them). There, you should be able to see what values your variables have and hopefully get to the bottom of what is going wrong.
Swami DeshanelSwami Deshanel
I did as you suggested, but when i look at the log, I dont see anything wrong:

28.0 APEX_CODE,DEBUG;APEX_PROFILING,INFO;CALLOUT,INFO;DB,INFO;SYSTEM,DEBUG;VALIDATION,INFO;VISUALFORCE,INFO;WORKFLOW,INFO
10:06:38.284 (284172000)|ENTERING_MANAGED_PKG|rh2
10:06:38.651 (651706000)|ENTERING_MANAGED_PKG|TRIMDA
10:06:38.682 (682181000)|SOQL_EXECUTE_BEGIN|[27]|Aggregations:0|select Id, Enhanced_Display_DupeStatusAccount__c, SocialCRM_Lead_LinkedIn__c, Send_Notification_on_Complete__c, OnBoarding_Option__c, SocialCRM_Contact_Facebook__c, SocialCRM_Lead_Twitter__c, SocialCRM_Account_GooglePlus__c, DeleteMRAfterConvert__c, MergeExclFields_Acc__c, MergeAppend2Field__c, Merge_Batch_Size_Max__c, Enhanced_Display_DupeStatusContact__c, MergeMultiPickLists__c, SocialCRM_Lead_Facebook__c, MergeCreateActivity__c, SocialCRM_Contact_LinkedIn__c, OwnerId, Merge_Type__c, SocialCRM_Account_Facebook__c, Lead_Show_ActionLink__c, LicenseNo__c, Enable_Batch__c, donotCreateOppty__c, MergeRules_Lead__c, Lead_DD_Trigger_Match_Level__c, OpptyName__c, Account_Enable_DD_Trigger__c, MergeAppendField__c, DeleteMRAfterMerge__c, Notification_Email_Address__c, MergeExclFields_Lead__c, SOQL_Count_Query__c, SocialCRM_Account_Twitter__c, SocialCRM_Contact_GooglePlus__c, Default_isQMerge__c, MergeRules_Con__c, Contact_Enable_DD_Trigger__c, Contact_DS_Match_Level__c, MergeAddNote__c, Account_Show_ActionLink__c, Name, Account_DS_Match_Level__c, Lead_DS_Match_Level__c, Convert_Batch_Size_Max__c, AddlNotification_Email_Address__c, ConvStatus__c, Contact_Show_ActionLink__c, overwriteLeadSource__c, MergeExclFields_Con__c, sendNoti__c, MergeRules_Acc__c, SocialCRM_Account_LinkedIn__c, Owner_of_Note__c, Lead_Enable_DD_Trigger__c, Owner_of_Activity__c, Activity_Closed_Status__c, SocialCRM_Lead_GooglePlus__c, Account_DD_Trigger_Match_Level__c, Contact_DD_Trigger_Match_Level__c, SocialCRM_Contact_Twitter__c from TRIMDA_Parameters__c LIMIT 1
10:06:38.687 (687230000)|SOQL_EXECUTE_END|[27]|Rows:1
10:06:38.809 (809749000)|ENTERING_MANAGED_PKG|TRIMDA
10:06:38.815 (815993000)|SOQL_EXECUTE_BEGIN|[27]|Aggregations:0|select Id, Enhanced_Display_DupeStatusAccount__c, SocialCRM_Lead_LinkedIn__c, Send_Notification_on_Complete__c, OnBoarding_Option__c, SocialCRM_Contact_Facebook__c, SocialCRM_Lead_Twitter__c, SocialCRM_Account_GooglePlus__c, DeleteMRAfterConvert__c, MergeExclFields_Acc__c, MergeAppend2Field__c, Merge_Batch_Size_Max__c, Enhanced_Display_DupeStatusContact__c, MergeMultiPickLists__c, SocialCRM_Lead_Facebook__c, MergeCreateActivity__c, SocialCRM_Contact_LinkedIn__c, OwnerId, Merge_Type__c, SocialCRM_Account_Facebook__c, Lead_Show_ActionLink__c, LicenseNo__c, Enable_Batch__c, donotCreateOppty__c, MergeRules_Lead__c, Lead_DD_Trigger_Match_Level__c, OpptyName__c, Account_Enable_DD_Trigger__c, MergeAppendField__c, DeleteMRAfterMerge__c, Notification_Email_Address__c, MergeExclFields_Lead__c, SOQL_Count_Query__c, SocialCRM_Account_Twitter__c, SocialCRM_Contact_GooglePlus__c, Default_isQMerge__c, MergeRules_Con__c, Contact_Enable_DD_Trigger__c, Contact_DS_Match_Level__c, MergeAddNote__c, Account_Show_ActionLink__c, Name, Account_DS_Match_Level__c, Lead_DS_Match_Level__c, Convert_Batch_Size_Max__c, AddlNotification_Email_Address__c, ConvStatus__c, Contact_Show_ActionLink__c, overwriteLeadSource__c, MergeExclFields_Con__c, sendNoti__c, MergeRules_Acc__c, SocialCRM_Account_LinkedIn__c, Owner_of_Note__c, Lead_Enable_DD_Trigger__c, Owner_of_Activity__c, Activity_Closed_Status__c, SocialCRM_Lead_GooglePlus__c, Account_DD_Trigger_Match_Level__c, Contact_DD_Trigger_Match_Level__c, SocialCRM_Contact_Twitter__c from TRIMDA_Parameters__c LIMIT 1
10:06:38.819 (819655000)|SOQL_EXECUTE_END|[27]|Rows:1
10:06:39.034 (1034117000)|CODE_UNIT_STARTED|[EXTERNAL]|01qZ0000000D8PP|checkPrimaryCampaignSource on Opportunity trigger event AfterInsert for [006Z0000008By3n]
10:06:39.034 (1034452000)|SYSTEM_CONSTRUCTOR_ENTRY|[3]|<init>(Integer)
10:06:39.034 (1034484000)|SYSTEM_CONSTRUCTOR_EXIT|[3]|<init>(Integer)
10:06:39.034 (1034532000)|SYSTEM_METHOD_ENTRY|[4]|LIST<Opportunity>.iterator()
10:06:39.034 (1034768000)|SYSTEM_METHOD_EXIT|[4]|LIST<Opportunity>.iterator()
10:06:39.034 (1034803000)|SYSTEM_METHOD_ENTRY|[4]|system.ListIterator.hasNext()
10:06:39.034 (1034825000)|SYSTEM_METHOD_EXIT|[4]|system.ListIterator.hasNext()
10:06:39.034 (1034928000)|SYSTEM_METHOD_ENTRY|[5]|SET<Id>.add(Object)
10:06:39.034 (1034957000)|SYSTEM_METHOD_EXIT|[5]|SET<Id>.add(Object)
10:06:39.034 (1034968000)|SYSTEM_METHOD_ENTRY|[4]|system.ListIterator.hasNext()
10:06:39.034 (1034981000)|SYSTEM_METHOD_EXIT|[4]|system.ListIterator.hasNext()
10:06:39.035 (1035110000)|SYSTEM_METHOD_ENTRY|[10]|MAP<Id,Opportunity>.keySet()
10:06:39.035 (1035165000)|SYSTEM_METHOD_EXIT|[10]|MAP<Id,Opportunity>.keySet()
10:06:39.035 (1035535000)|SOQL_EXECUTE_BEGIN|[10]|Aggregations:0|select Id, Lead.ConvertedOpportunityId from CampaignMember where (Lead.ConvertedOpportunityId = :tmpVar1 and HasResponded = false)
10:06:39.040 (1040971000)|SOQL_EXECUTE_END|[10]|Rows:0
10:06:39.041 (1041040000)|SYSTEM_CONSTRUCTOR_ENTRY|[12]|<init>(Integer)
10:06:39.041 (1041062000)|SYSTEM_CONSTRUCTOR_EXIT|[12]|<init>(Integer)
10:06:39.041 (1041083000)|SYSTEM_METHOD_ENTRY|[13]|LIST<CampaignMember>.iterator()
10:06:39.041 (1041203000)|SYSTEM_METHOD_EXIT|[13]|LIST<CampaignMember>.iterator()
10:06:39.041 (1041228000)|SYSTEM_METHOD_ENTRY|[13]|system.ListIterator.hasNext()
10:06:39.041 (1041244000)|SYSTEM_METHOD_EXIT|[13]|system.ListIterator.hasNext()
10:06:39.041 (1041262000)|SYSTEM_CONSTRUCTOR_ENTRY|[20]|<init>()
10:06:39.041 (1041277000)|SYSTEM_CONSTRUCTOR_EXIT|[20]|<init>()
10:06:39.041 (1041300000)|SYSTEM_METHOD_ENTRY|[21]|LIST<Opportunity>.iterator()
10:06:39.041 (1041319000)|SYSTEM_METHOD_EXIT|[21]|LIST<Opportunity>.iterator()
10:06:39.041 (1041328000)|SYSTEM_METHOD_ENTRY|[21]|system.ListIterator.hasNext()
10:06:39.041 (1041341000)|SYSTEM_METHOD_EXIT|[21]|system.ListIterator.hasNext()
10:06:39.041 (1041395000)|SYSTEM_METHOD_ENTRY|[22]|SET<Id>.contains(Object)
10:06:39.041 (1041419000)|SYSTEM_METHOD_EXIT|[22]|SET<Id>.contains(Object)
10:06:39.041 (1041432000)|SYSTEM_METHOD_ENTRY|[21]|system.ListIterator.hasNext()
10:06:39.041 (1041445000)|SYSTEM_METHOD_EXIT|[21]|system.ListIterator.hasNext()
10:06:39.041 (1041462000)|SYSTEM_METHOD_ENTRY|[29]|LIST<Opportunity>.size()
10:06:39.041 (1041479000)|SYSTEM_METHOD_EXIT|[29]|LIST<Opportunity>.size()
10:06:39.380 (1041497000)|CUMULATIVE_LIMIT_USAGE
10:06:39.380|LIMIT_USAGE_FOR_NS|(default)|
  Number of SOQL queries: 1 out of 100
  Number of query rows: 0 out of 50000
  Number of SOSL queries: 0 out of 20
  Number of DML statements: 0 out of 150
  Number of DML rows: 0 out of 10000
  Maximum CPU time: 0 out of 10000
  Maximum heap size: 0 out of 6000000
  Number of callouts: 0 out of 10
  Number of Email Invocations: 0 out of 10
  Number of fields describes: 0 out of 100
  Number of record type describes: 0 out of 100
  Number of child relationships describes: 0 out of 100
  Number of picklist describes: 0 out of 100
  Number of future calls: 0 out of 10

10:06:39.380|LIMIT_USAGE_FOR_NS|rh2|
  Number of SOQL queries: 0 out of 100
  Number of query rows: 0 out of 50000
  Number of SOSL queries: 0 out of 20
  Number of DML statements: 0 out of 150
  Number of DML rows: 0 out of 10000
  Maximum CPU time: 0 out of 10000
  Maximum heap size: 0 out of 6000000
  Number of callouts: 0 out of 10
  Number of Email Invocations: 0 out of 10
  Number of fields describes: 0 out of 100
  Number of record type describes: 0 out of 100
  Number of child relationships describes: 0 out of 100
  Number of picklist describes: 0 out of 100
  Number of future calls: 0 out of 10

10:06:39.380|LIMIT_USAGE_FOR_NS|TRIMDA|
  Number of SOQL queries: 2 out of 100
  Number of query rows: 2 out of 50000
  Number of SOSL queries: 0 out of 20
  Number of DML statements: 0 out of 150
  Number of DML rows: 0 out of 10000
  Maximum CPU time: 0 out of 10000
  Maximum heap size: 0 out of 6000000
  Number of callouts: 0 out of 10
  Number of Email Invocations: 0 out of 10
  Number of fields describes: 2 out of 100
  Number of record type describes: 0 out of 100
  Number of child relationships describes: 0 out of 100
  Number of picklist describes: 0 out of 100
  Number of future calls: 0 out of 10

10:06:39.380|CUMULATIVE_LIMIT_USAGE_END

10:06:39.041 (1041578000)|CODE_UNIT_FINISHED|checkPrimaryCampaignSource on Opportunity trigger event AfterInsert for [006Z0000008By3n]
10:06:39.371 (1371418000)|ENTERING_MANAGED_PKG|leadScoring
10:06:39.376 (1376123000)|SOQL_EXECUTE_BEGIN|[328]|Aggregations:0|select Name, leadScoring__Campaign__c, leadScoring__Field_Name__c, leadScoring__Operator__c, leadScoring__Value__c, leadScoring__Score_Change__c from LeadScoringRule__c where (Active__c = true and Type__c = :tmpVar1)
10:06:39.381 (1381944000)|SOQL_EXECUTE_END|[328]|Rows:0
10:06:39.433 (1433245000)|ENTERING_MANAGED_PKG|TRIMDA
10:06:39.439 (1439365000)|SOQL_EXECUTE_BEGIN|[27]|Aggregations:0|select Id, Enhanced_Display_DupeStatusAccount__c, SocialCRM_Lead_LinkedIn__c, Send_Notification_on_Complete__c, OnBoarding_Option__c, SocialCRM_Contact_Facebook__c, SocialCRM_Lead_Twitter__c, SocialCRM_Account_GooglePlus__c, DeleteMRAfterConvert__c, MergeExclFields_Acc__c, MergeAppend2Field__c, Merge_Batch_Size_Max__c, Enhanced_Display_DupeStatusContact__c, MergeMultiPickLists__c, SocialCRM_Lead_Facebook__c, MergeCreateActivity__c, SocialCRM_Contact_LinkedIn__c, OwnerId, Merge_Type__c, SocialCRM_Account_Facebook__c, Lead_Show_ActionLink__c, LicenseNo__c, Enable_Batch__c, donotCreateOppty__c, MergeRules_Lead__c, Lead_DD_Trigger_Match_Level__c, OpptyName__c, Account_Enable_DD_Trigger__c, MergeAppendField__c, DeleteMRAfterMerge__c, Notification_Email_Address__c, MergeExclFields_Lead__c, SOQL_Count_Query__c, SocialCRM_Account_Twitter__c, SocialCRM_Contact_GooglePlus__c, Default_isQMerge__c, MergeRules_Con__c, Contact_Enable_DD_Trigger__c, Contact_DS_Match_Level__c, MergeAddNote__c, Account_Show_ActionLink__c, Name, Account_DS_Match_Level__c, Lead_DS_Match_Level__c, Convert_Batch_Size_Max__c, AddlNotification_Email_Address__c, ConvStatus__c, Contact_Show_ActionLink__c, overwriteLeadSource__c, MergeExclFields_Con__c, sendNoti__c, MergeRules_Acc__c, SocialCRM_Account_LinkedIn__c, Owner_of_Note__c, Lead_Enable_DD_Trigger__c, Owner_of_Activity__c, Activity_Closed_Status__c, SocialCRM_Lead_GooglePlus__c, Account_DD_Trigger_Match_Level__c, Contact_DD_Trigger_Match_Level__c, SocialCRM_Contact_Twitter__c from TRIMDA_Parameters__c LIMIT 1
10:06:39.442 (1442935000)|SOQL_EXECUTE_END|[27]|Rows:1
CheyneCheyne
Aha, the CampaignMembers query is returning an empty list. Try writing the trigger on the Lead instead. This trigger is working in my developer instance:

trigger checkPrimaryCampaignSource on Lead (after update) {
    //This will be a set of all opportunity IDs for leads that were just converted
    Set<Id> convertedOppIds = new Set<Id>();
    for (Lead l :Trigger.new) {
        if (l.IsConverted == true) {
            convertedOppIds.add(l.ConvertedOpportunityId);
        }
    }
   
    //Now get a set of all of the campaign members related to the converted leads who have not responded to any of the campaigns
    List<CampaignMember> campaignMembers = [SELECT Id, Lead.ConvertedOpportunityId FROM CampaignMember WHERE Lead.ConvertedOpportunityId IN :convertedOppIds AND HasResponded = false];
    //Construct a set of opportunity ids that were converted from leads who did not respond to the campaign
    Set<Id> nonResponsiveOppIds = new Set<Id>();
    for (CampaignMember cm : campaignMembers) {
        nonResponsiveOppIds.add(cm.Lead.ConvertedOpportunityId);
    }
   
    //Now we can get a list of all of the opportunities where we need to remove the primary campaign source
    List<Opportunity> oppsToUpdate = [SELECT CampaignId FROM Opportunity WHERE Id IN :nonResponsiveOppIds];
    for (Opportunity opp : oppsToUpdate) {
        opp.CampaignId = null;
    }
   
    if (oppsToUpdate.size() > 0) {
        update oppsToUpdate;
    }
}
This was selected as the best answer
Swami DeshanelSwami Deshanel
You are a Genius!  Thank You
CheyneCheyne
Glad I could help :)
Swami DeshanelSwami Deshanel
You dont happen to have a test class i for this one did you?
CheyneCheyne
@isTest
private class TestCheckPrimaryCampaignSource {
    static testMethod void testCheckPrimaryCampaignSource() {
        //Create Lead, Campaign, and CampaignMember
        Lead l = new Lead(LastName='Test', Company='Test');
        insert l;
        Campaign c = new Campaign(Name='Test Campaign', IsActive=true);
        insert c;
        CampaignMember cm = new CampaignMember(LeadId=l.Id, CampaignId=c.Id, Status='Sent');
        insert cm;
       
        //Convert the lead
        Database.LeadConvert lc = new Database.LeadConvert();
        lc.setLeadId(l.id);
       
        LeadStatus convertStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];
        lc.setConvertedStatus(convertStatus.MasterLabel);
       
        Database.LeadConvertResult lcr = Database.convertLead(lc);
       
        //Check that the new Opportunity has an empty CampaignId
        Opportunity opp = [SELECT CampaignId FROM Opportunity WHERE Id = :lcr.opportunityId];
        system.assertEquals(null, opp.CampaignId);
    }
}
Swami DeshanelSwami Deshanel
Thanks again!  I had to modify it to insert some data to satisfy a few validation rules, and now it works perfectly. 
Swami DeshanelSwami Deshanel
Im not sure if this is even possible or not, but on the trigger you helped me with, if the most recently associated campaign does not equal responded, then it clears he primary campaign source.  Which is exactly what i asked for.  But if the lead had responded to an earlier campaign, but not the most recently assoicated campaign, is there any way to have the primary campaign source be the campaign the lead had either first responded to, or most recently responded to?   
Swami DeshanelSwami Deshanel
I recently started getting this error below.   Maybe you can help me?

Error: System.DmlException: Update failed. First exception on row 0 with id 00Qc0000005FcihEAC; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, checkPrimaryCampaignSource: execution of AfterUpdate caused by: System.QueryException: Non-selective query against large object type (more than 100000 rows). Consider an indexed filter or contact salesforce.com about custom indexing. Even if a field is indexed a filter might still not be selective when: 1. The filter value includes null (for instance binding with a list that contains null) 2. Data skew exists whereby the number of matching rows is very large (for instance, filtering for a particular foreign key value that occurs many times) Trigger.checkPrimaryCampaignSource: line 11, column 1: [] (System Code)
CheyneCheyne
This seems to imply that your CampaignMember query is returning more than 100,000 rows. This is strange since you are filtering on opportunity ID. Are your leads/opportunities members of a large number of campaigns or is it possible that there are duplicate campaign members? I would try running the query in the developer console to see what it returns.
PrKPrK
Hi Cheyne,

I have similar requirement where in when a lead is converted, I want to set primary campaign source to be the first campaign that the lead responded to. Let's say there are three Campaigns Camp1,Camp2 and Camp3. And the lead responded to Camp2, the end result is that I am setting opportunity's campaign Id field to be this value(Camp2).Campaign Influence rule criteria has been setup as Responded= True.

So when I go to the opportunity detail page, it shows Camp2 as Primary Campaign Source, But in the campaign influence
related list on opportunity, I can see two Camp2 records.Even if i am trying to manually update primary campaign source on Opp without any trigger, its creating duplicate records.
Is there any limitation on campaign influence?