Automatic creation of Salesforce.com leads from product registrations

Our company recently started using Salesforce.com as its CRM system. We’ve all been astonished at the change it has made to almost every facet of our business. We’re on top of leads, interacting with customers, and tracking every call now using our integration between InGenius Connector and Salesforce.com.

But, we wanted to do more – we wanted to set up a system where we could call customers who have downloaded our software, and help them with the installation and configuration of the application. As with most telephony applications, it can be complicated to set up because of the many different types of phone systems out there.

So, we came up with a plan:

  1. User obtains a trial key from any of our download pages,
  2. The registration system sends an email to the user, with their trial key,
  3. The registration system also sends an email to a special email address at Salesforce.com, containing the registration info,
  4. Some custom Apex code at Salesforce.com parses the email, and creates a lead, and a task showing what the user downloaded.

Details:

So, here’s what we did, in more detail:

1) Create Email

We modified our registration system to send an email when a trial key is requested. The email looks like this:

Subject: [Trial Key]
Source:AUTOMATION
 Campaign:
 FirstName:Bob
 LastName:Smith
 Email:bob@bob.com
 Phone:555-1212
 Company:Bob's Baker
 Country:Canada
 Industry:
 Dealer:YES
 Product:IC
 Coupon:11111-22222-33333-44444-5555
 Platform_OS: Windows
 Platform_CRM:Salesforce.com
 Platform_TELEPHONY:Asterisk

2) Create Apex Class

We created an Apex Class to handle the incoming mail. The class parses the incoming email, then does the following:

  1. Checks to see if there’s a contact with this email address,
  2. Checks to see if there’s a lead with this email address,
  3. If not found, then create a lead with the user’s info,
  4. Create a task with the details of the product the user has downloaded. Creating a task is convenient because we can automatically handle the case where a user trials more than one product – they just get created as tasks on a lead/contact.

The Apex code looks like this:

Note that the variables ending in __c are custom variables in our Salesforce.com installation.

global class InGenius_Integration_Registration_Email implements Messaging.InboundEmailHandler {
 global Messaging.InboundEmailResult handleInboundEmail(
   Messaging.InboundEmail email,
   Messaging.InboundEnvelope envelope) {
    Messaging.InboundEmailResult result = new Messaging.InboundEmailresult();
    String EmailPlainText= '';
    string EmailSource;
    string EmailCampaign;
    string EmailFirstName;
    string EmailLastName;
    string EmailEmail;
    string EmailPhone;
    string EmailCompany;
    string EmailCountry;
    string EmailIndustry;
    string EmailDealer;
    string EmailProduct;
    string EmailCoupon;
    string EmailPlatform_OS;
    string EmailPlatform_CRM;
    string EmailPlatform_TELEPHONY;
    Boolean found = false;
    ID ContactId;
    Lead insertedLead;
    System.debug('Email Received from: ' + envelope.fromAddress + ' (' + email.subject + ')' );
    // Ignore emails with the incorrect subject
    if( email.subject != '[TRIAL KEY]' ) {
        System.debug('Email rejected: Wrong Subject(' + email.subject + ')' );
        return result;
    }
    try {
        EmailPlainText = email.plainTextBody;
        String[] emailbody=email.plainTextBody.split('\n',0);
        System.debug(emailbody);
        // THIS IS NOT a terrific way to parse the email, but it works...
        // If the email format changes, by even ONE character, this will fail.
        EmailSource =             emailbody[0].substring(7);
        EmailCampaign =           emailbody[1].substring(9);
        EmailFirstName =          emailbody[2].substring(10);
        EmailLastName =           emailbody[3].substring(9);
        EmailEmail =              emailbody[4].substring(6);
        EmailPhone =              emailbody[5].substring(6);
        EmailCompany =            emailbody[6].substring(8);
        EmailCountry =            emailbody[7].substring(8);
        EmailIndustry =           emailbody[8].substring(9);
        EmailDealer =             emailbody[9].substring(7);
        EmailProduct =            emailbody[10].substring(8);
        EmailCoupon =             emailbody[11].substring(7);
        EmailPlatform_OS =        emailbody[12].substring(12);
        EmailPlatform_CRM =       emailbody[13].substring(13);
        EmailPlatform_TELEPHONY = emailbody[14].substring(19);
        if( EmailDealer=='YES' )
            EmailDealer='Dealer';
        else
            EmailDealer='End User';
        System.debug(EmailSource);
        System.debug(EmailCampaign);
        System.debug(EmailFirstName);
        System.debug(EmailLastName);
        System.debug(EmailEmail);
        System.debug(EmailPhone);
        System.debug(EmailCompany);
        System.debug(EmailCountry);
        System.debug(EmailIndustry);
        System.debug(EmailDealer);
        System.debug(EmailProduct);
        System.debug(EmailCoupon);
        System.debug(EmailPlatform_OS);
        System.debug(EmailPlatform_CRM);
        System.debug(EmailPlatform_TELEPHONY);
    }
    catch( exception e4 ) {
        System.Debug('ProcessTrial Failure: Could Not parse email');
        return result;
    }
    // Try to lookup any contacts based on the email from address
    // If there is more than 1 contact with the same email address,
    // we just use the first match
    try {
        // Does a contact exist with this email?
        List<Contact> contactList = [Select Id, Name, Email From Contact Where Email = :EmailEmail Limit 1];
        if( !contactList.IsEmpty()) {
            ContactId = contactList[0].Id;
            System.Debug('Found Existing Contact:' + contactList[0].Name);
            found = true;
        }
        else {
            // Does a Lead exist with this email?
            List<Lead> leadList = [Select Id, Name, Email From Lead Where Email = :EmailEmail Limit 1];
            if( !leadList.IsEmpty()) {
                ContactId = leadList[0].Id;
                System.Debug('Found Existing Lead:' + leadList[0].Name);
                found = true;
            }
            else {
                // Create a Lead with this email
                Lead leadToInsert = new lead(
                    FirstName=EmailFirstName,
                    LastName=EmailLastName,
                    email=EmailEmail,
                    Company=EmailCompany,
                    Country=EmailCountry,
                    Industry=EmailDealer,
                    Status='Working - Key Issued',
                    Phone=EmailPhone,
                    LeadSource=EmailCampaign,
                    Product__c = EmailProduct,
                    TrialKey__c = EmailCoupon,
                    Phone_System__c=EmailPlatform_TELEPHONY,
                    Users_CRM__c=EmailPlatform_CRM);
                insert(leadToInsert);
                ContactId = leadToInsert.Id;
                System.Debug('Created Lead' + EmailFirstName + ' ' + EmailLastName + ' ' + EmailCompany + ' ' + ContactId);
                found = true;
            }
        }
    }
    catch (exception e2) {
        System.Debug('ProcessTrial Failure: Could Not Create Lead:' +  EmailFirstName + ' ' + EmailLastName + ' ' + e2);
    }
    if( found ) {
        try {
            // New Task object to be created
            Task[] newTask = new Task[0];
            // Add a new Task to the contact record we just found or created above.
            newTask.add(new Task(
                Description =  EmailPlainText,
                Priority = 'Normal',
                Status = 'Key Issued',
                Subject = EmailProduct,
                Product__c = EmailProduct,
                RegistrationCoupon__c = EmailCoupon,
                //IsReminderSet = true, // optional, set a reminder
                //ReminderDateTime = System.now()+2, // Set reminder for 2 days in the future.
                WhoId =  ContactID));
            insert newTask;
            System.debug('New Task: ' + newTask );
        }
        catch (exception e3) {
            System.debug('ProcessTrial Failure: Create New Task Failed: ' + e3 );
        }
    }
    else {
        System.Debug('ProcessTrial Failure: Could Not Create Lead:' +  EmailFirstName + ' ' + EmailLastName);
        return result;
    }
    result.success = true;
    return result;
 }

3) Configure Email Service

Once the Apex class is created, then you need to go to Develop -> Email Services and add a new Email Service to handle the incoming mail. This is where you’ll get the unique email address. Note also, that you may have to adjust the permissions, and adjust settings for which emails you accept mail from. By default this is quite locked down by Salesforce.com.

4) Last Step:

We hired Katy! Katy looks after calling customers when they’ve downloaded a trial version of our software, and make sure that the install goes smoothly. Thanks Katy!

Further Notes:

  • We are planning to add additional code to update the contact once a user purchases our software.
  • We are planning to improve the email parsing.
  • We had quite a few issues getting the debugging to work reliably at Salesforce.com. It is not clear how to enable debugging, and how to extract debug logs.
Advertisements

Tags: , , , ,

%d bloggers like this: