[SalesForce] How to create an Opportunity in Apex with the standard Primary Campaign Source functionality

I've set up some automation so that when a CampaignMember receives a specific status (Evaluation Request), a Contact, Account, and a set of project records are created. An external system notifies SFDC once the evaluation has started, and an opportunity is automatically created.

So I already have a Contact and Account record. The Contact has a CampaignMember which has already responded, and is the only CampaignMember associated with the Contact (in my test cases, at least).

Here's the first attempt ('ep' and 'ei' are custom objects, but you get the idea):

Opportunity newOpp = new Opportunity(
    AccountId = ep.Account__c,
    Name = ep.Account__r.Name + '-Automated',
    CloseDate = System.today() + 90,
    OwnerId = ep.Account__r.OwnerId,
    StageName = oppStage,
    RecordTypeId = oppRecType);
insert newOpp;

OpportunityContactRole ocr = new OpportunityContactRole(
    OpportunityId = newOpp.Id,
    ContactId = ei.Contact__c,
    IsPrimary = TRUE);
insert ocr;

When I check the Opportunity that is created, the Contact and Campaign show up as expected in the Campaign Influence related list, but the Primary Campaign Source field is not filled in. If you explicitly set the Primary Campaign Source, a new Campaign Influence entry is created, which is not tied to a Contact record.

OK, fine.

I know this works already with another process which creates an Opportunity while running through a Database.LeadConvert() call.

So here's the kludge attempt two, which converts and merges a dummy lead:

Lead l = new Lead(
    LastName = 'Temp',
    Company = 'Temp',
    RecordTypeId = leadRecType);
insert l;

Database.LeadConvert lc = new Database.LeadConvert();
lc.setLeadId(l.Id);
lc.setOwnerId(ep.Account__r.OwnerId);
lc.setConvertedStatus('Converted to Opportunity');
lc.setAccountId(ep.Account__c);
lc.setContactId(ei.Contact__c);
lc.setOpportunityName(ep.Account__r.Name + '-Automated');
lc.setOverwriteLeadSource(FALSE);

Opportunity newOpp = new Opportunity();
Database.LeadConvertResult lcr = Database.ConvertLead(lc, FALSE);
if(lcr.isSuccess()) {
    newOpp.Id = lcr.getOpportunityId();
    newOpp.CloseDate = System.today() + 90;
    newOpp.StageName = oppStage;
    newOpp.RecordTypeId = oppRecType;
}
update newOpp;

Same result.

I can't associate the dummy lead with the Campaign, because the automation is triggered off of the CampaignMember status.

For now, we've settled on asking the sales rep to select the primary OCR manually so that the fields are updated correctly, but this is a ridiculous step when I should be able to set these values directly.

Has anyone had any luck populating the Primary Campaign Source correctly within Apex? It's a black box as far as the SFDC implementation, and I'm considering rolling my own as a replacement. Our marketing team relies on this value heavily.

Best Answer

You can assign a campaign to the Opportunity's primary campaign source by:

CampaignMember campaign_member = ...;
Opportunity newOpp = new Opportunity(
    ...
    CampaignId: campaign_member.CampaignId,
    ...);

Check the sforce api for Opportunity here.

Related Topic