This article is relevant if you are seeking a best practice for NetSuite for lead generation.
Background
NetSuite has good tools for marketing automation and lead generation. However, like many things in NetSuite, if you are willing to invent a bit, you can make business practices and CRM management much better.
In most organizations, leads are obtained from many sources. Examples may be from a web site contact form, to trade show leads, and purchased leads. The nature of lead management means that you may have minimal information on the individual who my be interested in your products and services. Often it may be a name, email address and the source of where this was obtained.
In all CRM activities, duplicate records are to be avoided as it will create noise, increase your costs, and lower your ability to make good assessments of your campaign work effectiveness. NetSuite’s lead management tools help you avoid duplicates by offering warnings include tools to help de-duplicate. Yet, even with these tools, duplicates are common especially when there are multiple sources for obtaining leads.
A Better NetSuite Lead Import Practice
NetSuite’s CRM offers a campaign capacity. While we can get sophisticated with campaign management, for this discussion, we will keep it simple. NetSuite offers simple out of the box campaigns. A new lead, via its source, can be associated with a NetSuite campaign. Each campaign has an associated “[Default Event]”. The default event will be used to hold information about a “response” which tells a marketing manager that there has been interaction with the organization.
The best practice is to add a lead to the system during the very first interaction. Subsequent interactions represent responses to various offers for products and services conversation. The best practice is to track subsequent communications as responses to campaign efforts. This will allow marketers to understand behavior and better tailor their communications. That said, the challenge is that a subsequent response may come in the form of another lead record to import due to the way third party systems or marketing and sales practices are organized.
Use a Custom Lead Import Table with a Custom Mass Update
Instead of importing leads directly into NetSuite lead table, instead, create a custom CSV lead import table that will pose no threat to duplicate records in the environment. See image for an overview. From there, use a custom mass update to read each imported record and decide if a new NetSuite lead record should be created or a campaign response should be added. Once this practice is stabilized, it can be hooked up for real time updates against inbound customer contact forms or other integrated systems.
Sample SuiteScript Lead Import and Campaign Response Pattern
The following SuiteScript code pattern illustrates the logic offered in the diagram above. For other SuiteScript developers, enjoy the code pattern for adding a NetSuite address record and a campaign response.
var CONST_NEW_LEAD_STATUS = 19; // Lead - Show //------------------------------------------------------------------ //Function: MassUpdate_LIR (Lead Import Record) //Record: MKTG - Lead Import Record : customrecord_cust_lir //Script Type: Mass Update //Description: When a lead import record is created, immediately lookup customer // and add campaign response or add a new lead if not found //Date: 20150301 //------------------------------------------------------------------ function MassUpdate_LIR(rectype, recid) { var record = nlapiLoadRecord(rectype, recid); //noempty custom function returns a default value if there is no data in the first parameter var custrecord_lir_customer = noempty(record.getFieldValue("custrecord_lir_customer"), ''); var custrecord_lir_campaign = noempty(record.getFieldValue("custrecord_lir_campaign"), ''); var custrecord_lir_companyname = noempty(record.getFieldValue("custrecord_lir_companyname"), ''); var custrecord_lir_firstname = noempty(record.getFieldValue("custrecord_lir_firstname"), ''); var custrecord_lir_lastname = noempty(record.getFieldValue("custrecord_lir_lastname"), ''); var custrecord_lir_title = noempty(record.getFieldValue("custrecord_lir_title"), ''); var custrecord_lir_email = noempty(record.getFieldValue("custrecord_lir_email"), ''); var custrecord_lir_phone = noempty(record.getFieldValue("custrecord_lir_phone"), ''); var custrecord_lir_addr1 = noempty(record.getFieldValue("custrecord_lir_addr1"), ''); var custrecord_lir_addr2 = noempty(record.getFieldValue("custrecord_lir_addr2"), ''); var custrecord_lir_city = noempty(record.getFieldValue("custrecord_lir_city"), ''); var custrecord_lir_state = noempty(record.getFieldValue("custrecord_lir_state"), ''); var custrecord_lir_zipcode = noempty(record.getFieldValue("custrecord_lir_zipcode"), ''); var custrecord_lir_country = noempty(record.getFieldValue("custrecord_lir_country"), ''); if (custrecord_lir_customer.length > 0){ nlapiLogExecution('ERROR', 'customer record already exists for this lead record'); return; } // does this customer already exist? //custom lookup_customer function uses the email address as the key; var customer_id = lookup_customer(custrecord_lir_email); nlapiLogExecution('DEBUG', 'customer_id', customer_id); // add lead or response if (customer_id == 0){ nlapiLogExecution('DEBUG', 'creating new lead...'); // add lead var full_name = (custrecord_lir_firstname + " " + custrecord_lir_lastname).trim(); // create the record NS_record = nlapiCreateRecord('lead', {recordmode: 'dynamic'}); NS_record.setFieldValue('entitystatus', CONST_NEW_LEAD_STATUS); NS_record.setFieldValue('isperson', 'T'); NS_record.setFieldValue('companyname', custrecord_lir_companyname); NS_record.setFieldValue('firstname', custrecord_lir_firstname); NS_record.setFieldValue('lastname', custrecord_lir_lastname); NS_record.setFieldValue('title', custrecord_lir_title); NS_record.setFieldValue('email', custrecord_lir_email); NS_record.setFieldValue('phone', custrecord_lir_phone); nlapiLogExecution('DEBUG', custrecord_lir_companyname, custrecord_lir_firstname + '|' + custrecord_lir_lastname + '|' + custrecord_lir_title); NS_record.setFieldValue('leadsource', custrecord_lir_campaign); //Add first line to sublist NS_record.selectNewLineItem('addressbook'); NS_record.setCurrentLineItemValue('addressbook', 'defaultshipping', 'T'); //This field is not a subrecord field. NS_record.setCurrentLineItemValue('addressbook', 'defaultbilling', 'T'); //This field is not a subrecord field. NS_record.setCurrentLineItemValue('addressbook', 'label', custrecord_lir_addr1); //This field is not a subrecord field. //create address subrecord var subrecord = NS_record.createCurrentLineItemSubrecord('addressbook', 'addressbookaddress'); //set subrecord fields subrecord.setFieldText('country', custrecord_lir_country); //Country must be set before setting the other address fields subrecord.setFieldValue('attention', noempty(full_name,'')); subrecord.setFieldValue('addressee', custrecord_lir_companyname); subrecord.setFieldValue('addrphone', custrecord_lir_phone); subrecord.setFieldValue('addr1', custrecord_lir_addr1); subrecord.setFieldValue('addr2', custrecord_lir_addr2); subrecord.setFieldValue('city', custrecord_lir_city); subrecord.setFieldValue('state', custrecord_lir_state); subrecord.setFieldValue('zip', custrecord_lir_zipcode); //commit subrecord and line item subrecord.commit(); NS_record.commitLineItem('addressbook'); nlapiLogExecution('DEBUG', 'create lead ' + custrecord_lir_companyname); var cus_id = nlapiSubmitRecord(NS_record, false, true); nlapiLogExecution('AUDIT', 'created lead ' + custrecord_lir_companyname, cus_id); // add the new customer id to the lead record record.setFieldValue('custrecord_lir_customer', cus_id); nlapiSubmitRecord(record, false, true); } else { nlapiLogExecution('DEBUG', 'Adding campaign response for', customer_id); // add campaign response var new_rec = nlapiCreateRecord('campaignresponse'); new_rec.setFieldValue('entity', customer_id); new_rec.setFieldValue('leadsource', custrecord_lir_campaign); new_rec.setFieldText('campaignevent', '[Default Event]'); new_rec.setFieldValue('newresponsedate', nlapiDateToString(new Date(), 'date')); new_rec.setFieldText('response', 'Responded'); nlapiSubmitRecord(new_rec); // add the customer id to the lead record record.setFieldValue('custrecord_lir_customer', customer_id); var resp_id = nlapiSubmitRecord(record); nlapiLogExecution('AUDIT', 'Response id', resp_id); } }
Improve your NetSuite Business Practices
My team and I have been working for over 25 years in various ERP and CRM systems, what comes forth in the NetSuite system is the power of the platform. NetSuite offer so many features yet it allows us to invent solutions to specific client challenges. If you have a specific NetSuite area you want to enhance, let’s have a conversation.
Dear Martin i used part of your code to integrate outside marketing campaing in netsuite. Anyhow i cannot find the field ‘newresponsedate’ and i cannot set date i want eg new_rec.setFieldValue(‘newresponsedate’,’20xx/xx/xx’);
doesnt seem not to affect the field that looks always autocompiled with now
Looking at the SuiteScript record browser, the field value is “responsedate”. Also, be sure to use NetSuite Date Functions to set the value as using strings or standard JavaScript date objects can be problematic.
Is there a reason you do this as a mass update rather than a map/reduce? Thanks!
Michelle,
At the time of this article, 2015, we did not have map/reduce as a capacity in the platform.
Marty