You need to sign in to do that
Don't have an account?
Roger Wicki
Web To Lead Trigger
Hi folks
I created a Lead trigger after insert, that should search for Contacts with the same Email address as the lead and update a field depending on a lead field.
More detailed:
We use a Web-To-Lead Form to create Leads for people who would like to unsubscribe for one of our two newsletters we send. Because creating Records over this form is by far the easiest way (no VF pages), we had a go for that. We adapted the web-to-lead form to a simple link which creates a lead and redirects to a chosen website. The link contains the Org Id, the Lead Record Type Id and a value to fill the picklist "OptOutType" in which we store for what newsletter the user wants to unsubscribe.
My test class executes fine without any (unwanted) errors. However, when using the web to lead link, there's only a lead created but no update on contact. That is when I thought that maybe the code somehow runs using access restrictions and tried to run the code as admin user, but then the lead wasn't even created anymore.
Because the Web To Lead process isn't run by any existing user, I can not use the Debug Log option from the SF setup as there is nobody to track. That leaves me clueless on how to catch the error message...
I use a trigger template with trigger handler classes fro all of my code. On that just a few notes:
- Trigger runs on every DML operation
- Trigger calls the TriggerManager class and adds an instance of a handler class and passes on the type of DML operation
- Trigger calls the methods "setValues(trigger.new, trigger.old.map)" and "handle(dmlOperation)".
- The handler class implements the triggerTempalte interface which makes it execute the two methods mentioned before
And here is my handler class:
public class LeadHandlerNewsletter implements TriggerTemplate.Handler
{
public void handle(TriggerTemplate.TriggerAction theAction)
{
list<Lead> relLeads = new list<Lead>();
I created a Lead trigger after insert, that should search for Contacts with the same Email address as the lead and update a field depending on a lead field.
More detailed:
We use a Web-To-Lead Form to create Leads for people who would like to unsubscribe for one of our two newsletters we send. Because creating Records over this form is by far the easiest way (no VF pages), we had a go for that. We adapted the web-to-lead form to a simple link which creates a lead and redirects to a chosen website. The link contains the Org Id, the Lead Record Type Id and a value to fill the picklist "OptOutType" in which we store for what newsletter the user wants to unsubscribe.
My test class executes fine without any (unwanted) errors. However, when using the web to lead link, there's only a lead created but no update on contact. That is when I thought that maybe the code somehow runs using access restrictions and tried to run the code as admin user, but then the lead wasn't even created anymore.
Because the Web To Lead process isn't run by any existing user, I can not use the Debug Log option from the SF setup as there is nobody to track. That leaves me clueless on how to catch the error message...
I use a trigger template with trigger handler classes fro all of my code. On that just a few notes:
- Trigger runs on every DML operation
- Trigger calls the TriggerManager class and adds an instance of a handler class and passes on the type of DML operation
- Trigger calls the methods "setValues(trigger.new, trigger.old.map)" and "handle(dmlOperation)".
- The handler class implements the triggerTempalte interface which makes it execute the two methods mentioned before
And here is my handler class:
public class LeadHandlerNewsletter implements TriggerTemplate.Handler
{
private list<Lead> newLeads;
private list<RecordType> recTypes;
private map<String, Id> recTypeMap = new map<String, Id>();
private User owner = new User();
public void setValues(list<SObject> newValues, map<Id, SObject> oldValues)
{
private list<RecordType> recTypes;
private map<String, Id> recTypeMap = new map<String, Id>();
private User owner = new User();
public void setValues(list<SObject> newValues, map<Id, SObject> oldValues)
{
newLeads = newValues;
recTypes = [ SELECT Id, Name FROM RecordType WHERE SObjectType = 'Lead' ];
for ( RecordType rec : recTypes )
{
recTypeMap.put(rec.Name, rec.Id);
}
owner = [ SELECT Id FROM User WHERE CustomApexErrorReceiver__c = true AND isActive = true LIMIT 1 ];
if ( owner == NULL || Test.isRunningTest() )
{
Profile admin = [ SELECT Id FROM Profile WHERE Name = 'System Administrator' LIMIT 1 ];
owner = [ SELECT Id FROM User WHERE ProfileId = :admin.Id AND isActive = true LIMIT 1 ];
}
}
public void handle(TriggerTemplate.TriggerAction theAction)
{
if ( theAction == TriggerTemplate.TriggerAction.afterInsert )
{
processRelevant(findRelevant(newLeads, recTypeMap));
}
}
private static list<Lead> findRelevant(list<Lead> allLeads, map<String, Id> recTypeMap)
{
private static list<Lead> findRelevant(list<Lead> allLeads, map<String, Id> recTypeMap)
{
list<Lead> relLeads = new list<Lead>();
try
{
for ( Lead currLead : allLeads )
{
if ( currLead.RecordTypeId == recTypeMap.get('Newsletter Opt Out') )
{
relLeads.add(currLead);
}
}
return relLeads;
}
catch (System.Nullpointerexception e)
{
System.debug('Record Type Mapping got messed up, returning current list to continue');
return relLeads;
}
}
private void processRelevant(list<Lead> relLeads)
{
private void processRelevant(list<Lead> relLeads)
{
// Both String Keys for maps are Email addresses
map<String, Lead> leadMap = new map<String, Lead>();
map<String, list<Contact>> emailContactMap = new map<String, list<Contact>>();
list<Contact> contacts;
list<String> keys = new list<String>();
for ( Lead currLead : relLeads )
{
list<Contact> contacts;
list<String> keys = new list<String>();
for ( Lead currLead : relLeads )
{
Lead aLead = new Lead();
aLead = currLead;
leadMap.put(currLead.Email, aLead);
}
contacts = [ SELECT Id, Email, Manufacturer_Update__c, Retailer_Update__c FROM Contact WHERE Email IN :leadMap.keySet() ];
for ( Contact c : contacts )
{
if ( emailContactMap.containsKey(c.Email) )
{
emailContactMap.get(c.Email).add(c);
}
else
{
emailContactMap.put(c.Email, new list<Contact>{c});
}
// Collect leads whose Email were not retrieved
keys.add(c.Email);
}
list<Contact> contactsToUpdate = new list<Contact>();
for ( String s : emailContactMap.keySet() )
{
if ( leadMap.get(s).OptOutType__c.equalsIgnoreCase('ManufacturerUpdate') )
{
for ( Contact c : emailContactMap.get(s) )
{
c.Manufacturer_Update__c = 'no - has unsubscribed';
contactsToUpdate.add(c);
}
}
else if ( leadMap.get(s).OptOutType__c.equalsIgnoreCase('RetailerUpdate') )
{
for ( Contact c : emailContactMap.get(s) )
{
c.Retailer_Update__c = 'no - has unsubscribed';
contactsToUpdate.add(c);
}
}
}
// Create Task for unprocessed Leads
list<Lead> unprocessed = new list<Lead>();
list<Task> errorTasks = new list<Task>();
for ( String s : keys )
{
leadMap.remove(s);
}
unprocessed = leadMap.values();
for ( Lead currLead : unprocessed )
{
errorTasks.add(new Task(WhoId = currLead.Id, Subject = 'Unsubscription failed!', OwnerId = owner.Id));
}
// This block seems not to be executed at all / correctly from the Web-To-Lead Form
try
{
update contactsToUpdate;
if ( errorTasks != NULL && errorTasks.size() != 0 )
{
insert errorTasks;
}
// Code Coverage for Exception
if ( Test.isRunningTest() )
{
System.debug('Throwing error intentionally');
insert new Account();
}
}
catch(System.DmlException e)
{
System.debug('The process just crashed with error message: ' + e.getMessage());
}
}
}
I finally got it working. The key was that Web-To-Lead first inserts a lead without information (so trigger.new on insert is useless) and then updates the very same lead with the information provided. Jeff May from the Community pointed that out here (https://success.salesforce.com/answers?id=90630000000hAp2AAE).
This means I don't need to have the debug log anymore, but thanks for the hint. I didn't try it yet but "Default Lead Creator" can't be the reason as that is me. The reason may however be "Default Lead Owner" which is someone else.
All Answers
I finally got it working. The key was that Web-To-Lead first inserts a lead without information (so trigger.new on insert is useless) and then updates the very same lead with the information provided. Jeff May from the Community pointed that out here (https://success.salesforce.com/answers?id=90630000000hAp2AAE).
This means I don't need to have the debug log anymore, but thanks for the hint. I didn't try it yet but "Default Lead Creator" can't be the reason as that is me. The reason may however be "Default Lead Owner" which is someone else.