Display Salesforce CMS Content
Display CMS Content in Experience Builder Sites
Before Using CMS Connect
Edit a CMS Connection
Manage CMS Connections
CMS Connector Page Code
CMS Connect Recommendations for Optimal Usage
CMS Connect Examples
If you use CMS Connect to render personalized content in your Experience Builder site, your setup process requires the following connector JSP page code.
To get your personalized content from Adobe Experience Manager working in your site, create a JSP connector page that contains the following code. You can add to this code as needed.
The connector JSP page logic includes these sections.
componentUrls—an array of component path URLs for which personalization must be runasset—a JavaScript asset specified in the Asset Path field in the CMS connection that is injected when the JSP page loadsclientContext—IP address, language, country, state, city, latitude, and longituderequestId—a token returned as part of the postMessage to validate the authenticity of the responsedomain—the domain of the site requesting personalized contentpostMessage to your site. Construct the script src like this: \<your_site_domain/_sfdc/cms-connect/aem_personalization/salesforceConnector.js>. Any asset specified in the Asset Path field in the CMS connection is included in your JSP.postMessage.To ensure that the connector page code gets personalization working in your site, follow these guidelines.
postMessage.Note
1<!-- Salesforce connector to run AEM personalization-->
2<%@include file="/libs/foundation/global.jsp"%><%
3%><%@page import="
4 java.io.StringWriter,
5 java.net.URL,
6 com.day.cq.wcm.api.WCMMode,
7 com.day.cq.wcm.core.stats.PageViewStatistics,
8 com.day.text.Text,
9 java.util.ResourceBundle,
10 com.day.cq.i18n.I18n,
11 com.day.cq.personalization.TargetedContentManager,
12 com.day.cq.personalization.ClientContextUtil,
13 org.apache.sling.commons.json.JSONObject,
14 org.apache.sling.commons.json.JSONArray,
15 com.day.cq.commons.JS,
16 org.apache.sling.engine.*,
17 org.apache.sling.api.SlingHttpServletRequest,
18 org.apache.sling.api.resource.ResourceResolver,
19 java.util.*,
20 com.day.cq.*" %><%
21
22 %><cq:includeClientLib categories="personalization.kernel"/><%
23 if(request.getParameter("payload") != null) {
24 // For every component URL, get the Teasers object and strategy.
25 JSONObject payload = new JSONObject(request.getParameter("payload"));
26 JSONArray compUrls = payload.getJSONArray("componentUrls");
27 String asset = payload.getString("asset");
28 HashMap<String, JSONArray> teaserMap = new HashMap<>();
29 HashMap<String, String> strategyMap = new HashMap<>();
30 ResourceBundle resourceBundle = slingRequest.getResourceBundle(null);
31 I18n i18n = new I18n(resourceBundle);
32 final TargetedContentManager targetedContentManager = sling.getService(TargetedContentManager.class);
33 SlingRequestProcessor requestProcessor = sling.getService(SlingRequestProcessor.class);
34 ResourceResolver resolver = slingRequest.getResourceResolver();
35 for(int j=0; j<compUrls.length(); j++) {
36
37 JSONArray allTeasers = new JSONArray();
38 String strategy = "";
39
40 try {
41 String requestPath = new URL(compUrls.getString(j)).getPath().replaceAll(".html", "");
42
43 Resource resourceObject = resolver.getResource(requestPath);
44
45 Node rootNode = resourceObject.adaptTo(Node.class);
46 ValueMap prop = resourceObject.adaptTo(ValueMap.class);
47
48 // Get the strategy path
49 String strategyPath = prop.get("strategyPath", (String) null);
50 if (strategyPath != null) {
51 strategy = Text.getName(strategyPath);
52 strategy = strategy.replaceAll(".js", "");
53 }
54
55 // Get the campaign path
56 String campaignPath = prop.get("campaignpath", (String) null);
57 String campaignClass = "";
58 if (campaignPath != null) {
59 Page campaignPage = pageManager.getPage(campaignPath);
60 if (campaignPage != null) {
61 campaignClass = "campaign-" + campaignPage.getName();
62 }
63 }
64
65 JSONObject teaserInfo = targetedContentManager.getTeaserInfo(resourceResolver, campaignPath, requestPath);
66 allTeasers = teaserInfo.getJSONArray("allTeasers");
67
68 // Add selectors from the current page for the mobile case, e.g. "smart", "feature" etc.
69 String selectors = slingRequest.getRequestPathInfo().getSelectorString();
70 selectors = selectors != null ? "." + selectors : "";
71
72 for (int i = 0; i < allTeasers.length(); i++) {
73 JSONObject t = (JSONObject) allTeasers.get(i);
74 t.put("url", t.get("path") + "/_jcr_content/par" + selectors + ".html");
75 }
76
77 // Use "default" child node as default teaser and add at the end of the teaser list
78 JSONObject defaultTeaser = new JSONObject();
79 defaultTeaser.put("path", resourceObject.getPath() + "/default");
80 defaultTeaser.put("url", resourceObject.getPath()+ ".default" + selectors + ".html");
81 defaultTeaser.put("name", "default");
82 defaultTeaser.put("title", i18n.get("Default"));
83 defaultTeaser.put("campainName", "");
84 defaultTeaser.put("thumbnail", resourceObject.getPath() + ".thumb.png");
85 allTeasers.put(defaultTeaser);
86 } catch (Exception e) {
87 // If an exception occurs for any of the component URLs, we will put default values in teaserMap and strategyMap
88 }
89
90 teaserMap.put(compUrls.getString(j), allTeasers);
91 strategyMap.put(compUrls.getString(j), strategy);
92
93 }
94
95 String requestId = payload.getString("requestId");
96 String domain = payload.getString("domain");
97 JSONObject teaserJson = new JSONObject(teaserMap);
98 JSONObject strategyJson = new JSONObject(strategyMap);
99
100 %>
101
102 <html>
103 <head>
104 <script type="text/javascript" src="/etc/clientlibs/granite/jquery.js"></script>
105 <script type="text/javascript" src="/etc/clientlibs/granite/utils.js"></script>
106 <script type="text/javascript" src="/etc/clientlibs/granite/jquery/granite.js"></script>
107 <script type="text/javascript" src="/etc/clientlibs/foundation/jquery.js"></script>
108 <script type="text/javascript" src="/etc/clientlibs/foundation/shared.js"></script>
109 <script type="text/javascript" src="/etc/clientlibs/granite/lodash/modern.js"></script>
110 <script type="text/javascript" src="/etc/clientlibs/foundation/personalization/kernel.js"></script>
111 <!--TODO: Include the script that will send a postMessage to your site. The path of the JS is <your site domain/_sfdc/cms-connect/aem_personalization/salesforceConnector.js> -->
112 <!--The below line injects a script that is passed in the request -->
113 <script type="text/javascript" src="<%= asset %>"></script>
114 </head>
115
116 <body>
117 <script>
118 var teaserMap = <%= teaserJson %>;
119 var strategyMap = <%= strategyJson %>;
120 var requestId = "<%= requestId %>";
121 var domain = "<%= domain %>";
122 setClientContext();
123 var resolvedTeasers = getResolvedTeasers(teaserMap, strategyMap);
124 CMS_CONNECT_PERSONALIZATION_AEM.responsePersonalization(resolvedTeasers, requestId, domain);
125
126
127 // This is a sample client-context that can be used.
128 // Salesforce provides the client-context object that can be used to build the JSON.
129 /**
130 * @typedef {object} payload.clientContext
131 * @property {String} ipAddress User's ipAddress
132 * @property {String} language User language
133 * @property {String} country User's country
134 * @property {String} state User's state
135 * @property {String} city User's city
136 * @property {String} latitude User's latitude
137 * @property {String} longitude User's longitude
138 */
139 function setClientContext() {
140 var payload = <%= payload %>;
141 var clientContext = payload.clientContext;
142 // Set client-context
143 var clientContextJson = {};
144 clientContextJson.surferinfo = {
145 'IP': clientContext.ipAddress
146 };
147 clientContextJson.profile = {
148 'language': clientContext.language,
149 'country': clientContext.country,
150 'state': clientContext.state,
151 'city': clientContext.city
152 };
153 clientContextJson.geolocation = {
154 'latitude': clientContext.latitude,
155 'longitude': clientContext.longitude
156 };
157 CQ_Analytics.ClientContextMgr.clientcontext = clientContextJson;
158 }
159
160 /**
161 * Runs personalization logic for all the component URLs requested
162 * @param {teaserMap} Map of componentUrl as key and teasers object for the component
163 * @param {strategyMap} Map of componentUrl as key and strategy for the component
164 */
165 function getResolvedTeasers(teaserMap, strategyMap) {
166 var resolvedTeasers = {};
167 for (var key in teaserMap) {
168 try {
169 if (teaserMap.hasOwnProperty(key)) {
170 var resolvedTeaser = CQ_Analytics.Engine.resolveTeaser(teaserMap[key], strategyMap[key], null);
171 resolvedTeasers[key] = resolvedTeaser.url.substring(1);
172 }
173 } catch (err) {
174 // If any error occurs in calculating resolved teaser for a component url, we save it as error
175 resolvedTeasers[key] = "error";
176 }
177 }
178
179 return resolvedTeasers;
180 }
181 </script>
182 </body>
183 </html>
184 <%
185 }
186 %>