function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
HNMHNM 

web-to-lead product relationship

Hi,

 

Any suggestions on how I may receive a web lead containing the product ID and quantity and have that info appear in the opportunity when it's converted?  I can do the web-to-lead bit with hidden fields etc but it just arrives as a inert  text field and there doesn't seem to be a clear way to map lead fields to the built-in product list and price book. 

 

I'm ready to dive into Apex and do it  manually but I have a feeling that I'm not the only one who has tried this.

 

Anyone been down this path before?  Any ideas?

 

 

Thanks,

 

HNM

Best Answer chosen by Admin (Salesforce Developers) 
EnthEnth

OK, here you go, seems to work. I've got 2 new Opportunity fields WebLeadQuantity__c (Number) and WebLeadProduct__c (Text). I pass my product code from my web form, not the pbe id (if you do this you can shorten the trigger slightly - but using the Product code means it will work in live and sandbox/developer edition).

 

Here's the trigger, replace the WebLead fields with your own and it should work (you can do it simpler if you never ever bulk load Opportunities):

 

* Function: If we have any web leads with products and quantity then create a line item */
trigger create_WebOpportunityLines on Opportunity (after insert) {

    // Get a list of all the WebProduct codes for our opportunities
    List<String> prodList = new List<String>();
    for (Opportunity opp : trigger.new) {
    	if (opp.WebLeadProduct__c != null) prodList.add(opp.WebLeadProduct__c);
    }
    
    // Create a map of the applicable pricebookentrys so we can reference unit prices 
    // without breaking governor limits
    Id standardPb = [SELECT Id From PriceBook2 WHERE isStandard = true][0].Id;

    Map<String, PriceBookEntry> pbeMap = new Map<String, PriceBookEntry>();
    List<PriceBookEntry> pbeList = [SELECT Id, UnitPrice, ProductCode 
    				      FROM PriceBookEntry 
    				     WHERE ProductCode IN :prodList 
    				       AND PriceBook2Id = :standardPb]; 
    // Populate the map with the list items, keyed by product code
    for (PriceBookEntry pbe : pbeList) {
    	pbeMap.put(pbe.ProductCode, pbe);
    }
    
    List<OpportunityLineItem> oliList = new List<OpportunityLineItem>();
    for (Opportunity opp : trigger.new) {
        // Check if this is a web lead - ideally expand this with the lead source to identify
        if (opp.WebLeadQuantity__c != null && opp.WebLeadProduct__c != null) {
            OpportunityLineItem oli = new OpportunityLineItem();
            oli.OpportunityId = opp.Id;
            oli.PriceBookEntryId = pbeMap.get(opp.WebLeadProduct__c).Id;
            oli.Quantity = opp.WebLeadQuantity__c;
            oli.UnitPrice = pbeMap.get(opp.WebLeadProduct__c).UnitPrice;
            oliList.add(oli);
        }
    }
    
    if (oliList.size() > 0) insert oliList;
    
}

 

 

 

All Answers

EnthEnth

I assume you already know how to Map Lead Fields on the Leads->Fields setup.

 

You can't map lead fields to product fields, they have to be mapped to Account, Contact or Opportunity fields.

 

However. If you create reciprocal custom fields on your opportunity then you can map the custom values to the Opportunity.

 

You can then write a workflow on the Opportunity Line Item (aka Opportunity Product) and use the formula editor to set the fields on your line item to the values on your opportunity. 

 

HTH

EnthEnth

Just one point, that solution would only work when you add a line item to the opportunity, if you want to automatically create the line item from the product_id and quantity then you will need to write an Apex Trigger to do so - using the technique to get the data onto the Opportunity object.

 

This is a pretty easy trigger except for the need to negotiate the Salesforce PriceBookEntry table. The easiest option is if your website holds the PriceBookEntryId for the product (assuming you have just 1 currency or default currency), otherwise it's a bit more tricky but still possible to write the Apex to find the PBEId for a given product code in the standard price book.

HNMHNM

This is a really helpful suggestion, I have just one currency and I'll try including the PBEId into the webform. 

 

Thanks,

 

HNM

EnthEnth

Just tried it out and hit a snag. You'll have to look up the pricebook anyway as you need to set the price on the OLI before it will let you insert.

 

Either insert a value of 0 (not great but easy) or lookup the PriceBookEntry - which also means you don't need to code up your PBEIds in your web page. I'm just testing some code for this, give me 10 mins and I'll paste it here.

EnthEnth

OK, here you go, seems to work. I've got 2 new Opportunity fields WebLeadQuantity__c (Number) and WebLeadProduct__c (Text). I pass my product code from my web form, not the pbe id (if you do this you can shorten the trigger slightly - but using the Product code means it will work in live and sandbox/developer edition).

 

Here's the trigger, replace the WebLead fields with your own and it should work (you can do it simpler if you never ever bulk load Opportunities):

 

* Function: If we have any web leads with products and quantity then create a line item */
trigger create_WebOpportunityLines on Opportunity (after insert) {

    // Get a list of all the WebProduct codes for our opportunities
    List<String> prodList = new List<String>();
    for (Opportunity opp : trigger.new) {
    	if (opp.WebLeadProduct__c != null) prodList.add(opp.WebLeadProduct__c);
    }
    
    // Create a map of the applicable pricebookentrys so we can reference unit prices 
    // without breaking governor limits
    Id standardPb = [SELECT Id From PriceBook2 WHERE isStandard = true][0].Id;

    Map<String, PriceBookEntry> pbeMap = new Map<String, PriceBookEntry>();
    List<PriceBookEntry> pbeList = [SELECT Id, UnitPrice, ProductCode 
    				      FROM PriceBookEntry 
    				     WHERE ProductCode IN :prodList 
    				       AND PriceBook2Id = :standardPb]; 
    // Populate the map with the list items, keyed by product code
    for (PriceBookEntry pbe : pbeList) {
    	pbeMap.put(pbe.ProductCode, pbe);
    }
    
    List<OpportunityLineItem> oliList = new List<OpportunityLineItem>();
    for (Opportunity opp : trigger.new) {
        // Check if this is a web lead - ideally expand this with the lead source to identify
        if (opp.WebLeadQuantity__c != null && opp.WebLeadProduct__c != null) {
            OpportunityLineItem oli = new OpportunityLineItem();
            oli.OpportunityId = opp.Id;
            oli.PriceBookEntryId = pbeMap.get(opp.WebLeadProduct__c).Id;
            oli.Quantity = opp.WebLeadQuantity__c;
            oli.UnitPrice = pbeMap.get(opp.WebLeadProduct__c).UnitPrice;
            oliList.add(oli);
        }
    }
    
    if (oliList.size() > 0) insert oliList;
    
}

 

 

 

This was selected as the best answer
HNMHNM

Well thank you very much for this,  I'm new to Apex so I'm creating some psuedo code to layout the steps as I understand them and matching them to your code to see if I've got it right.  So it will take a day before I test and get back to you.

 

Thanks again,

 

HNM

HNMHNM

Enth,

 

This worked really well.  I really appreciate it!

 

HNM

EnthEnth

No worries, don't be surprised to see it on the AppExchange!