Set Defaults for Opportunity Contact Roles (when converting)

It’s always bugged me that the Primary flag and a Role are not set on Opportunity Contact Roles when converting a Lead.  After every convert, I manually set these.  Typically, I set the Role to “Decision Maker”and the Primary Flag to True.  I got sick of doing this manually, so I wrote a trigger for it and I am sharing it with you all.


trigger Opportunities on Opportunity (after insert) {

	Opportunities o = new Opportunities();


public class Opportunities {

    // Default Constructor
    public Opportunities()
    // Sets default values on the Contact Role record created during Conversion. Called on AFTER INSERT
    public void SetContactRoleDefaults(Opportunity[] opptys) 
        * Variables
		set<ID> set_opptyIDs = new set<ID>();
        * Initial Loop
        // Get a set of the Opportunity IDs being affected.
		for(Opportunity o:opptys) { 
        * Process Records
        // Update the Contact Role record to be Primary and the Decision Maker
        list<OpportunityContactRole> list_opptyContactRolesToUpdate = new list<OpportunityContactRole>();
		for(OpportunityContactRole ocr:[select Id,IsPrimary,Role from OpportunityContactRole where OpportunityId in :set_opptyIDs]) { 
			ocr.IsPrimary = true;
			ocr.Role = 'Decision Maker';
		if (list_opptyContactRolesToUpdate.size() > 0) {
			update list_opptyContactRolesToUpdate;

Test Class

private class Opportunities_Test {

    static testMethod void SetContactRoleDefaults_Test() {
        // Create a Lead
        Lead l = new Lead();
        l.lastname = 'Lastname';
        l.firstname = 'FirstName'; = 'Company';
        insert l;
        // Convert the Lead
        Database.LeadConvert lc = new database.LeadConvert();
		LeadStatus convertStatus = [Select Id, MasterLabel from LeadStatus where IsConverted=true limit 1];
		Database.LeadConvertResult lcr = Database.convertLead(lc);
		// Query Contact Role Records and Asserts all was set correctly.
		for (OpportunityContactRole ocr:[select Id,IsPrimary,Role from OpportunityContactRole where OpportunityId = :lcr.getOpportunityId()]) {
			system.AssertEquals('Decision Maker', ocr.Role);
			system.AssertEquals(true, ocr.IsPrimary);


  1. John Wall Said,

    February 16, 2009 @ 7:36 am

    Scott, this does take some work out of the process, but we have another problem before this – is there any way to force a contact to be associated when the opportunity is created?


  2. Scott Hemmeter Said,

    February 16, 2009 @ 11:28 am

    @John Wall,

    There is nothing built in. What I’d do is add a custom field on your Opportunity called Primary Contact. Require it on your page layout. Add a trigger that adds that Contact as the Primary Contact role on your Opportunity. Since it’s required on the Page Layout for new Opportunities, they must fill it in. This would make it work much like the Primary Campaign does on Opportunities in standard Salesforce.

  3. John Wall Said,

    February 17, 2009 @ 6:45 am

    Thanks Scott, that’s great.

  4. Kevin Richardson Said,

    March 28, 2009 @ 9:38 am


    I have a similar issue (I think). I’d like to create a trigger that takes the user from two separate opportunity fields and sets them into the contact roles with roles based on which oppty field they came from.

    Possible? Thoughts?

  5. Scott Hemmeter Said,

    March 29, 2009 @ 3:20 pm

    @Kevin, It is certainly possible to do with a trigger.

  6. Josh Said,

    May 29, 2009 @ 1:04 pm

    Hey Scott,

    I’m an admin without much coding experience, and I’m trying to get this working for my org. It runs fine in the dev environment, but when I try to deploy it to my production enviro using Eclipse, it says I need a test method for the trigger. Any chance you could share that, too?



  7. Scott Hemmeter Said,

    June 2, 2009 @ 12:16 pm

    @Josh, the test code is in the post. 🙂

  8. Eric Gronholz Said,

    September 9, 2009 @ 12:43 pm

    Excellent approach. Thanks for sharing. I modified its use a little by placing similar code in an “after update” trigger for the lead and checking to see if the update was caused by the conversion process. This code only runs if the conversion process was initiated via the UI:

    trigger trgLeadConvert on Lead (after update) {

    if ( == 1) {
    if (Trigger.old[0].isConverted == false &&[0].isConverted == true &&[0].ConvertedOpportunityId != null) {
    //make sure the contact role associated to the opportunity is marked as the primary contact
    list list_opptyContactRolesToUpdate = new list();
    for(OpportunityContactRole ocr:[select Id,IsPrimary,Role from OpportunityContactRole where OpportunityId =[0].ConvertedOpportunityId]) {
    ocr.IsPrimary = true;
    ocr.Role = ‘Decision Maker’;

    if (list_opptyContactRolesToUpdate.size() > 0) {
    update list_opptyContactRolesToUpdate;

  9. Scott Hemmeter Said,

    September 9, 2009 @ 1:36 pm


    Good call. I actually did the same thing in my org at one point when I was refactoring my code to be more efficient. I agree it’s better to place code that is to run upon Lead Conversion in a Lead after upgrade trigger.

  10. Ted Evangelakis Said,

    January 26, 2010 @ 3:42 pm


    How easy would it be to repurpose this to creating a new opportunity from an existing account instead of a lead. Most of our accounts only have one contact but if there were more, could it do the equivalent of a select top 1 in SQL and just take the first contact by default? This could of course be changed by the user.

  11. Scott Hemmeter Said,

    January 27, 2010 @ 10:36 am


    I am not sure how the code above gets you much further than other examples, but you should be able to get it done. To be honest, I am not really following what you need, but I am sure it can be done.

    FYI, if you create the Opportunity from the Contact record instead of the Account, the Opportunity will still get hooked up to the Account AND that Contact will be added as a Contact Role.

  12. Colin Said,

    August 17, 2010 @ 11:15 am

    Is there somewhere I can get a refresher on how to implement this in my org. I know I need to do it in the Sandbox first, then move it over. But it’s been a while…any help is much appreciated. Thanks!

  13. Scott Hemmeter Said,

    August 17, 2010 @ 11:19 am

    Colin, your best source for development is That’s where you’ll find the refresher on how to develop. All the code you need for this specific functionality is in this blog post. It’d take quite a bit of explanation to get you setup with salesforce in general.

  14. Colin Said,

    August 17, 2010 @ 12:14 pm


    I completely understand that you’re not here to teach someone how to use SF, and wouldn’t ask you to do that. But, if you could help me with one thing, it would be much appreciated. I have all the code installed in my Sandbox, but the test class is failing…giving me this error message:

    System.AssertException: Assertion Failed: Expected: Decision Maker, Actual: null

    I definitely have a picklist value of Decision Maker, so I’m not sure why I’m getting that error…any advice? Thank you in advance for your help!

  15. Scott Hemmeter Said,

    August 17, 2010 @ 1:03 pm

    @Colin, the test code is asserting that a contact role was created with the role set in line 31 of the class. Did you change the default Role that the new record would assign? If so, the test class should assert against that same role value.

  16. Colin Said,

    August 17, 2010 @ 1:24 pm

    I changed the contact roles to have a default value of “Decision Maker”, and now I’m getting a slightly different error (below):


    System.AssertException: Assertion Failed: Expected: true, Actual: false

    Class.Opportunities_Test.SetContactRoleDefaults_Test: line 26, column 13 External entry point

    Again, thank you for your help with this…I’ve spent a lot of time trying to solve this problem!

  17. Scott Hemmeter Said,

    August 17, 2010 @ 1:30 pm

    @Colin, Line 26 above is asserting that you are setting the Primary flag in line 30 of the class. Maybe you changed that too?

    I would suggest you make the class work the way you want it to. For the Tests, their purpose is to make sure it’s working as you expect, so you should adjust the assert statements to test that the data is being setup as you define it in the class.

    The asserts are actually optional when it comes to deploying the code to Production. They are not there for code coverage. They are there to assert the functionality is working as expected.

    you can email support [at] if you want to handle this in greater detail.

  18. wen Said,

    September 22, 2010 @ 5:31 pm

    @Eric- When entering the lead trigger I get

    Error: Compile Error: line 9:11 no viable alternative at character ‘‘’ at line 9 column 11

    Just to confirm 1. this is used in conjunction with both the Class and Opp trigger? and 2. I would add the second after update suggestion to Leads, right? ( trigger trgLeadConvert on Lead (after update) {)


  19. Scott Hemmeter Said,

    September 22, 2010 @ 5:43 pm

    @wen, if you literally copied and pasted from this site, try replacing any ‘ and ” characters you copied and re-type them. This site makes them look nicer, so you might have actually copied a different character from here than you thought.

  20. gow Said,

    January 24, 2011 @ 4:33 pm

    How do I simulate creating opportunity from Contact Detail page in my test code. Can anyone help with this?


  21. mike Said,

    March 1, 2011 @ 5:18 pm

    That is a gr8 trigger but when i tried implementing this in my sandbox i came across i doubt how can we set the role to decision maker when i create a new opportunity from the existing account , right now this only works if you convert a lead but i want to update the opp which iam creating from the existing accounts

  22. Scott Hemmeter Said,

    March 1, 2011 @ 5:32 pm

    @mike, this trigger is only for converting a lead. You’d have to do a trigger on the insert of a new oppty to solve the other issue.

  23. mike Said,

    March 31, 2011 @ 1:21 pm

    Hi Scott,
    i exactly copied ur code and test class in my instance but the test class covers only 2%, i been trying this since yesterday but couldn’t get enough coverage.Any help for covering my class is appreciated

  24. mike Said,

    March 31, 2011 @ 1:29 pm

    Sorry i forgot to mention that i created new role “primary role” so instead of decision maker i included this , your code covers 100% for decision maker but if i include this primary role it just covers 2% do i have to change anything in code?

  25. Scott Hemmeter Said,

    March 31, 2011 @ 1:30 pm

    @mike, the only thing I can think of is that you have fields required on your objects and the test code isn’t populating enough fields. perhaps it’s hitting a validation rule. The lead I have being created is only populating the minimum. Also, if you allow for validation rules and triggers on convert, it’s possible that the trigger is not firing when the test code converts the lead.

    I’d suggest running the test code of that one class and look in its log for the word “EXCEPTION”. It will show any errors you may have in there.

  26. Scott Hemmeter Said,

    March 31, 2011 @ 1:53 pm

    @mike, I think you’d just need to change the class and test class to not use Decision Maker and to use your new role value.

  27. Corinne Said,

    November 3, 2011 @ 4:02 pm

    Hi Scott,

    Thanks for an awesome trigger and being so helpful in the comments! Quick question, since I’m a novice Salesforce user: how would I modify this trigger so it only applies to leads that had a certain value when converted? For example, if I only wanted the Role set if the original lead had “Do Not Call” checked off? Thanks in advance! 🙂

  28. Tom Said,

    May 2, 2012 @ 1:57 pm

    @Eric Gronholz, I like this approach. However, I get an “unexpected token” error on the List line (line 5 in my case). Any idea why that is happening?

  29. Tom Said,

    May 2, 2012 @ 2:53 pm

    I figured out my issue. Duh. Missing the list name:

  30. UPDATE: Set Defaults for Opportunity Contact Roles (when converting) | Perspectives on Said,

    June 4, 2012 @ 9:34 am

    […] Tips By Scott Hemmeter Share I’ve had a few people reach out regarding an old post about defaulting Opportunity Contact Roles on a Lead convert. Turns out the trigger on Opportunities is not the best option. This was resolved […]

  31. UPDATE: Set Defaults for Opportunity Contact Roles (when converting) | WikiCloud Said,

    November 29, 2012 @ 8:03 pm

    […] had a few people reach out regarding an old post about defaulting Opportunity Contact Roles on a Lead convert. Turns out the trigger on Opportunities is not the best option. This was resolved […]

RSS feed for comments on this post