I have spent hours on it but haven't been able to figure out anything. The idea is simple:

  1. User clicks on standard Opportunity clone button.
  2. User selects either 'Clone without products' or 'Clone with Products'
  3. On the cloned record, the stage is set to Identified (first one) and certain custom fields are cleared out (doesn't matter if it's with or w/o products). I started off with a simple trigger like this:

    trigger OpportunityClone on Opportunity (before insert) {
    for (Opportunity o : Trigger.new) {
        if (o.isClone()) {
            o.StageName = 'Identification';
            o.IsCloned__c = true;
            o.Roll_Out_Plan__c = NULL;
            o.Rollout_Duration__c = NULL;
            o.Roll_Out_Start__c = NULL;
            o.External_Opportunity_ID__c = NULL;

But for some weird reason, it works perfectly for the 'Clone With Products' button action but doesn't do anything for 'Clone Without Products' action.

It seems like the isClone() isn't being detected at all when doing the latter.

Is there a way to fix the above or an alternative better way? Any help is much appreciated. I have pulled my hair enough on this.

  • Not sure why but isClone() returns false with clone without products just tested.
    – Mr.Frodo
    Jun 19, 2016 at 5:09

2 Answers 2


You can take this following approach.

  1. Create a custom field called Record Id in opportunity and update that field with Opportunity Id through the workflow field update (condition: when record is created).

  2. In the before insert trigger, verify if Record Id is null then that record is new record. and If Record Id is not null then that record is being created through cloning.

This way you can bypass the use of IsCloned() or getCloneSourceId() methods in trigger.

Please find below sample code.

trigger OpportunityClone on Opportunity (before insert) {
    for (Opportunity o : Trigger.new) 
        System.debug('Record Id=' + o.Record_Id__c);

        if(o.Record_Id__c == null)
            //handle records for new operation
        else if (o.Record_Id__c !='') 
           //handle records for clone
            o.StageName = 'Identification';                  
  • @SantanuBoral If you "return" you'll exit early. This may have an unintended effect on bulk data loads, because only the first record will be evaluated.
    – sfdcfox
    Jun 19, 2016 at 17:49
  • That unfortunately didn't work and I had to go with a URL hack. Not fond of URL hacks but there was no other option here. Jun 19, 2016 at 19:37
  • Actually do not need to put return statement, it's just a sample to show that logic. I will update part Jun 19, 2016 at 20:02
  • @Mayank, where it is failing? I have tested, it is working as expected Jun 19, 2016 at 20:08
  • @Mayank, please create a fresh opportunity record and do the testing, for old records there should be data migrations, thanks. Let me know Jun 19, 2016 at 20:18

It looks like this was a historical issue that has since been resolved in Spring `18 - Apex "isClone()" method always return false when doing opportunity clone "without copying opportunity product" mode.

Apex "isClone()" method always return false when doing opportunity clone "without copying opportunity product" mode.

Note: This issue applies to workflow as well.

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.