Magnolia 5.6 reached end of life on June 25, 2020. This branch is no longer supported, see End-of-life policy.
Magnolia connects to Salesforce to capture and enrich leads. This gives you the possibility to capture more precise leads and nurture leads by providing Salesforce with the data that leads are using. Magnolia's personalization feature can retrieve information from Salesforce to provide tailored content to web visitors, proving a richer user experience.
Create a connected app in SalesForce admin central.
App Setup → Create → Apps
.Connected Apps → New
Fill:Connected App Name
, API Name
(values don't matter)Contact Email
API (Enable OAuth Settings)
Callback URL
: list all your public instances: http(s)://<domain>/<contextPath>/callback
, e.g http://localhost:8080/magnoliaPublic/callbackSave
.Edit
and Manage
).Consumer Key, Consumer Secret
to your Magnolia instance (see the next section).Personal Setup → My Personal Information → Reset My Security Token
Security token
from the email you've just received to your Magnolia instance (see the next section). We need to authenticate Accounts to be able provide personalized content for them. Accounts are not logged into Salesforce as Salesforce users but only into Magnolia context. You need to provide a custom text field to Accounts module on you Salesforce instance under info.magnolia.resteasy.client.RestEasyClientDefinition info.magnolia.resteasy.client.factory.RestEasyClientFactory https://help.salesforce.com/apex/HTViewHelpDoc?id=connected_app_create.htm * * * https://help.salesforce.com/apex/HTViewHelpDoc?id=user_security_token.htm *Setup - App Setup - Customize - Accounts - Fields
where the passwords will be stored. Define the name of this field under config:server/filters/SalesForceAccountAuthenticationFilter@passwordFieldName
.Node name Value https://YOUR_SALES_FORCE_INSTANCE/services
Sample pages
The first think which we need is a command which performs rest calls to the Salesforce instance. There are four basic command for authentication, get and post request already implemented. You can see the example of the rest call to retrieve all the campaigns names from Salesforce.
SalesForceCommands parameters | ||
Name | Constant field | Description values |
---|---|---|
Object name | info.magnolia.salesforce.command.AbstractSalesForceCommand#PARAMETER_S_OBJECT_NAME = "salesForceSObjectName" | A string representing module name (e.g. Account). |
Query | info.magnolia.salesforce.command.SalesForceQueryCommand#PARAMETER_QUERY = "salesForceQuery" | A query to be performed. |
Request body | info.magnolia.salesforce.command.SalesForcePostCommand#PARAMETER_BODY = "salesForceBody" | An instance of org.codehaus.jackson.JsonNode. |
Http method | info.magnolia.salesforce.command.SalesForcePostCommand#PARAMETER_HTTP_METHOD = "salesForceMethod" | info.magnolia.salesforce.command.SalesForcePostCommand# METHOD_PATCH = "PATCH" |
public class MyTestClass { private final RestEasyCommandsManager commandsManager; @Inject public MyTestClass(RestEasyCommandsManager commandsManager) { this.commandsManager = commandsManager; } public JsonNode execute(final String command, final String path, final Map<String, Object> parameters) throws Exception { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put(SalesForceQueryCommand.PARAMETER_QUERY, "SELECT Campaign.Name FROM Campaign"); return this.getCommandsManager().executeCommand(SalesForceQueryCommand.CATALOG, "SalesForceQueryCommand", SalesForceQueryCommand.PARAMETER_RESULT, parameters); }} }
info.magnolia.salesforce.command.SalesForceAuthorizeCommand info.magnolia.salesforce.command.SalesForceGetCommand info.magnolia.salesforce.command.SalesForceQueryCommand info.magnolia.salesforce.command.SalesForcePostCommandNode name Value
The samples contain traits for the Personalization module. Those are able to retrieve informations from Salesforce to provide personalized content. In this chapter is described how you can create a custom trait on the provided samples. If you've never created personalized content in Magnolia, please see Creating custom traits.
Trait detector filter true info.magnolia.salesforce.personalization.SalesForceDetectorFilter info.magnolia.salesforce.personalization.SalesForceTraits SELECT Type FROM Opportunity o, o.Account a WHERE a.Name='{salesForceExternalName}' SELECT Id, password__c, Name, Industry, BillingStreet, BillingState, BillingPostalCode, BillingCity, BillingCountry FROM Account WHERE Name = '{salesForceExternalName}' SELECT Campaign.Name FROM Opportunity o, o.Account a WHERE a.Name='{salesForceExternalName}'Node name Value
A trait voter decides if a certain page variant has to be served to the current user or not. There's not much difference between a
SalesForceVoter
trait voter and any other voter. The default trait voter for Salesforce doesn't use any special logic compared to info.magnolia.externaltraits.filter.AbstractJsonTraitVoter
. This voter just splits the passed String value to module name - property path - expected property value regexp
. For example the value is Opportunity-Type-Existing Business.
The voter looks for Opportunity trait which are all the opportunities related to logged in account. Then searches for type of all opportunities and returns true if there is at least one opportunity with the type Existing Business.
public class SalesForceVoter extends AbstractJsonTraitVoter { public SalesForceVoter() { super(SalesForceTraits.class); } }
Parameter converter is needed for Personalization#Personalization-Preview. It Converts String to a corresponding trait class holding a json and vice versa. There a no special logic in the default
SalesForceParameterConverter
. It expect a property value in the format traitName-propertyPath-expectedValueRegexp
. For example we want to check if there is an Opportunity
with the Type
Existing Business
, we set the value Opportunity-Type-Existing Business
via choose audience dialog to a page variant.
public class SalesForceParameterConverter extends AbstractJsonTraitParameterConverter { public SalesForceParameterConverter() { super(SalesForceTraits.class); } }