I have been able to get a trigger to work that either updates a checkbox on the Contact Object based on whether an Opportunity is Open or not (based on the Stage Name).

This checkbox updates Pardot. What the Marketing dept would like to know is there a way that I can pass the Opportunity Contact Role (any of them, not just primary) over to the Contact Object?

I could create a custom object, and then create a lookup value link to Opportunity to use a cross-object formula, but I don't see it there. Plus, since Contact is a child in the relationship, I can't get a value to show due to the 1:M relationship.

Can anyone think of another way to do this?


I had a similar request and solved it using a visualforce page that I embedded on in the opportunity page layout with a 0px width and a 0 hight (so it would run, but not distract from the page):

<apex:page standardController="Opportunity" extensions="OpportunityContactRoleExtension" action="{!syncOpportunityContactRoles}" />

... which referenced an extension that updates a custom multi-select picklist called OpportunityRoles__c on the Contact object which mimics the values in the Opportunity Contact Roles picklist...

public with sharing class OpportunityContactRoleExtension {

    public Opportunity opp;

    public OpportunityContactRoleExtension(ApexPages.StandardController controller) {
        opp = (Opportunity)controller.getRecord();

    public void syncOpportunityContactRoles() {

    public static void syncOpportunityContactRolesFuture(Id oppId) {

        Map<Id, Contact> mapContacts = new Map<Id, Contact>([SELECT Id, OpportunityRoles__c FROM Contact WHERE OpportunityId = :oppId]);

        Map<Id, List<OpportunityContactRole>> mapContactsToRole = new Map<Id, List<OpportunityContactRole>>();
        for (OpportunityContactRole role : [SELECT Id, Role, ContactId FROM OpportunityContactRole WHERE ContactId IN :mapContacts.keySet() ORDER BY Role]) {
            if (!mapContactsToRole.containsKey(role.ContactId))
                mapContactsToRole.put(role.ContactId, new List<OpportunityContactRole>());

        String oldRole;
        String newRole;
        List<String> oldRoleList;
        List<String> newRoleList;
        Set<String> oldRoleSet;
        Set<String> newRoleSet;
        Boolean runThis;
        List<Contact> contacts = new List<Contact>();
        for (Id conId : mapContactsToRole.keySet()) {
            runThis = false;
            oldRole = mapContacts.get(conId).OpportunityRoles__c;
            oldRole = (oldRole == null) ? '' : oldRole;
            newRole = '';
            for (Integer i = 0; i < mapContactsToRole.get(conId).size(); i++) {
                if (i > 0)
                    newRole += ';';
                newRole += mapContactsToRole.get(conId)[i].Role;
            if (oldRole == '' || newRole == '') {
                if (oldRole != '' || newRole != '')
                    runThis = true;
            } else {
                oldRoleList = oldRole.split(';');
                newRoleList = newRole.split(';');
                oldRoleSet = new Set<String>(oldRoleList);
                newRoleSet = new Set<String>(newRoleList);
                if (!oldRoleSet.isEmpty() || !newRoleSet.isEmpty())
                    runThis = true;
            if (runThis) {
                Contact con = new Contact();
                    con.Id = conId;
                    con.OpportunityRoles__c = newRole;

        update contacts;



Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.