You need to sign in to do that
Don't have an account?
Duplicates from Web2lead
I have a PHP page that sends the Web2Lead information to Salesforce (the data goes to contacts, not leads). In Salesforce I have a trigger that prevents duplicates from being inserted, based on the key of email address, lead source, and creation date. In the sandbox and in Production this works fine and when I go to the landing page and try to create a duplicate, it won't let me (this is good). However, every now and then duplicate contacts are still being created (at the exact same time).
Below is the trigger I'm using. What can I do to effectively prevent duplicates from being inserted?
trigger AvoidWebleadDuplicatesTrigger on Contact (before insert) { set <string> setEmail = new set<string>(); set <string> setLeadSource = new set<string>(); list <contact> currentcontacts = new list<contact>(); for(contact acc:trigger.new) { setEmail.add(acc.Email); setLeadSource.add(acc.LeadSource); } currentcontacts = [select Email,LeadSource,CreatedDate,id from contact where Email in:setEmail and LeadSource in:setLeadSource and CreatedDate = TODAY]; for(contact acc:trigger.new) { if( currentcontacts.size() > 0 ) acc.adderror('This contact already exists: ' + acc.Email + ' - ' + acc.LeadSource ); } }
If you're using the standard web to lead form, and the user submits more than one record at a time (e.g. double-clicking the submit button), those items may be queued together into the same trigger invocation. This means that a proper trigger should also check incoming records against each other as well to verify that there aren't in-flight dupes. You can do this by adding the values to a set. Here's one possible version:
All Answers
Hi Forza,
When you same it is creating the duplicate contact at the same time - I am sensing that the form is being submitted twice and this might be an issue at the form end..
Did you try to find if there might be an issue there?
Hi Sonam,
I agree that this is probably an issue on the website's end, but I'm trying to deal with the issue from the Salesforce end, which is why I wrote the trigger to prevent duplicates from being inserted. I'm stumped - the trigger seems to work, and I cannot create duplicates from the website, yet every now and then they do show up.
Is there anything I can do at the trigger end, to get a better handle on these dupes?
If you're using the standard web to lead form, and the user submits more than one record at a time (e.g. double-clicking the submit button), those items may be queued together into the same trigger invocation. This means that a proper trigger should also check incoming records against each other as well to verify that there aren't in-flight dupes. You can do this by adding the values to a set. Here's one possible version:
SFDCFox, thanks for the code. I will have to study it and figure out what it's doing under the hood.
One problem I have now is that my test class no longer works/passes. Would you take a look at it and SFDCFoxify it?
Thank you...
Your test method is actually attempting to insert duplicates, and the trigger is now correctly blocking those duplicates (it wasn't before).
The only change you need here is to verify the trigger is operating as intended:
I thought the point of the test class was to recreate the scenario that I'm trying to test for. That is the reason I'm creating 2 regular contacts and 2 duplicate contacts. Is that not the correct approach?
On the test class side, for the 4 system.asserts I got false, false, true, true. That means the first 2 inserts failed, and the second 2 (the dupes) succeeded to fail (as expected). What could have caused the non-dupes to fail?
There are some workflows running in the background, but I thought the before trigger would execute before any workflows, so that shouldn't be an impact. *Shouldn't*...
The test method you proffered initially was correct in its intent, but the logic bug in the method (not verifying the success and failure of each record), hid the actual bug in the trigger logic. When the logic bug of the trigger was fixed, it exposed the bug in the test method, which also needed to be fixed.
Triggers do execute before workflow rules, but workflow rules can also cause an echo effect that causes triggers that executed once to execute a second time. This gives the trigger an opportunity to respond to changes to the record that occurred as a result of a field update. However, that should not have an effect here, because the records are still isolated, and so should not have failed.
You can check the results of each Database.SaveResult in a loop, using System.Debug to dump out their success/failure flags and any error messages, then check the log file after running the test (located in the Developer Console). Once you determine the error, you can take steps to correct it.
There are several types of errors that could prevent saving, including validation rules, other triggers on the same object failing, required fields missing (universally required permission), invalid record types selected for the test user, or any of a dozen other reasons (or more).
Without the log files, it will be difficult to know why the tests failed or what steps you can take to fix the test. That is your next logical step.
SFDCFox, I'm not able to paste the log file here, even a shortened version, so I'm just adding the errors I spotted:
ne 1:87 no viable alternative at character '"'
07:19:05.669 (669544000)|FATAL_ERROR|System.QueryException: line 1:87 no viable alternative at character '"'
Trigger.AvoidWebleadDuplicatesTrigger: line 40, column 1
07:19:05.669 (669561000)|FATAL_ERROR|System.QueryException: line 1:87 no viable alternative at character '"'
Trigger.AvoidWebleadDuplicatesTrigger: line 40, column 1
Line 40 of the trigger deals with building a SQL query:
for(Contact record:Database.query('SELECT Id, Email, LeadSource FROM Contact WHERE CreatedDate = TODAY AND ('+String.join(queryFilters,' OR ')+')'))
{
contacts.get(String.escapeSingleQuotes(record.LeadSource)).get(String.escapeSingleQuotes(record.Email)).addError('This contact already exists. (step 3)');
}
Sorry, I wrote the prior code without testing. Here's a tested version:
Thank you very much - you really provided a great service! I've learned a lot and will probably learn some more when I study your latest code.