Saturday, July 18, 2020

Configure Sling Mapping for Resource Resolution in Adobe Experience Manager — Deep Dive

This tutorial explains the complete details on configuring sling mapping for resource resolution in Adobe Experience Manager.
Resource mapping is used to define the content mapping and redirects in AEM.
I have enabled two sample domains www.example1.com and www.example2.com pointing to /content/wknd/us/en and /content/wknd/ca/en nodes respectively(sample wknd website nodes).
The flow is as below


sling-resource-mapping-in-adobe-experience-manager

The user request for www.example1.com and www.example2.com, the Apache redirects the user to the domain specific landing pages and also redirect the user to the shortened URL(hide/content/wknd/<country code> if user access the page with full content path). The dispatcher pass through the shortened content URL’s to publisher by appending the full content path /content/wknd/<country code>
As first step let us enable the virtual host configurations for www.example1.com and www.example2.com in Apache(Dispatcher)
“DispatcherUseProcessedURL on” configuration should be enabled in dispatcher configuration to enable the Pass Through URL’s to work
e.g
Now both the domains www.example1.com and www.example2.com are accessible, this will display the mapped landing page content but the internal page links still point to the complete URL(/content/wknd/<<country code>>)


Image for post
sling-resource-mapping-in-adobe-experience-manager

Let us now enable the run mode specific(my case the server is enabled with additional run mode “dev”) ResourceResolver configuration — “Apache Sling Resource Resolver Factory” to reverse map the internal full content path to the shortened URL— enable the mapping for all the required content paths.


Image for post

Now the internal page links are transformed to shortened URL based on the URL mappings in the Resource Resolver.


Image for post
Image for post

This approach has multiple draw backs —
  • the mapping don’t supports the regex expressions
  • it doesn’t support cross-site links because this rewriting method is not domain-aware
  • reverse map the content path to the corresponding domain wont work
The incoming URL will be resolved without any issue as the dispatcher always send the complete path(e.g /content/wknd/us/en.html) to the publisher — http://localhost:4503/system/console/jcrresolver.


sling-resource-mapping-in-adobe-experience-manager
Image for post

The content path is not reversed mapped to the domain URL


Image for post

This will create issues while supporting multiple domains in the AEM platform and need to link the pages between sites(the components should identify the domain corresponding to the content path while linking the pages from different sites — ResourceResolver.map(…))
We should use the etc mapping to enable the forward resolving(resolve the incoming URL to content path) and reverse mapping (map the content path to the domain)
As a first step create an environment specific mapping folder (sling:Folder)— /etc/map.dev.publish, the etc mapping configurations won’t honor the run mode but it is possible to enable the environment specific configuration by enabling different folders e.g map.dev.publish, map.uat.publish, map.stage.publish and map.prod.publish and configure the folder to the run mode specific JCR Resolver configuration( “Apache Sling Resource Resolver Factory”).
Create a folder http or https(sling:Folder) under map.dev.publish based on the protocol used to communicate to publisher, use https even the SSL is terminated at load balancer level — the mapping details can be stored to code repository for better management.


Image for post
sling-resource-mapping-in-adobe-experience-manager
sling-resource-mapping-in-adobe-experience-manager

Enable the below Sling Mappings under /etc/map.dev.publish /http(s) based on the protocol used— this will enable the forward mapping(resolve) — map the incoming URL to the content path(forward mapping is optional as the dispatcher is already sending the complete content path to publisher) and reverse mapping (map)— map the content path to shortened DNS URL.


sling-resource-mapping-in-adobe-experience-manager
Image for post
sling-resource-mapping-in-adobe-experience-manager
Image for post

Now the forward and reverse mapping works as expected


Image for post
sling-resource-mapping-in-adobe-experience-manager
sling-resource-mapping-in-adobe-experience-manager
sling-resource-mapping-in-adobe-experience-manager
Image for post
Image for post

The resolve and map methods of org.apache.sling.api.resource.ResourceResolver interface can be used to resolve/map the resources in java services/components.
Let us now enable some additional sling mappings
Resolve(Forward Mapping) the specific incoming URL to a different content path.
e.g the incoming request to the sitemap.xml file should be internally mapped to a different location where the file is located(under /content/wknd)
Create a node sitemap_mapping of type “sling:Mapping” under /etc/map.dev.publish/www.example1.com and add the below properties


Image for post

Now the request to sitemap.xml — http://www.example.com/sitemap.xml displays the content from /content/wknd/sitemap.xml(enabled sample sitemap.xml file under /content/wknd)


Image for post
sling-resource-mapping-in-adobe-experience-manager

Multiple forward mappings can be created as required for the specific domain.
Reverse Map the URLs to remove the .html extension from the page links
Let us now enable additional reverse mapping to remove the html extension from internal page links.
Create a node reverse_no_html of type “sling:Mapping” under /etc/map.dev.publish/www.example1.com and add the below properties


Image for post
sling-resource-mapping-in-adobe-experience-manager
Image for post

Multiple reverse mappings can be created as required for the specific domain.
Enable external redirects for specific URL’s
Let us now enable a external redirect, redirect the request with string “test” to a external URL — https://albinsblog.com
Create a node external_redirect of type “sling:Mapping” under /etc/map.dev.publish/www.example1.com and add the below properties


sling-resource-mapping-in-adobe-experience-manager

Now the URL http://www.example1.com/test.html will be redirected to https://www.albinsblog.com
The jcr package can be downloaded from the below link

References




The sling mapping helps us to map the incoming request to the internal content path and at the same time map the internal content path to the complete DNS based shortened URL. This will enable the AEM platform to support multi tenants and allows the author to cross link the websites just through the content path(AEM automatically maps the content path to the domain URL)


Thursday, July 16, 2020

How to configure Auto Completion enabled search form with Adobe Search and Promote?

This tutorial explains the details on configuring the Auto Completion enabled search form to a website with Adobe Search and promote.

Autocomplete, or word completion, is a feature in which the search form recommends the search terms based on the word user beginning to type.

adobe-search-and-promote-auto-completion

I am enabling the indexing through IndexConnector and enabling custom JSON based templates.

Refer the below URL for details on enabling IndexConnector and the custom templates.

Sample XML feed data

<feed xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
<channel>
<title>Product Feed</title>
<Item>
<link>https://qa.example.com/product-title/p/prod1</link>
<title>
<![CDATA[Java Title1]]>
</title>
<description>
<![CDATA[<p>Prod1 description</p>]]>
</description>
<productType>Java</productType>
<ProductId>prod1</ProductId>
<imageUrl>/content/dam/Images/product/prod1.jpg</imageUrl>
</Item>
<Item>
<link>https://qa.example.com/product-title/p/prod2</link>
<title>
<![CDATA[Java Title2]]>
</title>
<description>
<![CDATA[<p>Prod2 description</p>]]>
</description>
<productType>java</productType>
<ProductId>prod2</ProductId>
<imageUrl>/content/dam/Images/product/prod2.jpg</imageUrl>
</Item>
<Item>
<link>https://qa.example.com/product-title/p/prod3</link>
<title>
<![CDATA[Java Title3]]>
</title>
<description>
<![CDATA[<p>Prod3 description</p>]]>
</description>
<productType>java</productType>
<ProductId>prod3</ProductId>
<imageUrl>/content/dam/Images/product/prod3.jpg</imageUrl>
</Item>
<Item>
<link>https://qa.example.com/product-title/p/prod4</link>
<title>
<![CDATA[Java Title4]]>
</title>
<description>
<![CDATA[<p>Prod4 description</p>]]>
</description>
<productType>java</productType>
<ProductId>prod4</ProductId>
<imageUrl>/content/dam/Images/product/prod4.jpg</imageUrl>
</Item>
<Item>
<link>https://qa.example.com/product-title/p/prod5</link>
<title>
<![CDATA[Lava Title]]>
</title>
<description>
<![CDATA[<p>Lava description</p>]]>
</description>
<productType>Lava</productType>
<ProductId>prod5</ProductId>
<imageUrl>/content/dam/Images/product/prod5.jpg</imageUrl>
</Item>
</channel>
</feed>

The various areas of Auto-Complete can be configured through Design → Auto-Complete

Image for post

Configure and setup the options that control the generation of the auto-complete enabled search form

adobe-search-and-promote-auto-completion

Maximum suggestions — Specifies the maximum number of items to display in the auto-complete suggestions list.

Minimum input characters — Specifies the number of characters that a customer must type into the auto-complete search form before it displays suggestions.

Maximum cache entries — Specifies the maximum number of previously requested auto-complete suggestions to cache in the customer’s browser. Generally, you should leave this setting at the default of 1000. While you can completely disable browser caching by setting this option to 0, it is not recommended.

Display shadow — Adds a cosmetic drop-shadow to the auto-complete suggestions list.

Form name — Specifies the “name” attribute of the auto-complete enabled search form’s “form” tag.

Div tag ID — Specifies the ID attribute of the auto-complete enabled search form’s “div” tag.

Input tag ID — Specifies the ID attribute of the auto-complete enabled search form’s “input” tag.

Match only at beginning of phrase — Specifies whether to match the with the beginning of phrase.

Enable the required configurations and save changes

Configure the list of words and phrases that Auto-Complete displays to a customer as suggestions.

adobe-search-and-promote-auto-completion

Popular Searches Period — Controls the time period for the inclusion of words and phrases from a customer’s recent searches.

Maximum Search Count — Controls the maximum number of searched words and phrases to include in the auto-complete word list. The top words and phrases, which are also the most popular, are included.

Field Name — Each field name defines the name of one field for which to include indexed values. Use + and — to add or remove field names.

Maximum Value Count — Defines the maximum count of field values that are allowed for the selected field name. The top values, which are also the most referenced, are included.

Add these words and phrases — The auto-complete word list is populated with the words and phrases that are listed in this area

Remove these words and phrases — Entries in this area are not displayed in the auto-complete word list.Regular expressions are allowed in this list. To specify a regular expression in this list, start the line with regexp followed by a single space, followed by the regular expression. Any lines in the word list that match the regular expression are removed

Ignore Case — Duplicate entries in the auto-complete word list that differ only by alphabetic uppercase/lowercase are removed; all word list entries are forced to lowercase.

Update on Re-Index — Auto-complete word list is automatically regenerated after each successful account re-index.

After enabling the the required configurations the final word list can be previewed — the words are included from different sources “Popular Searches”, “Field Values”, “Added Words & Phrases” and “Removed Words & Phrases”

adobe-search-and-promote-auto-completion

Configure the auto-complete cascading style sheet that you want to use. Auto-Complete CSS controls the content of autocomplete_styles.css, which is included as a part of the auto-complete enabled search form.The CSS you specify here controls the visual presentation of the auto-complete suggestion list.

Image for post

Enable the required CSS changes.

Now the form configurations ready, push the changes to live. The form can be previewed by clicking on “Search Form”

Image for post

The search form HTML can be integrated to website now, retrieve the form source by clicking on “Form Source”

adobe-search-and-promote-auto-completion
<html><!--To apply your custom auto-complete CSS, add the line below (un-commented) within the head section of the page containing this search form.  -->
<head>
<link rel="stylesheet" type="text/css" href="https://content.atomz.com/xxxxxxxxxx/publish/autocomplete_styles.css?sp_css_cache_ver=2" />
</head><body>
<!-- Omniture HTML for Search w/Auto-Complete -->
<!-- Do not change the name of the form from "search_form"! -->
</br>
</br>
<div class="yui-skin-sam">
<form name="search_form" method="get" action="http://xxxxxxxxxx.guided.ss-omtrdc.net" target="_blank">
<input type="text" id="q" name="q" />
<input type="submit" value="Search" />
<div id="autocomplete"></div>
<input type="hidden" name="sp_cs" value="UTF-8" />
</form>
</div>
<!-- For maximum performance, place these tags at the bottom of the body section of the page(s) containing this search form. -->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/utilities/utilities.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/datasource/datasource-min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/autocomplete/autocomplete-min.js"></script>
<script type="text/javascript" src="https://content.atomz.com/xxxxxxxxxx/publish/autocomplete_data.js?sp_js_cache_ver=6"></script>
</body></html>
Image for post

The values of sp_css_cache_ver and sp_js_cache_ver changed on every modification of auto complete setup.

The updated CSS and JavaScript values can be retrieved by enabling the presentation template, enable the required configuration in the presentation template based on the template type, I am using JSON template type in my case

custom_presentation_json.tmpl (Sample with minimal configuration)

<guided-content-type-header content="application/json" />
<guided-if-query-param-defined gsname="callback" /><guided-query-param gsname="callback" />(</guided-if-query-param-defined>
{
"general" :
{
"query" : "<guided-query-param gsname='q' />",
"total" : "<guided-results-total />",
"page_lower" : "<guided-results-lower>",
"page_upper" : "<guided-results-upper>",
"page_total": "<guided-page-total/>"
},
"search-form":
{
"auto-complete-enabled": "<guided-if-autocomplete>1<guided-else-autocomplete>0</guided-if-autocomplete>",
"css": "<guided-ac-css escape="ijson"/>" ,
"form-content": "<guided-ac-form-content escape="ijson"/>",
"javascript": "<guided-ac-javascript escape="js"/>"
}
,
"facets" :
[

],
"results" :
[
<guided-results gsname="default">
{
"index" : "<guided-result-index />",
"title" : "<guided-result-field gsname="title" escape="ijson" />",
"productType" : "<guided-result-field gsname="productType" escape="ijson" />"
}<guided-if-not-last>,</guided-if-not-last>
</guided-results>
]
}
<guided-if-query-param-defined gsname="callback">)</guided-if-query-param-defined>

Retrieve the details through http://xxxxxxxxxx.guided.ss-omtrdc.net/?do=json

{
"general": {
"query": "",
"total": "223",
"page_lower": "1",
"page_upper": "10",
"page_total": "23"
},
"search-form": {
"auto-complete-enabled": "1",
"css": "<link rel=\"stylesheet\" type=\"text/css\" href=\"//content.atomz.com/xxxxxxxxxx/publish/autocomplete_styles.css?sp_js_param=2\" />\n",
"form-content": "<div id=\"autocomplete\"></div>\n\n",
"javascript": "<script type=\"text/javascript\" src=\"
http://ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/utilities/utilities.js\"></script>\n<script type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/datasource/datasource-min.js\"></script>\n<script type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/autocomplete/autocomplete-min.js\"></script>\n<script type=\"text/javascript\" src=\"//content.atomz.com/xxxxxxxxxx/publish/autocomplete_data.js?sp_js_param=4\"></script>"
}
,
"facets": [],
"results": [
{
"index": "",
"title": "Book Lava title",
"productType": "Book"
},
{
"index": "",
"title": "Book Lava Title",
"productType": "Book"
},
{
"index": "",
"title": "Book Lava title",
"productType": "Book"
},
{
"index": "",
"title": "Book Lava Title",
"productType": "Book"
},
{
"index": "",
"title": "Book Lava title",
"productType": "Book"
},
{
"index": "",
"title": "Book Lava Title",
"productType": "Book"
},
{
"index": "",
"title": "Book Lava title",
"productType": "Book"
},
{
"index": "",
"title": "Book Lava Title",
"productType": "Book"
},
{
"index": "",
"title": "Book Lava title",
"productType": "Book"
},
{
"index": "",
"title": "Book Lava Title",
"productType": "Book"
}
]
}

If you are using custom search form with custom java script and CSS, the auto completion data can be retrieved through the below JSONP URL

https://content.atomz.com/autocomplete/spxx/xx/xx/xx/?callback=jQuery35109061281263500554_1594919810495&query=tit&max_results=7&beginning=1&ignore_apostrophes=1

beginning=0, matches the query data anywhere in the auto completion data

spxx/xx/xx/xx/ — Split the account number to this specific pattern

Stage URL — https://content.atomz.com/autocomplete/spxx/xx/xx/xx-stage/?callback=jQuery35109061281263500554_1594919810495&query=java&max_results=7&beginning=0&ignore_apostrophes=1

<html>
<head>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<head>
<body>
<script>
var accountno='spxxxxxxxx';
var splitan = accountno.substring(0, 4) + "/" + accountno.substring(4, 6) + "/" + accountno.substring(6, 8) + "/" + accountno.substring(8) + "/";
var url = "https://content.atomz.com/autocomplete/" + splitan;
var query = 'tit';
var max_results = 7;
var beginning = 1;
$.ajax({
url : url,
data : {query: query, max_results: max_results, beginning: beginning},
dataType : 'jsonp',
success : function(data){
if(data.length){
alert(data);
$.each(data, function(i, field){
//add the individual data to the auto completion div
});
}else{

}
}
});
</script>
</body>
<html>
Image for post

The Auto-completion can be used in the search form to recommends the search terms based on the word user beginning to type.