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
ChickenOrBeefChickenOrBeef 

Populate 'Primary Campaign Source' with most recent Campaign Influence

Hey everyone,

Here is the issue we need to resolve:

1) A lead is converted to an opportunity without being in a campaign yet
2) The lead is now the Primary Contact on the opportunity
3) After a while that Primary Contact gets put in a campaign

The issue?

4) The 'Primary Campaign Source' field on the opportunity needs to be populated with the last campaign the Primary Contact was added to

Can I do this with a regular Apex trigger? Or do I need to use batch Apex?

Thanks!
-Greg
Best Answer chosen by ChickenOrBeef
Sonam_SFDCSonam_SFDC
You can try the following:
1)create a trigger on Campaign Member object such that you can get the Contact associated with this Campaign
2)Once you have the campaign - get the opportuities linked to his Contact using SOQL
3)Once you have this lst - you can update the Primary Campaign Source field with the name of the campaign this contact is linked with.

All Answers

Sonam_SFDCSonam_SFDC
You can try the following:
1)create a trigger on Campaign Member object such that you can get the Contact associated with this Campaign
2)Once you have the campaign - get the opportuities linked to his Contact using SOQL
3)Once you have this lst - you can update the Primary Campaign Source field with the name of the campaign this contact is linked with.
This was selected as the best answer
ShashForceShashForce

Hi,

How is the primaty contact put in a campaign? Is it through apex? If it is done through a DML, I though we can create a trigger on "Contact Role", but we unfortunately cannot create triggers on "opportunitycontactrole".

You may have to use batch apex and schedule it to run periodically.

My idea: You can get the contact ID for the primary contact from the opportunitycontactrole object using a SOQL query, then query that Contact ID on the "CampaignMember" object, and get the ID of the campaign which has the latest Created Date, may be through ASC LIMIT to 1. This Campaign ID can then be updated in the opportunity's Primaty Campaign Source field.

I haven't tried it myself though.

If this answers your question, please mark this as the Best Answer for this post, so that others can benefit from this post.

Thanks,
Shashank

Kramer Hope 1Kramer Hope 1
Hey Greg,

Did you get this to work? Would you mind sharing the SOQL you used? I am having this  same issue.

Best,
Kramer
ChickenOrBeefChickenOrBeef
Hey Kramer,

I ended up using batch apex for this. Here's the entire batch class:
 
global class BatchClassContactCampaign implements Database.batchable<sObject>{

global database.QueryLocator start(Database.BatchableContext ctx){ 
       
       return database.getQueryLocator([SELECT
                                            Id,CampaignId,Batch_Time_Stamp__c,
                                        	(SELECT Id, ContactId, OpportunityId FROM OpportunityContactRoles WHERE IsPrimary = TRUE)
                                        FROM
                                            Opportunity
                                        WHERE
                                       		CampaignId = NULL
			    						AND
                                       		IsClosed = FALSE]);
       
   }     
    
   global void execute(Database.BatchableContext ctx, List<Opportunity> oppList){
       
       Set<String> contactSet = new Set<String>();
       Map<String,String> oppMap = new Map<String,String>();
       Map<String,String> campMap = new Map<String,String>();
       Map<ID,Opportunity> oppsToUpdate = new Map<ID,Opportunity>();
       
       FOR(Opportunity opp : [SELECT
                             	Id,CampaignId,Batch_Time_Stamp__c,
                             	(SELECT Id, ContactId, OpportunityId FROM OpportunityContactRoles WHERE IsPrimary = TRUE)
                              FROM
                              	Opportunity
                              WHERE
                              	Id In :oppList]){
                                  
                                  FOR(OpportunityContactRole ocr : opp.OpportunityContactRoles){
                                      contactSet.add(ocr.ContactId);
                                      oppMap.put(ocr.OpportunityId,ocr.ContactId);
                                  }
                              }
       
       List<CampaignMember> cm = [SELECT
                                 	Id, ContactId, CampaignId
                                  FROM
                                 	CampaignMember
                                  WHERE
                                 	ContactId In :contactSet
                                  ORDER BY CreatedDate ASC];
       
       
       FOR(CampaignMember cm1 : cm){
           	campMap.put(cm1.ContactId,cm1.CampaignId);
       	}
       
       FOR(Opportunity opp1 : oppList){
           
           		String oldCampaignId = opp1.CampaignId;
               	opp1.CampaignId = campMap.get(oppMap.get(opp1.Id));
           
           IF(oldCampaignId == NULL && opp1.CampaignId != NULL){
           		oppsToUpdate.put(opp1.Id,opp1);
           }
    	}
       
       TRY{
       		UPDATE oppsToUpdate.values();
       }     
           CATCH(Exception ex){
               System.debug('<<<ERROR>>> BatchClassContactCampaign Error: ' + ex.getMessage());
           }
       
   }
    
   global void finish(Database.BatchableContext ctx){    
       
   }
    
}

I'm not sure if that's the absolute most efficient way to handle that, but there it is. Let me know if you have any questions.

-Greg