Contact form duplicate detection now reads the request, not just the address

The website contact form creates a Lead in the CRM, and until now it decided whether a submission was a duplicate by comparing the email address as a plain string. That was wrong in two opposite directions at the same time, and both were live. A returning prospect asking about something new was filed as […]

In this series · Part 6 of 27

1Dynamics 365 CRM: API integration + change-control repo2Dynamics 365 CRM: Last Contact Engagement tracking on Accounts3Turning a sales-intelligence export into a clean CRM data model4Dynamics 365 CRM: contacts inherit their company’s website, and emails timestamp by send time5Your SEO health now lives as a dashboard inside the CRM6Contact form duplicate detection now reads the request, not just the address7Marketing list members now show engagement and account fit8Campaign responses now create leads behind a confirmation step9Three CRM automations passed their tests without running the code that had just changed10A signature defect that three mailboxes agreed was not there11Why a corrected email signature kept sending the old one12A read-only CRM endpoint for scoring outside the desktop13Choosing what runs the AI layer in the CRM sales process14Asking whether a partner is involved, instead of inferring it15An email step in the sales process can now be excused, not only sent16The rehearsal that guards every process change had been failing silently17A one to one email from a lead left the engagement record blank18Two local dependencies, and only one was obvious19Filing a generated document to the record automatically20One meeting that served two process steps, recorded as two21A setting that stored correctly, read back correctly, and was never in force22Generating a product catalogue from one canonical file23Three date fields that existed on every row, and had never once been written24Unused, unreferenced, and still not safe to delete25A measure that could not record early26A sales automation that runs as itself, not as an administrator27A stage change that was refused, and reported as a success

On this page

Free Revenue Lifecycle Assessment

Connect with Marissa Wright to receive a free Revenue Lifecycle Assessment Report on your own business.

Book a consult →

The website contact form creates a Lead in the CRM, and until now it decided whether a submission was a duplicate by comparing the email address as a plain string. That was wrong in two opposite directions at the same time, and both were live. A returning prospect asking about something new was filed as a repeat and never became a Lead, so genuinely new interest went into the record as a note instead of the pipeline. Meanwhile one person writing in from x@, x+something@ and a capitalised spelling of the same address became three separate Leads, because nothing tidied the address before comparing it. The fix addresses both, and it is now live.

  • Addresses are normalised before they are compared. The address is trimmed and lowercased, and a plus tag is stripped, so a person who uses tagged addresses is recognised as one person. Google accounts additionally ignore dots, so dots are removed for those and only those. That restriction matters more than it looks: for most providers a.b@ and ab@ are two different mailboxes, so applying the rule everywhere would have fixed duplicate records by silently merging two real people, which is a worse failure than the one being fixed.
  • A repeat only counts as a repeat if nothing new is being asked. The form asks what the enquiry is about, and those answers are now part of the decision. Ask about something never asked before and it creates a Lead, even from a familiar address. Ask about the same things again and it stays a note on the existing Lead, exactly as before. Asking nothing in particular is treated as its own kind of request rather than as a match for everything.
  • The comparison is bounded to six months. Someone returning after half a year is a new opportunity, not a duplicate of an old one.
  • Verified by submitting the real form, not by reading the change. Eleven submissions were put through the live form covering both outcomes, each confirmed by which record it actually produced. One of them exists purely as a control: it proves the six month filter really is excluding old records rather than quietly matching nothing, which would have looked identical from the outside and made every other test pass for the wrong reason. All test records were then deleted and their absence confirmed by re-reading the database.