Salesforce coding lessons for the 99%
Finally, Apex tutorials for point-and-click admins! Written by a self-taught Google engineer.
  • Beginner Tutorials
    • Apex
    • Certifications
    • Career Info
    • Technical Architect
    • Visualforce
    • Videos
  • Apex Academy
  • Success Stories
  • About Me
  • Misc
    • Mailbag
    • Challenges
    • Links
    • Login to my Org
Follow @dvdkliuor SUBSCRIBE!

What is a Salesforce trigger?

May 9, 2013

Preface: this post is part of the Write Your First Trigger From Start to Finish series.

Have you ever run into any of these workflow limitations?

  • Your workflow can’t create or update a separate object!
  • You’re not allowed to reference certain fields, like Owner.Name (why Salesforce, why!)
  • You need your workflow to do more than just simple field updates and emails.

Nothing is more frustrating than being limited by a platform!  That’s why I started coding, and that’s why I want to help you learn too.

Imagine triggers to be like workflows without limitations.  Like workflows, you define entry criteria and actions.  Unlike workflows, you can make each of these do or reference anything you want.

With triggers, the only limit is your imagination!  …and your coding skills.  Don’t worry, you’ll be surprised how easy it is to do some amazing things with just a few lines of code.  Plus, this site is designed to kick start your learning.

Next post: Where to write code in Salesforce

46 Comments
Vijay Zutshi
November 10, 2019 @ 4:53 pm

Hi David,

Thanks for the the material that you have created. My question is as follows:
I did week 1 which is introduction and it went very well as I did exercises in that and also got points and badges for completing. Now when I go to week 2 and do the exercises as advised by you I do not get ant points. So how do I get that. I also want to create a new playground org. How do I do that.
Thanks
Vijay

Reply
    David Liu
    November 10, 2019 @ 5:03 pm

    Re read the content and watch the videos linked if you can!

    Reply
    David Liu
    November 10, 2019 @ 5:04 pm

    You want to create a free developer edition org

    Reply
Gina
May 9, 2018 @ 12:54 pm

Hi David,

Long time follower of your blogs/tutorials! Question about triggers vs classes, I’ve been advised by newer SF developers that it’s best to call classes from triggers (perhaps multiple classes from the same trigger) but have all the ‘magic’ happen inside the class. That it allows order of operations to be controlled. I am interested in your opinion as dip my toe into the development world.

Thank you!

Reply
    David Liu
    May 9, 2018 @ 10:01 pm

    Thanks true and it’s covered in Chapter 8.6 =)

    It’s not a necessity but it’s a good optimization. I wouldn’t focus on it right now while you’re learning – it’s kinda like learning to run before you walk!

    Reply
tharun
June 23, 2017 @ 12:18 am

I want to trigger custom field in opportunity after insert,after insert into custom field a callout to third party is done through that trigger and responsce from that callout is updated back into other custom field of same opportunity is it possible to keep trigger on custom field and make callout.

it want update before saving record

Reply
tharun
June 23, 2017 @ 12:16 am

hi david,

I want to trigger custom field in opportunity after insert,after insert into custom field a callout to third party is done through that trigger and responsce from that callout is updated back into other custom field of same opportunity is it possible to keep trigger on custom field and make callout.

it should happen before saving record.

Reply
Abdul
April 2, 2017 @ 10:15 am

Hey David I have been trying to figure this question out but understood it but can you please explain this?

Make sure the method can be called from the Anonymous Code window in the Developer Console, without having to instantiate the AccountUtility class.

Reply
    David Liu
    April 3, 2017 @ 9:07 pm

    Read about static methods!

    Reply
      Ravi Kumar
      September 28, 2017 @ 7:55 pm

      hello Dear David
      • Use a QueryLocator in the start method to collect all Lead records in the org.

      please provide answer for me

      Reply
Anonymous
November 2, 2016 @ 4:15 am

Hi David,

How to write trigger on a SObject which doesn’t support trigger eg. GoogleDoc.

Thanks

Reply
    David Liu
    November 3, 2016 @ 8:42 pm

    No can do! Need to write other types of classes!

    Reply
Sue Zhang
August 29, 2016 @ 12:18 pm

David,

Is it possible to change the owner of a custom object record which is created by a community user using trigger? I kept getting Insufficient Privileges error with message of ‘You do not have the level of access necessary to perform the operation you requested…’. Could you please give me some suggestions?

Thanks,
Sue

Reply
    David Liu
    August 29, 2016 @ 8:12 pm

    Definitely possible =) Probably an unrelated error that needs debugging!! Sorry can’t help without looking at the code!

    Reply
Alice
July 28, 2016 @ 8:55 am

Hi David, we are trying to integrate Zendesk and Salesforce in order to track our ticket timing and efficiency. I was wondering if you have any experience in this or could give any pointers? We are just starting out and not sure what to do at this stage! Thank you!

Reply
    David Liu
    July 28, 2016 @ 11:23 am

    Thanks for reaching out Alice!

    The paths of least resistance for you are:
    1. Use any existing Zendesk Salesforce apps – I’m sure there is one already (but it may not fit your exact need)
    2. Get an integration tool like Boomi (expensive) to manage the integration without code! You could have this integration done by tomorrow.

    I don’t recommend coding it in house or from a consultancy at this point since your team is just starting out and the only guarantee is CHANGE, which is very expensive in the long run =)

    Good luck!
    David

    Reply
sravanthi
May 30, 2016 @ 10:11 am

workflow can’t create or update a separate object .what does Seperate object mean?

Reply
    Pankaj kumar Pandey
    June 15, 2016 @ 8:25 am

    Separate object means object like Account and contact at same time.

    Reply
Anonymous
December 22, 2014 @ 4:22 pm

David – You rock!!! I’m a card carrying fan. Thanks for putting this site together. Very helpful!

Reply
deep
December 9, 2014 @ 9:17 pm

hi liu,

If two object doesnt have any relation ship,is it possible to write trigger between them?

Reply
    David Liu
    December 9, 2014 @ 9:30 pm

    You certainly can =) Possibilities are endless!

    Usually you just do a SOQL query for the data. IE match on a certain text field.

    Reply
Ben
December 2, 2014 @ 8:46 am

Finally a great website where you can get all the information you need to get started with coding – Thank you!!! : )

Reply
Evelyn
November 6, 2014 @ 7:05 am

I’m so glad I found this site! I’m a sales rep turned part time admin (basically because I know a tiny bit more than everyone else here) turned part time developer, and I’m in some serious need of help! I’m looking to just do a couple really basic things. 1. If an account/lead comes in as x # of employees, assign to user x. So all 1-20 assign to Patrick, 21-40 assign to Sasha and so on, and 2. Any case that contains “Patrick Ellwanger” assign to Patrick Ellwanger, and so on. I still haven’t searched through everything on this site yet, but any help would be greatly appreciated! Thanks so much for creating this website!

Reply
    David Liu
    November 6, 2014 @ 6:02 pm

    My pleasure Evelyn!

    You basically need to take this trigger and slightly repurpose it. The trigger in video 2 might help also!
    https://www.sfdc99.com/2014/07/02/apex-video-tutorial-write-your-first-trigger/

    You can post on the forums here too if you need more help!
    David

    Reply
      Evelyn
      November 10, 2014 @ 5:50 am

      Thanks! Have you ever had anyone do round robin for accounts (not leads)? That’s something I’m trying to accomplish instead of by employee count, and it seems like it can only be done on leads unless you create territories, which I don’t want to do as we’re a new company and things could change really quickly.

      Reply
        Cheryl Feldman (@CherFeldman)
        November 10, 2014 @ 8:48 am

        Hi Evelyn, we used to do this before the latest version of Territories. Because you can’t have queues on Accounts and that was a requirement, we essentially created a custom object that every account was associated to and based on that criteria a record was created associated to that account which had a few fields on it. One of the fields was owner of that object which would assign to a queue and then be accepted.

        We also had logic to add people to account team based on queue membership.

        One thing we did look at doing at one time was using logic to populate account teams based on location and other factors (company type, size, segmentation), we didn’t go that route, but maybe another option. Keep in mind you an insert into account teams using triggers, but you can’t calculate anything off of the account team (if something changes you can’t update something on the account).

        A lot of this could be solved if they allowed queues on accounts, there is an idea out there for this.

        Reply
Christine
August 10, 2014 @ 7:38 pm

Hi David,

I love your website! I’m learning a lot and will pass it on to other friends. I have a task I’m struggling with. I need to create a trigger each time a new contact is added to Salesforce that instructs a user to print a file label with the new contact’s information. In SalesForce, can I create a trigger that would automatically send the information to a printer in the office? Or would I simply have to email the user a report that would then be used with Microsoft Office to manually print the label?

Reply
    David Liu
    August 11, 2014 @ 8:33 pm

    You can talk to the printer if it has an API – but I’m guessing it doesn’t!

    The email report workaround is certainly possible =)
    https://www.sfdc99.com/2014/03/01/sending-emails-using-apex/

    Reply
Mthobisi
May 21, 2014 @ 1:31 am

Hi David

I would like to know is it possible to write a trigger that automatically creates an account record for every contact that is created/inserted and if I want to do the same for contact records that are already created how can I approach this? any sample code that you can share would be very help.

Reason why I want to do this:

Users only have access CRED to the Contact object
Sharing rules are used for users with different profiles (but sharing rules dont work unless the contact record is associated with an Account record).

Reply
    David Liu
    May 22, 2014 @ 5:27 pm

    Definitely possible! Apex ignores all permissions, so you’re fine there!

    Check out the first or second webinars for similar code!
    https://www.sfdc99.com/2014/05/22/congrats-and-thank-you/

    As for older records, you can simply use a mass insert tool like Data Loader or Workbench =)

    David

    Reply
      Mthobisi
      May 23, 2014 @ 12:19 am

      I did it, it works that was my first trigger ever…. I have also created a trigger that deletes the accounts that are associate with the contacts. However it’s not working. Code below with comments on the problem area

      trigger deleteAccountRecord on Contact (after delete) {

      RecordType donorRecType = [SELECT ID FROM RecordType WHERE sObjectType = ‘Contact’ AND DeveloperName = ‘Donor_Contact’];

      if(Trigger.isDelete){

      List contactIDList = new List();
      for(Contact contactToDelete: contactList) {
      if (contactToDelete.RecordTypeId != donorRecType.Id ) {

      contactIDList.add(contactToDelete.id);
      System.debug(‘Contact List —> ‘+ contactIDList.size()); // has values
      }
      }

      /** the DelAccountRecordList below does not return any records, if I run the query in the workbench with a Contact Id value it returns values, e.g. SELECT id FROM Account WHERE Id IN(SELECT accountId FROM Contact WHERE Id = ‘0031100000P7yas’)
      but the query below does not work, even if the contactIDList contains a Contact Id,**/

      List DelAccountRecordList = [select id from Account where Id IN(SELECT accountId FROM Contact WHERE Id IN: contactIDList)];

      if(DelAccountRecordList.size() >0){
      Database.DeleteResult[] deleteAccount = database.delete(DelAccountRecordList,false);
      System.Debug(‘deleteAccount —>’+ deleteAccount);

      }
      }

      }

      I have am out of ideas as to why my query does not work.

      Reply
        David Liu
        May 24, 2014 @ 12:44 am

        Try a “before delete” trigger =) Also, I don’t see where contactList is being created!

        Reply
          Mthobisi
          May 26, 2014 @ 1:43 am

          Sorry I had used ” ListcontactList = [SELECT Id FROM Contact];” to test if I will be to get any record on the DelAccountRecordList list, of which I do, but all the contacts get deleted with all their accounts if I delete one contact record, but the For loop originally uses the Trigger.old like below.

          for(Contact contactToDelete: Trigger.old) {
          if (contactToDelete.RecordTypeId != donorRecType.Id ) {

          contactIDList.add(contactToDelete.id);
          System.debug(‘Contact List —> ‘+ contactIDList.size()); // has values
          }
          }

          I have tried using the “Before Delete” and DelAccountRecordList does return records, however I get ”

          FATAL_ERROR System.DmlException: Delete failed. First exception on row 0 with id 0011100000R5ELkAAN; first error: SELF_REFERENCE_FROM_TRIGGER, Object (id = 0031100000QIa7i) is currently in trigger deleteAccountRecord, therefore it cannot recursively delete itself: []”

          Reply
            David Liu
            May 26, 2014 @ 10:20 am

            So let me see if we’re one the same page:

            When a contact is deleted, you want the contact’s account to be deleted as well. HOWEVER, you do not want other contacts on that account to be deleted, their Account record should just be empty.

            If that’s the case, make sure you clear out the other contact’s account fields (and update) before deleting the account!

            Hope this helps!
            David

            Reply
              Mthobisi
              May 26, 2014 @ 10:40 am

              Yes and Not exactly… I have a trigger that creates an Account record for every contact that will created, so the relationship will be more like 1:1 e.g. When I create a contact called David Liu an Account for that contact called David Liu will be created. This will be the case for every contact, this is done so that the sharing rules on the contact object will work.

              the users that will be be mostly working on the Contact object do not have access to the Account object hence the need of the trigger that deletes the Account that is associted with an Contact. I got some help from the dev forum.

              Below is the working code in case someone here ever need to do the same thing as me;

              trigger deleteAccountRecord on Contact (after delete) {

              RecordType donorRecType = [SELECT ID FROM RecordType WHERE sObjectType = ‘Contact’ AND DeveloperName = ‘Donor_Contact’];
              if(Trigger.isDelete){
              List accIds = new List();
              for(Contact contactToDelete: Trigger.old) {
              if (contactToDelete.RecordTypeId != donorRecType.Id ) {

              accIds.add(contactToDelete.AccountId);
              }
              }

              List DelAccountRecordList = [select id from Account where Id IN:accIds];

              if(DelAccountRecordList.size() >0){
              delete DelAccountRecordList ;

              }
              }
              }

              Reply
Catherine Johnson
May 15, 2014 @ 6:10 am

Hi David,
I am not sure how to ask you for help but here it goes. I am a new Salesforce admin for the state highway admin and I am very much interested in learning code. But I believe I need to master admin tasks first. Can you help me? I am at work now, please call me @ 410.545.8674. I have a lot to ask you but need to know where to start. thanks

Reply
    David Liu
    May 15, 2014 @ 2:24 pm

    Chapter 0 on the beginner tutorials is where you need to be!

    Reply
  • Pingback: What (approximately) 48 hours with Apex has taught me | SFDCinSeatown

  • Cheryl Feldman`
    March 12, 2014 @ 10:47 am

    OMG David. I was just sent to your site because I was having trouble teaching myself to code. I have been a salesforce admin for almost 10 years and have tried multiple times to learn apex but I just can’t grasp it. I’ve read a few posts by you and I understand more than I ever did from all the books I got from dreamforce. I can’t imagine how much time you must put into this site, thank you thank you thank you.

    Reply
      David Liu
      March 12, 2014 @ 8:09 pm

      Cheryl,

      So happy I can help, these comments are all the payment I need =*)

      Definitely ask if you get stuck!

      David

      Reply
    Anonymous
    March 11, 2014 @ 11:24 pm

    Your workflow can’t create or update a separate object!!???means?

    Reply
      David Liu
      March 11, 2014 @ 11:25 pm

      It means if you have a workflow on Accounts, the workflow cannot do any of these:
      – Create a new Contact
      – Update related Contacts

      Reply
    ram
    March 3, 2014 @ 4:44 am

    so if we are having a master- detail relation ship we are able to update the field right!!!

    Reply
      David Liu
      March 3, 2014 @ 10:31 pm

      Yes but only one way =) IE from the child to the parent. Not possible from parent to child, but possible with triggers!

      Reply
    lakshman
    August 3, 2013 @ 4:24 am

    Your workflow can’t create or update a separate object!.
    can u please explain it with some examples..

    Reply
      David Liu
      August 22, 2013 @ 11:58 pm

      For example, if you have a workflow on a Contact, you wouldn’t be able to add a field update to that workflow to update a field on the Contact’s Account.

      The only exception is if the relationship is a master-detail relationship – but these aren’t that common in most orgs!

      Reply

    Leave a Reply Cancel reply

    Your email address will not be published. Required fields are marked *


    *

    *

    Theme: Simple Style by Fimply