Updating Existing Leads Instead of Creating New Ones

Question
I am new to Apex and trying to solve the following problem using Salesforce Enterprise Edition.
We have a web-to-lead form that collects information about resource downloads. This form captures basic visitor details and includes a custom field to store a description of the downloaded resource. Visitors can download multiple resources, and each download gets logged in a database table. A cron job sends these download details to Salesforce, creating a new lead for each record. However, thinking about updating existing leads instead of creating new ones can be more efficient.
The issue arises when a visitor downloads another resource after their lead has already been created. Instead of updating the existing lead, Salesforce creates a new lead with the new download details. We need to prevent this behavior and instead append the new download details to the existing lead’s description field. To achieve this, I wrote the following trigger:
trigger UpdateLeadDescription on Lead (before insert) {
// Map to store existing leads by email
Map<String, Lead> existingLeads = new Map<String, Lead>();
// Query existing leads by email
List<Lead> existingLeadList = [SELECT Id, Description FROM Lead WHERE Email IN (SELECT Email FROM :Trigger.new)];
// Populate the map
for (Lead existingLead : existingLeadList) {
existingLeads.put(existingLead.Email, existingLead);
}
// Iterate through new leads
for (Lead newLead : Trigger.new) {
if (existingLeads.containsKey(newLead.Email)) {
// Lead exists, append description
Lead existingLead = existingLeads.get(newLead.Email);
newLead.Description = existingLead.Description + '\n' + newLead.Description;
}
}
}
However, the Salesforce Developer Console throws an error at line 6:
List<Lead> existingLeadList = [SELECT Id, Description FROM Lead WHERE Email IN (SELECT Email FROM :Trigger.new)];
The error reads: “Unexpected token ‘<‘.”
Could you help me debug this error and suggest a better approach to solve this issue?
Answer
In Salesforce, the Web-to-Lead feature typically creates a new lead every time a user submits a form. However, there are scenarios where you might want to update an existing lead instead of creating a new one. For example, when a visitor downloads multiple resources, the system should update the existing lead’s details rather than creating a new lead for each download.
Kickstart your career with our Salesforce training in Bangalore, designed to equip you with job-ready skills and hands-on experience through real-time projects. Enroll now for a free demo session!
The following trigger demonstrates how to achieve this functionality. It updates the description of an existing lead if a new lead with the same email address is inserted.
trigger UpdateLeadDescription on Lead (before insert) {
// Set to store emails from Trigger.new
Set<String> newLeadEmails = new Set<String>();
// Extract emails from Trigger.new
for (Lead newLead : Trigger.new) {
if (newLead.Email != null) {
newLeadEmails.add(newLead.Email);
}
}
// Query existing leads by email
Map<String, Lead> existingLeads = new Map<String, Lead>();
if (!newLeadEmails.isEmpty()) {
for (Lead existingLead : [SELECT Id, Email, Description FROM Lead WHERE Email IN :newLeadEmails]) {
existingLeads.put(existingLead.Email, existingLead);
}
}
// Iterate through new leads and update descriptions
for (Lead newLead : Trigger.new) {
if (newLead.Email != null && existingLeads.containsKey(newLead.Email)) {
// Lead exists, append description
Lead existingLead = existingLeads.get(newLead.Email);
newLead.Description = (existingLead.Description != null ? existingLead.Description + '\n' : '') + newLead.Description;
}
}
}
Explanation:
This code first collects all the email addresses from the incoming leads (Trigger.new
). It then queries the existing leads with matching email addresses and stores them in a map. During the before insert
phase, it checks if any new lead’s email matches an existing lead’s email. If a match is found, the trigger appends the new lead’s description to the existing lead’s description.
Alternate Approach:
If you want to handle duplicates in a more advanced way, such as deleting the newly created lead after updating the existing one, you can use the following trigger. This version includes a check to delete the new lead if it is redundant.
trigger UpdateLeadDescription on Lead (after insert) {
// Set to store emails from new leads
Set<String> setOfNewLeadEmails = new Set<String>();
// Extract emails from Trigger.new
for (Lead newLead : Trigger.new) {
setOfNewLeadEmails.add(newLead.Email);
}
if (!setOfNewLeadEmails.isEmpty()) {
// Map to store existing leads by email
Map<String, List<Lead>> mapOfExistingLeads = new Map<String, List<Lead>>();
// Query existing leads by email
for (Lead existingLead : [SELECT Id, Email, Description FROM Lead WHERE Email IN :setOfNewLeadEmails AND Id NOT IN :Trigger.new]) {
if (!mapOfExistingLeads.containsKey(existingLead.Email)) {
mapOfExistingLeads.put(existingLead.Email, new List<Lead>());
}
mapOfExistingLeads.get(existingLead.Email).add(existingLead);
}
// List to store leads to update and delete
List<Lead> listOfLeadsToUpdate = new List<Lead>();
List<Lead> listOfLeadsToDelete = new List<Lead>();
// Update and delete logic
for (Lead newLead : Trigger.new) {
if (newLead.Email != null && mapOfExistingLeads.containsKey(newLead.Email)) {
for (Lead existingLead : mapOfExistingLeads.get(newLead.Email)) {
existingLead.Description = (existingLead.Description != null ? existingLead.Description + ' \n ' : '') + newLead.Description;
listOfLeadsToUpdate.add(existingLead);
}
listOfLeadsToDelete.add(new Lead(Id = newLead.Id));
}
}
// Perform updates and deletions
if (!listOfLeadsToUpdate.isEmpty()) {
update listOfLeadsToUpdate;
}
if (!listOfLeadsToDelete.isEmpty()) {
delete listOfLeadsToDelete;
}
}
}
Explanation:
This after insert
trigger handles duplicates by updating the description of existing leads and deleting the redundant new leads. It ensures data consistency and prevents unnecessary clutter in the system.
Both approaches can be used depending on your specific requirements. If you’re unsure about the best method for your use case, consider the volume of data, business requirements, and system performance. Let me know if you need further clarification!
Salesforce Training with Real-Time Project Experience in Bangalore
Our Salesforce training program is tailored to provide personalized mentorship, certification exam preparation, and expert interview coaching, ensuring you stand out in the competitive job market. With access to comprehensive study materials, hands-on project experience, and continuous guidance, you’ll develop the confidence and skills needed to excel. By the end of the program, you’ll be ready to achieve certifications and gain the practical expertise employers highly value. Start your Salesforce journey with us and unlock exciting career opportunities!
Additionally, our Salesforce training in Bangalore delivers an immersive learning experience that equips you with essential skills to excel in the CRM industry. Covering vital areas like Salesforce Admin, Developer, and AI, the program balances theoretical knowledge with practical, real-world training. Through industry-relevant projects and assignments, you’ll gain the expertise to tackle complex business challenges using Salesforce solutions. Expert instructors provide valuable guidance to sharpen your technical skills and deepen your industry insights.
Take the first step toward an exciting Salesforce career and explore incredible job opportunities! Sign up for a FREE Demo today!