We have an Apex trigger that automatically converts a lead to a PersonAccount. We want to make sure that if there is already a PersonAccount with an email that matches that of the lead that we merge the lead with that existing PersonAccount.

We have the attached code running and in Sandbox it works. However, in live production environment it yields inconsistent results when used with web-to-lead, often creating duplicate PersonAccounts. I.e. even though there is an existing PersonAccount with an email address that matches that of the lead, the lead is not merged with it.

Any ideas why this might be happening? There are no other apps running in production.

trigger ConvertLeadToPersonAccountCheckDupesTrigger on Lead (after insert, after update) {
List<Lead> newLeads = [select Id, isConverted, Email from Lead where Id IN :trigger.new];
Set<Id> leads = new Set<Id>();
Set<String> leademails = new Set<String>();

for(Lead l : newLeads){

List<LeadStatus> convertedLeadStatuses = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];
Map<Id, String> leadstatuses = new Map<Id, String>();

for(LeadStatus ls : convertedLeadStatuses){
        leadstatuses.put(ls.Id, ls.MasterLabel);

List<Account> AccountList = [select Id,PersonEmail from Account where PersonEmail in: leademails];
Map<String, ID> accounts = new Map<String, ID>();

for(Account a : AccountList){
        accounts.put(a.PersonEmail, a.Id);

Id DupeAccountId=null;

for (Lead lead : newleads) {
  if (lead.isConverted == false) //to prevent recursion
    Database.LeadConvert lc = new Database.LeadConvert();

    DupeAccountId = null;
    DupeAccountId = accounts.get(lead.Email);

    if (DupeAccountId != null) {


    Database.LeadConvertResult lcr = Database.convertLead(lc);

2 Answers 2


The problem is in this statement

for(Account a : AccountList){
        accounts.put(a.PersonEmail, a.Id);

If you have 2 accounts with the same personEmail, it will only ever save the latest account id. i would switch it to be the other way around accounts.put(a.id, a.personEmail), and then change the logic in the newleads for loop to do the right merge.

  • We're using personEmail as a (semi)unique field. There shouldn't be duplicates - though we're not using validation rules or anything else to enforce this. The issue is that even when there is an account with the personEmail set, it's sometimes not being matched when the trigger fires using web-to-lead.
    – Matt
    Sep 18, 2013 at 9:54

Judging from your code I am uncertain why your person accounts are being duplicated. Since I am currently scripting a much more simple version for a client I thought I would leave this here in case you are still experiencing the original issue. This works in sandbox for me, so if doesn't work on your production there may be something in the way your form is submitting.

trigger testAutoConvert on Lead (after insert) {
    Set<String> leademails = new Set<String>();
    List<Lead> newLeads = new List<Lead>();

    // Get all the new leads
    for(Lead l : system.trigger.new){

    /* Make some maps of account and email addresses */
    List<Account> AccountList = [select Id, PersonEmail, OwnerId from Account where PersonEmail IN: leademails];
    Map<ID, String> peAccounts = new Map<ID, String>();
    Map<ID, ID> peAccountsOwner = new Map<ID, ID>();

    // Generic map for preventing loss of ids
    for(Account a : AccountList){
        peAccounts.put(a.id, a.PersonEmail);
        peAccountsOwner.put(a.id, a.OwnerId);

    // We will need this to get the id from the email address
    Map<String, ID> peAccountsFlipped = new Map<String, ID>();
    for(ID i : peAccounts.keyset()){
        peAccountsFlipped.put(peAccounts.get(i), i);

    /* System Conversion Requirements */
    leadStatus convertStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];
    List<Database.LeadConvert> leadConverts = new List<Database.LeadConvert>();
    Database.LeadConvert lc = new Database.LeadConvert();

    /* Configuring Payload */    
    for (Lead nl : newleads) {
        lc = new Database.LeadConvert();

        // Check to see if account already exists
        } else {
            // In the event an account doesn't exist

    // Fire Payload
    Database.LeadConvertResult[] lcr = Database.convertLead(leadConverts);
    System.debug(LoggingLevel.INFO, lcr);

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .